From 923696f324d8b9fd040bfc8028bece894ff9ef9b Mon Sep 17 00:00:00 2001 From: tkymmm <136296842+tkymmm@users.noreply.github.com> Date: Fri, 25 Apr 2025 22:06:04 +0900 Subject: [PATCH 1/5] Update messages_ja_JP.properties (#3417) # Description of Changes Please provide a summary of the changes, including: - What was changed - Why the change was made - Any challenges encountered Closes #(issue_number) --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing) for more details. --- src/main/resources/messages_ja_JP.properties | 144 +++++++++---------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/src/main/resources/messages_ja_JP.properties b/src/main/resources/messages_ja_JP.properties index 0c75570b6..6cff67330 100644 --- a/src/main/resources/messages_ja_JP.properties +++ b/src/main/resources/messages_ja_JP.properties @@ -10,9 +10,9 @@ multiPdfPrompt=PDFを選択 (2つ以上) multiPdfDropPrompt=PDFを選択 (又はドラッグ&ドロップ) imgPrompt=画像を選択 genericSubmit=送信 -uploadLimit=Maximum file size: -uploadLimitExceededSingular=is too large. Maximum allowed size is -uploadLimitExceededPlural=are too large. Maximum allowed size is +uploadLimit=最大ファイルサイズ: +uploadLimitExceededSingular=のサイズが大きすぎます。許可された最大サイズは +uploadLimitExceededPlural=のサイズが大きすぎます。許可された最大サイズは processTimeWarning=警告:この処理はファイルサイズによって1分程度かかることがあります pageOrderPrompt=ページ順序 (ページ番号をカンマ区切り又は2n+1のような関数で入力): pageSelectionPrompt=カスタムページ選択(ページ番号1、5、6または2n + 1などの関数のコンマ区切りリストを入力します): @@ -78,14 +78,14 @@ visitGithub=Githubリポジトリを訪問する donate=寄付する color=色 sponsor=スポンサー -info=Info -pro=pro +info=情報 +pro=Pro page=ページ pages=ページ loading=読込中... addToDoc=ドキュメントに追加 reset=リセット -apply=Apply +apply=適用 noFileSelected=No file selected. Please upload one. legal.privacy=プライバシーポリシー @@ -237,31 +237,31 @@ adminUserSettings.activeUsers=アクティブユーザー: adminUserSettings.disabledUsers=無効なユーザー: adminUserSettings.totalUsers=ユーザー合計: adminUserSettings.lastRequest=最後のリクエスト -adminUserSettings.usage=View Usage +adminUserSettings.usage=使用状況を表示 -endpointStatistics.title=Endpoint Statistics -endpointStatistics.header=Endpoint Statistics -endpointStatistics.top10=Top 10 -endpointStatistics.top20=Top 20 -endpointStatistics.all=All -endpointStatistics.refresh=Refresh -endpointStatistics.includeHomepage=Include Homepage ('/') -endpointStatistics.includeLoginPage=Include Login Page ('/login') -endpointStatistics.totalEndpoints=Total Endpoints -endpointStatistics.totalVisits=Total Visits -endpointStatistics.showing=Showing -endpointStatistics.selectedVisits=Selected Visits -endpointStatistics.endpoint=Endpoint -endpointStatistics.visits=Visits -endpointStatistics.percentage=Percentage -endpointStatistics.loading=Loading... -endpointStatistics.failedToLoad=Failed to load endpoint data. Please try refreshing. -endpointStatistics.home=Home -endpointStatistics.login=Login -endpointStatistics.top=Top -endpointStatistics.numberOfVisits=Number of Visits -endpointStatistics.visitsTooltip=Visits: {0} ({1}% of total) -endpointStatistics.retry=Retry +endpointStatistics.title=エンドポイント統計 +endpointStatistics.header=エンドポイント統計 +endpointStatistics.top10=トップ10 +endpointStatistics.top20=トップ20 +endpointStatistics.all=すべて +endpointStatistics.refresh=更新 +endpointStatistics.includeHomepage=ホームページを含める ('/') +endpointStatistics.includeLoginPage=ログインページを含める ('/login') +endpointStatistics.totalEndpoints=エンドポイント合計 +endpointStatistics.totalVisits=総訪問数 +endpointStatistics.showing=表示 +endpointStatistics.selectedVisits=選択された訪問先 +endpointStatistics.endpoint=エンドポイント +endpointStatistics.visits=訪問 +endpointStatistics.percentage=比率 +endpointStatistics.loading=読込中... +endpointStatistics.failedToLoad=エンドポイントデータのロードに失敗しました。更新してみてください。 +endpointStatistics.home=ホーム +endpointStatistics.login=ログイン +endpointStatistics.top=トップ +endpointStatistics.numberOfVisits=訪問回数 +endpointStatistics.visitsTooltip=訪問数: {0} (合計の{1}%) +endpointStatistics.retry=再試行 database.title=データベースのインポート/エクスポート database.header=データベースのインポート/エクスポート @@ -292,7 +292,7 @@ home.desc=PDFのあらゆるニーズに対応するローカルホスティン home.searchBar=機能検索... -home.viewPdf.title=View/Edit PDF +home.viewPdf.title=PDFの表示/編集 home.viewPdf.desc=表示、注釈、テキストや画像の追加 viewPdf.tags=view,read,annotate,text,image @@ -307,7 +307,7 @@ home.sortBy=ソート順: home.multiTool.title=PDFマルチツール home.multiTool.desc=ページの結合、回転、並べ替え、削除します。 -multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side,interactive,intractable,move +multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side,interactive,intractable,move,delete,migrate,divide home.merge.title=結合 home.merge.desc=複数のPDFを1つに結合します。 @@ -515,12 +515,12 @@ home.showJS.title=JavaScriptを表示 home.showJS.desc=PDFに挿入されたJavaScriptを検索して表示します。 showJS.tags=JS -home.autoRedact.title=自動塗りつぶし -home.autoRedact.desc=入力したテキストに基づいてPDF内のテキストを自動で塗りつぶし(黒塗り)ます。 +home.autoRedact.title=自動墨消し +home.autoRedact.desc=入力したテキストに基づいてPDF内のテキストを自動で墨消し(黒塗り)ます。 autoRedact.tags=Redact,Hide,black out,black,marker,hidden -home.redact.title=手動塗りつぶし -home.redact.desc=選択したテキスト、描画した図形、選択したページに基づいてPDFを塗りつぶします。 +home.redact.title=手動墨消し +home.redact.desc=選択したテキスト、描画した図形、選択したページに基づいてPDFを墨消します。 redact.tags=Redact,Hide,black out,black,marker,hidden,manual home.tableExtraxt.title=PDFをCSVに変換 @@ -609,30 +609,30 @@ login.alreadyLoggedIn2=デバイスからログアウトしてもう一度お試 login.toManySessions=アクティブなセッションが多すぎます #auto-redact -autoRedact.title=自動塗りつぶし -autoRedact.header=自動塗りつぶし +autoRedact.title=自動墨消し +autoRedact.header=自動墨消し autoRedact.colorLabel=カラー autoRedact.textsToRedactLabel=編集するテキスト(行区切り) autoRedact.textsToRedactPlaceholder=例: \n機密 \n極秘 autoRedact.useRegexLabel=正規表現を使用する autoRedact.wholeWordSearchLabel=単語単位の検索 autoRedact.customPaddingLabel=追加の余白 -autoRedact.convertPDFToImageLabel=PDFをPDF画像に変換 (塗りつぶしの後ろのテキストを削除するために使用) +autoRedact.convertPDFToImageLabel=PDFをPDF画像に変換 (墨消しの後ろのテキストを削除するために使用) autoRedact.submitButton=送信 #redact -redact.title=手動編集 -redact.header=手動編集 +redact.title=手動墨消し +redact.header=手動墨消し redact.submit=編集 -redact.textBasedRedaction=テキストベースの編集 -redact.pageBasedRedaction=ページベースの編集 +redact.textBasedRedaction=テキストベースの墨消し +redact.pageBasedRedaction=ページベースの墨消し redact.convertPDFToImageLabel=PDFをPDF画像に変換します (ボックスの背後のテキストを削除するために使用します) redact.pageRedactionNumbers.title=ページ redact.pageRedactionNumbers.placeholder=(例:1,2,8、4,7,12-16、2n-1) redact.redactionColor.title=編集色 redact.export=出力 redact.upload=アップロード -redact.boxRedaction=ボックス描画編集 +redact.boxRedaction=ボックス描画の墨消し redact.zoom=ズーム redact.zoomIn=拡大 redact.zoomOut=縮小 @@ -739,10 +739,10 @@ sanitizePDF.title=PDFをサニタイズ sanitizePDF.header=PDFファイルをサニタイズ sanitizePDF.selectText.1=JavaScriptアクションを削除 sanitizePDF.selectText.2=埋め込みファイルを削除 -sanitizePDF.selectText.3=Remove XMP metadata +sanitizePDF.selectText.3=XMPメタデータを削除 sanitizePDF.selectText.4=リンクを削除 sanitizePDF.selectText.5=フォントを削除 -sanitizePDF.selectText.6=Remove Document Info Metadata +sanitizePDF.selectText.6=ドキュメント情報のメタデータを削除 sanitizePDF.submit=PDFをサニタイズする @@ -891,8 +891,8 @@ sign.last=最後のページ sign.next=次のページ sign.previous=前のページ sign.maintainRatio=アスペクト比を維持を切替え -sign.undo=Undo -sign.redo=Redo +sign.undo=元に戻す +sign.redo=やり直す #repair repair.title=修復 @@ -963,8 +963,8 @@ compress.title=圧縮 compress.header=PDFを圧縮 compress.credit=本サービスはPDFの圧縮/最適化にqpdfを使用しています。 compress.grayscale.label=圧縮にグレースケールを適用する -compress.selectText.1=Compression Settings -compress.selectText.1.1=1-3 PDF compression,
4-6 lite image compression,
7-9 intense image compression Will dramatically reduce image quality +compress.selectText.1=圧縮設定 +compress.selectText.1.1=1-3 PDF圧縮、
4-6 弱い画像圧縮、
7-9 強い画像圧縮により画質が大幅に低下します compress.selectText.2=品質レベル: compress.selectText.4=自動モード - PDFを正確なサイズにするために品質を自動調整する。 compress.selectText.5=PDFサイズ (例:25MB, 10.8MB, 25KB) @@ -1003,7 +1003,7 @@ pdfOrganiser.mode.7=最初に削除 pdfOrganiser.mode.8=最後を削除 pdfOrganiser.mode.9=最初と最後を削除 pdfOrganiser.mode.10=奇数-偶数の結合 -pdfOrganiser.mode.11=Duplicate all pages +pdfOrganiser.mode.11=すべてのページを複製 pdfOrganiser.placeholder=(例:1,3,2または4-8,2,10-12または2n-1) @@ -1408,25 +1408,25 @@ validateSignature.cert.bits=ビット #################### # Cookie banner # #################### -cookieBanner.popUp.title=How we use Cookies -cookieBanner.popUp.description.1=We use cookies and other technologies to make Stirling PDF work better for you—helping us improve our tools and keep building features you'll love. -cookieBanner.popUp.description.2=If you’d rather not, clicking 'No Thanks' will only enable the essential cookies needed to keep things running smoothly. -cookieBanner.popUp.acceptAllBtn=Okay -cookieBanner.popUp.acceptNecessaryBtn=No Thanks -cookieBanner.popUp.showPreferencesBtn=Manage preferences -cookieBanner.preferencesModal.title=Consent Preferences Center -cookieBanner.preferencesModal.acceptAllBtn=Accept all -cookieBanner.preferencesModal.acceptNecessaryBtn=Reject all -cookieBanner.preferencesModal.savePreferencesBtn=Save preferences -cookieBanner.preferencesModal.closeIconLabel=Close modal -cookieBanner.preferencesModal.serviceCounterLabel=Service|Services -cookieBanner.preferencesModal.subtitle=Cookie Usage -cookieBanner.preferencesModal.description.1=Stirling PDF uses cookies and similar technologies to enhance your experience and understand how our tools are used. This helps us improve performance, develop the features you care about, and provide ongoing support to our users. -cookieBanner.preferencesModal.description.2=Stirling PDF cannot—and will never—track or access the content of the documents you use. -cookieBanner.preferencesModal.description.3=Your privacy and trust are at the core of what we do. -cookieBanner.preferencesModal.necessary.title.1=Strictly Necessary Cookies -cookieBanner.preferencesModal.necessary.title.2=Always Enabled -cookieBanner.preferencesModal.necessary.description=These cookies are essential for the website to function properly. They enable core features like setting your privacy preferences, logging in, and filling out forms—which is why they can’t be turned off. -cookieBanner.preferencesModal.analytics.title=Analytics -cookieBanner.preferencesModal.analytics.description=These cookies help us understand how our tools are being used, so we can focus on building the features our community values most. Rest assured—Stirling PDF cannot and will never track the content of the documents you work with. +cookieBanner.popUp.title=クッキーの使用方法 +cookieBanner.popUp.description.1=私たちはStirling PDFをより快適にご利用いただけるようCookieやその他のテクノロジーを使用しています。これによりツールの改善やお気に入りの機能の構築を継続できます。 +cookieBanner.popUp.description.2=希望しない場合は「いいえ」をクリックすると、スムーズに動作するために必要なCookieのみが有効になります。 +cookieBanner.popUp.acceptAllBtn=Ok +cookieBanner.popUp.acceptNecessaryBtn=いいえ +cookieBanner.popUp.showPreferencesBtn=設定の管理 +cookieBanner.preferencesModal.title=同意管理センター +cookieBanner.preferencesModal.acceptAllBtn=すべて受け入れる +cookieBanner.preferencesModal.acceptNecessaryBtn=すべて拒否する +cookieBanner.preferencesModal.savePreferencesBtn=環境設定の保存 +cookieBanner.preferencesModal.closeIconLabel=モーダルを閉じる +cookieBanner.preferencesModal.serviceCounterLabel=サービス +cookieBanner.preferencesModal.subtitle=Cookieの使用 +cookieBanner.preferencesModal.description.1=Stirling PDFはお客様の体験の向上、ツールの利用状況を把握するためにCookieなどのテクノロジーを使用しています。これによりパフォーマンスの向上、お客様が求める機能の開発、そしてユーザーへの継続的なサポートの提供が可能になります。 +cookieBanner.preferencesModal.description.2=Stirling PDFはユーザーが使用するドキュメントの内容を追跡したりアクセスしたりすることはできません。 +cookieBanner.preferencesModal.description.3=お客様のプライバシーと信頼は当社の活動の中核です。 +cookieBanner.preferencesModal.necessary.title.1=厳密に必要なCookie +cookieBanner.preferencesModal.necessary.title.2=常に有効 +cookieBanner.preferencesModal.necessary.description=これらのCookieはウェブサイトが正常に機能するために不可欠です。プライバシー設定、ログイン、フォームへの入力といったコア機能を有効にするため、無効にすることはできません。 +cookieBanner.preferencesModal.analytics.title=分析 +cookieBanner.preferencesModal.analytics.description=これらのCookieはツールがどのように使用されているかを把握するのに役立ちます。これによりコミュニティが最も重視する機能の開発に集中することができます。ご安心ください。Stirling PDFはお客様が操作するドキュメントの内容を追跡することは決してありません。 From ec88a272bee82b431136c78eb093832e01ce29c7 Mon Sep 17 00:00:00 2001 From: Ludy Date: Fri, 25 Apr 2025 15:06:21 +0200 Subject: [PATCH 2/5] Update German properties (#3416) # Description of Changes Please provide a summary of the changes, including: - What was changed - Why the change was made - Any challenges encountered Closes #(issue_number) --- ## Checklist ### General - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [x] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md) (if applicable) - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing) for more details. --- scripts/ignore_translation.toml | 3 + src/main/resources/messages_de_DE.properties | 110 +++++++++---------- 2 files changed, 58 insertions(+), 55 deletions(-) diff --git a/scripts/ignore_translation.toml b/scripts/ignore_translation.toml index 521f3c54c..12f3bc7a4 100644 --- a/scripts/ignore_translation.toml +++ b/scripts/ignore_translation.toml @@ -56,6 +56,9 @@ ignore = [ 'validateSignature.cert.version', 'validateSignature.status', 'watermark.type.1', + 'endpointStatistics.top10', + 'endpointStatistics.top20', + 'cookieBanner.popUp.acceptAllBtn', ] [el_GR] diff --git a/src/main/resources/messages_de_DE.properties b/src/main/resources/messages_de_DE.properties index dfe973fb2..3bb563f6f 100644 --- a/src/main/resources/messages_de_DE.properties +++ b/src/main/resources/messages_de_DE.properties @@ -10,9 +10,9 @@ multiPdfPrompt=PDFs auswählen(2+) multiPdfDropPrompt=Wählen Sie alle gewünschten PDFs aus (oder ziehen Sie sie per Drag & Drop hierhin) imgPrompt=Wählen Sie ein Bild genericSubmit=Absenden -uploadLimit=Maximum file size: -uploadLimitExceededSingular=is too large. Maximum allowed size is -uploadLimitExceededPlural=are too large. Maximum allowed size is +uploadLimit=Maximale Dateigröße: +uploadLimitExceededSingular=ist zu groß. Die maximal zulässige Größe ist +uploadLimitExceededPlural=sind zu groß. Die maximal zulässige Größe ist processTimeWarning=Achtung: Abhängig von der Dateigröße kann dieser Prozess bis zu einer Minute dauern pageOrderPrompt=Seitenreihenfolge (Geben Sie eine durch Komma getrennte Liste von Seitenzahlen ein): pageSelectionPrompt=Benutzerdefinierte Seitenauswahl (Geben Sie eine durch Kommas getrennte Liste von Seitenzahlen 1,5,6 oder Funktionen wie 2n+1 ein): @@ -86,14 +86,14 @@ loading=Laden... addToDoc=In Dokument hinzufügen reset=Zurücksetzen apply=Anwenden -noFileSelected=No file selected. Please upload one. +noFileSelected=Keine Datei ausgewählt. Bitte laden Sie eine hoch. legal.privacy=Datenschutz legal.terms=AGB legal.accessibility=Barrierefreiheit legal.cookie=Cookie-Richtlinie legal.impressum=Impressum -legal.showCookieBanner=Cookie Preferences +legal.showCookieBanner=Cookie Einstellungen ############### # Pipeline # @@ -237,31 +237,31 @@ adminUserSettings.activeUsers=Aktive Benutzer: adminUserSettings.disabledUsers=Deaktivierte Benutzer: adminUserSettings.totalUsers=Gesamtzahl der Benutzer: adminUserSettings.lastRequest=Letzte Anfrage -adminUserSettings.usage=View Usage +adminUserSettings.usage=Statistiken -endpointStatistics.title=Endpoint Statistics -endpointStatistics.header=Endpoint Statistics +endpointStatistics.title=Endpunktstatistik +endpointStatistics.header=Endpunktstatistik endpointStatistics.top10=Top 10 endpointStatistics.top20=Top 20 -endpointStatistics.all=All -endpointStatistics.refresh=Refresh -endpointStatistics.includeHomepage=Include Homepage ('/') -endpointStatistics.includeLoginPage=Include Login Page ('/login') -endpointStatistics.totalEndpoints=Total Endpoints -endpointStatistics.totalVisits=Total Visits -endpointStatistics.showing=Showing -endpointStatistics.selectedVisits=Selected Visits -endpointStatistics.endpoint=Endpoint -endpointStatistics.visits=Visits -endpointStatistics.percentage=Percentage -endpointStatistics.loading=Loading... -endpointStatistics.failedToLoad=Failed to load endpoint data. Please try refreshing. -endpointStatistics.home=Home -endpointStatistics.login=Login -endpointStatistics.top=Top -endpointStatistics.numberOfVisits=Number of Visits -endpointStatistics.visitsTooltip=Visits: {0} ({1}% of total) -endpointStatistics.retry=Retry +endpointStatistics.all=Alle +endpointStatistics.refresh=Aktualisieren +endpointStatistics.includeHomepage=Startseite ('/') einschließen +endpointStatistics.includeLoginPage=Anmeldeseite einschließen ('/login') +endpointStatistics.totalEndpoints=Gesamtendpunkte +endpointStatistics.totalVisits=Gesamtbesuche +endpointStatistics.showing=Zeigen +endpointStatistics.selectedVisits=Ausgewählte Besuche +endpointStatistics.endpoint=Endpunkt +endpointStatistics.visits=Besuche +endpointStatistics.percentage=Prozentsatz +endpointStatistics.loading=Laden... +endpointStatistics.failedToLoad=Endpunktdaten nicht geladen, bitte aktualisieren Sie die Seite. +endpointStatistics.home=Startseite +endpointStatistics.login=Anmeldeseite +endpointStatistics.top=Spitze +endpointStatistics.numberOfVisits=Anzahl der Besuche +endpointStatistics.visitsTooltip=Besuche: {0} ({1}% des Gesamten) +endpointStatistics.retry=Wiederholen database.title=Datenbank Import/Export database.header=Datenbank Import/Export @@ -739,10 +739,10 @@ sanitizePDF.title=PDF Bereinigen sanitizePDF.header=PDF Bereinigen sanitizePDF.selectText.1=Javascript-Aktionen entfernen sanitizePDF.selectText.2=Eingebettete Dateien entfernen -sanitizePDF.selectText.3=Remove XMP metadata +sanitizePDF.selectText.3=XMP-Metadaten entfernen sanitizePDF.selectText.4=Links entfernen sanitizePDF.selectText.5=Schriftarten entfernen -sanitizePDF.selectText.6=Remove Document Info Metadata +sanitizePDF.selectText.6=Dokumenten-Metadaten entfernen sanitizePDF.submit=Bereinigen @@ -891,8 +891,8 @@ sign.last=Letzte Seite sign.next=Nächste Seite sign.previous=Vorherige Seite sign.maintainRatio=Seitenverhältnis beibehalten ein-/ausschalten -sign.undo=Undo -sign.redo=Redo +sign.undo=Rückgängig +sign.redo=Wiederherstellen #repair repair.title=Reparieren @@ -963,8 +963,8 @@ compress.title=Komprimieren compress.header=PDF komprimieren compress.credit=Dieser Dienst verwendet qpdf für die PDF-Komprimierung/-Optimierung. compress.grayscale.label=Graustufen für Komprimierung anwenden -compress.selectText.1=Compression Settings -compress.selectText.1.1=1-3 PDF compression,
4-6 lite image compression,
7-9 intense image compression Will dramatically reduce image quality +compress.selectText.1=Kompressionseinstellungen +compress.selectText.1.1=1-3 PDF-Komprimierung,
4-6 Leichte Bildkomprimierung,
7-9 Intensive Bildkomprimierung verringert die Bildqualität dramatisch compress.selectText.2=Optimierungsstufe: compress.selectText.4=Automatischer Modus – Passt die Qualität automatisch an, um das PDF auf die exakte Größe zu bringen compress.selectText.5=Erwartete PDF-Größe (z.B. 25 MB, 10,8 MB, 25 KB) @@ -1003,7 +1003,7 @@ pdfOrganiser.mode.7=Erste entfernen pdfOrganiser.mode.8=Letzte entfernen pdfOrganiser.mode.9=Erste und letzte entfernen pdfOrganiser.mode.10=Ungerade-Gerade-Zusammenführung -pdfOrganiser.mode.11=Duplicate all pages +pdfOrganiser.mode.11=Alle Seiten duplizieren pdfOrganiser.placeholder=(z.B. 1,3,2 oder 4-8,2,10-12 oder 2n-1) @@ -1046,7 +1046,7 @@ decrypt.success=Datei erfolgreich entschlüsselt. multiTool-advert.message=Diese Funktion ist auch auf unserer PDF-Multitool-Seite verfügbar. Probieren Sie sie aus, denn sie bietet eine verbesserte Benutzeroberfläche und zusätzliche Funktionen! #view pdf -viewPdf.title=View/Edit PDF +viewPdf.title=PDF anzeigen/bearbeiten viewPdf.header=PDF anzeigen #pageRemover @@ -1408,25 +1408,25 @@ validateSignature.cert.bits=bits #################### # Cookie banner # #################### -cookieBanner.popUp.title=How we use Cookies -cookieBanner.popUp.description.1=We use cookies and other technologies to make Stirling PDF work better for you—helping us improve our tools and keep building features you'll love. -cookieBanner.popUp.description.2=If you’d rather not, clicking 'No Thanks' will only enable the essential cookies needed to keep things running smoothly. +cookieBanner.popUp.title=Wie wir Cookies verwenden +cookieBanner.popUp.description.1=Wir verwenden Cookies und andere Technologien, damit Stirling PDF für Sie besser funktioniert. Dies hilft uns dabei, unsere Tools zu verbessern und weiterhin Funktionen zu entwickeln, die Ihnen gefallen werden. +cookieBanner.popUp.description.2=Wenn Sie dies nicht möchten, klicken Sie auf „Nein, Danke“. Dadurch werden nur die unbedingt erforderlichen Cookies aktiviert, die für einen reibungslosen Ablauf erforderlich sind. cookieBanner.popUp.acceptAllBtn=Okay -cookieBanner.popUp.acceptNecessaryBtn=No Thanks -cookieBanner.popUp.showPreferencesBtn=Manage preferences -cookieBanner.preferencesModal.title=Consent Preferences Center -cookieBanner.preferencesModal.acceptAllBtn=Accept all -cookieBanner.preferencesModal.acceptNecessaryBtn=Reject all -cookieBanner.preferencesModal.savePreferencesBtn=Save preferences -cookieBanner.preferencesModal.closeIconLabel=Close modal -cookieBanner.preferencesModal.serviceCounterLabel=Service|Services -cookieBanner.preferencesModal.subtitle=Cookie Usage -cookieBanner.preferencesModal.description.1=Stirling PDF uses cookies and similar technologies to enhance your experience and understand how our tools are used. This helps us improve performance, develop the features you care about, and provide ongoing support to our users. -cookieBanner.preferencesModal.description.2=Stirling PDF cannot—and will never—track or access the content of the documents you use. -cookieBanner.preferencesModal.description.3=Your privacy and trust are at the core of what we do. -cookieBanner.preferencesModal.necessary.title.1=Strictly Necessary Cookies -cookieBanner.preferencesModal.necessary.title.2=Always Enabled -cookieBanner.preferencesModal.necessary.description=These cookies are essential for the website to function properly. They enable core features like setting your privacy preferences, logging in, and filling out forms—which is why they can’t be turned off. -cookieBanner.preferencesModal.analytics.title=Analytics -cookieBanner.preferencesModal.analytics.description=These cookies help us understand how our tools are being used, so we can focus on building the features our community values most. Rest assured—Stirling PDF cannot and will never track the content of the documents you work with. +cookieBanner.popUp.acceptNecessaryBtn=Nein Danke +cookieBanner.popUp.showPreferencesBtn=Einstellungen verwalten +cookieBanner.preferencesModal.title=Einwilligungszentrum +cookieBanner.preferencesModal.acceptAllBtn=Akzeptiere alle +cookieBanner.preferencesModal.acceptNecessaryBtn=Alle ablehnen +cookieBanner.preferencesModal.savePreferencesBtn=Einstellungen speichern +cookieBanner.preferencesModal.closeIconLabel=Anzeige schließen +cookieBanner.preferencesModal.serviceCounterLabel=Service | Dienstleistungen +cookieBanner.preferencesModal.subtitle=Cookie-Nutzung +cookieBanner.preferencesModal.description.1=Stirling PDF verwendet Cookies und ähnliche Technologien, um Ihr Erlebnis zu verbessern und den Einsatz unserer Tools zu verstehen. Dies hilft uns, die Leistung zu verbessern, die für Sie wichtigen Funktionen zu entwickeln und unseren Nutzern kontinuierlichen Support zu bieten. +cookieBanner.preferencesModal.description.2=Stirling PDF kann und wird niemals den Inhalt der von Ihnen verwendeten Dokumente verfolgen oder darauf zugreifen. +cookieBanner.preferencesModal.description.3=Ihre Privatsphäre und Ihr Vertrauen stehen bei uns im Mittelpunkt. +cookieBanner.preferencesModal.necessary.title.1=Streng notwendige Cookies +cookieBanner.preferencesModal.necessary.title.2=Immer aktiviert +cookieBanner.preferencesModal.necessary.description=Diese Cookies sind für das ordnungsgemäße Funktionieren der Website unerlässlich. Sie ermöglichen grundlegende Funktionen wie das Festlegen Ihrer Datenschutzeinstellungen, das Anmelden und das Ausfüllen von Formularen. Daher können sie nicht deaktiviert werden. +cookieBanner.preferencesModal.analytics.title=Analyse +cookieBanner.preferencesModal.analytics.description=Diese Cookies helfen uns zu verstehen, wie unsere Tools genutzt werden, damit wir uns darauf konzentrieren können, die Funktionen zu entwickeln, die unserer Community am meisten am Herzen liegen. Seien Sie beruhigt – Stirling PDF kann und wird niemals den Inhalt der Dokumente verfolgen, mit denen Sie arbeiten. From 5f8b208db407fa1abcde0a0d7b0fa5b08d9390d1 Mon Sep 17 00:00:00 2001 From: Ludy Date: Fri, 25 Apr 2025 15:35:12 +0200 Subject: [PATCH 3/5] Refactor codebase to replace explicit constructors with Lombok annotations and remove boilerplat (#3415) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description of Changes - **What was changed:** - Removed explicit constructor definitions annotated with `@Autowired` across services, controllers, filters, and schedulers. - Added Lombok’s `@RequiredArgsConstructor` to automatically generate required-args constructors and eliminate boilerplate. - Introduced other Lombok annotations (`@Data`, `@Getter`, `@Setter`, `@EqualsAndHashCode`, `@NoArgsConstructor`) on model and API classes to replace manual getters/setters and constructors. - Standardized string comparisons to use the constant-first form (e.g., `"value".equals(variable)`). - Cleaned up unused imports and organized OpenAPI configuration by extracting default title/description constants. - **Why the change was made:** - To reduce repetitive boilerplate code and improve maintainability. - To leverage Lombok for cleaner, more consistent dependency injection and data modeling. - To ensure a uniform coding style across the entire codebase. #3406 --- ## Checklist ### General - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md) (if applicable) - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing) for more details. --- .../SPDF/EE/KeygenLicenseVerifier.java | 85 +++++++++---------- .../software/SPDF/EE/LicenseKeyChecker.java | 2 - .../software/SPDF/config/AppConfig.java | 8 +- .../SPDF/config/EndpointConfiguration.java | 2 - .../SPDF/config/EndpointInspector.java | 9 +- .../SPDF/config/EndpointInterceptor.java | 6 +- .../software/SPDF/config/InitialSetup.java | 6 +- .../SPDF/config/LocaleConfiguration.java | 9 +- .../software/SPDF/config/MetricsFilter.java | 9 +- .../software/SPDF/config/OpenApiConfig.java | 30 ++++--- .../software/SPDF/config/WebMvcConfig.java | 7 +- .../config/security/AppUpdateAuthService.java | 11 +-- .../security/CustomLogoutSuccessHandler.java | 4 +- .../security/CustomUserDetailsService.java | 9 +- .../config/security/IPRateLimitingFilter.java | 8 +- .../config/security/InitialSecuritySetup.java | 11 +-- .../config/security/LoginAttemptService.java | 6 +- .../security/RateLimitResetScheduler.java | 7 +- .../SPDF/config/security/UserService.java | 19 +---- .../security/database/ScheduledTasks.java | 7 +- ...tomOAuth2AuthenticationSuccessHandler.java | 12 +-- ...mSaml2ResponseAuthenticationConverter.java | 6 +- .../security/saml2/SAML2Configuration.java | 6 +- .../session/CustomHttpSessionListener.java | 2 - .../session/SessionPersistentRegistry.java | 7 +- .../security/session/SessionScheduled.java | 7 +- .../api/AdditionalLanguageJsController.java | 7 +- .../controller/api/AnalysisController.java | 9 +- .../SPDF/controller/api/CropController.java | 9 +- .../controller/api/DatabaseController.java | 6 +- .../SPDF/controller/api/MergeController.java | 8 +- .../api/MultiPageLayoutController.java | 9 +- .../api/PdfImageRemovalController.java | 17 +--- .../controller/api/PdfOverlayController.java | 9 +- .../api/RearrangePagesPDFController.java | 8 +- .../controller/api/RotationController.java | 9 +- .../controller/api/ScalePagesController.java | 9 +- .../controller/api/SettingsController.java | 10 +-- .../controller/api/SplitPDFController.java | 8 +- .../api/SplitPdfByChaptersController.java | 10 +-- .../api/SplitPdfBySectionsController.java | 9 +- .../api/SplitPdfBySizeController.java | 8 +- .../api/ToSinglePageController.java | 9 +- .../SPDF/controller/api/UserController.java | 11 +-- .../api/converters/ConvertHtmlToPDF.java | 15 +--- .../converters/ConvertImgPDFController.java | 8 +- .../api/converters/ConvertMarkdownToPdf.java | 15 +--- .../converters/ConvertOfficeController.java | 11 +-- .../api/converters/ConvertPDFToOffice.java | 9 +- .../api/converters/ConvertWebsiteToPDF.java | 13 +-- .../api/converters/ExtractCSVController.java | 8 +- .../api/filters/FilterController.java | 9 +- .../api/misc/AutoRenameController.java | 10 +-- .../api/misc/AutoSplitPdfController.java | 8 +- .../api/misc/BlankPageController.java | 8 +- .../api/misc/DecompressPdfController.java | 8 +- .../api/misc/ExtractImageScansController.java | 8 +- .../api/misc/ExtractImagesController.java | 8 +- .../api/misc/FlattenController.java | 8 +- .../api/misc/MetadataController.java | 8 +- .../controller/api/misc/OCRController.java | 11 +-- .../api/misc/OverlayImageController.java | 8 +- .../api/misc/PageNumbersController.java | 9 +- .../controller/api/misc/RepairController.java | 9 +- .../misc/ReplaceAndInvertColorController.java | 10 +-- .../controller/api/misc/ShowJavascript.java | 9 +- .../controller/api/misc/StampController.java | 9 +- .../api/pipeline/PipelineController.java | 9 +- .../api/security/CertSignController.java | 8 +- .../controller/api/security/GetInfoOnPDF.java | 8 +- .../api/security/PasswordController.java | 9 +- .../api/security/RedactController.java | 8 +- .../security/RemoveCertSignController.java | 9 +- .../api/security/SanitizeController.java | 9 +- .../security/ValidateSignatureController.java | 12 +-- .../api/security/WatermarkController.java | 9 +- .../controller/web/DatabaseWebController.java | 7 +- .../controller/web/HomeWebController.java | 6 +- .../controller/web/MetricsController.java | 11 +-- .../controller/web/OtherWebController.java | 9 +- .../software/SPDF/model/ApiEndpoint.java | 4 +- .../software/SPDF/model/Authority.java | 38 +++------ .../software/SPDF/model/PersistentLogin.java | 37 +------- .../software/SPDF/model/PipelineConfig.java | 35 +------- .../SPDF/model/PipelineOperation.java | 24 +----- .../stirling/software/SPDF/model/Role.java | 28 ++---- .../stirling/software/SPDF/model/User.java | 75 +++------------- .../software/SPDF/model/api/GeneralFile.java | 2 - .../SPDF/model/api/HandleDataRequest.java | 2 - .../software/SPDF/model/api/ImageFile.java | 2 - .../SPDF/model/api/MultiplePDFFiles.java | 2 - .../SPDF/model/api/PDFComparison.java | 2 - .../SPDF/model/api/PDFComparisonAndCount.java | 2 - .../SPDF/model/api/PDFWithPageNums.java | 7 +- .../model/api/SplitPdfByChaptersRequest.java | 2 - .../model/api/SplitPdfBySectionsRequest.java | 2 - .../model/api/user/UpdateUserDetails.java | 2 - .../model/api/user/UpdateUserUsername.java | 2 - .../SPDF/model/api/user/Username.java | 2 - .../SPDF/model/api/user/UsernameAndPass.java | 2 - .../service/CustomPDFDocumentFactory.java | 6 +- .../service/MetricsAggregatorService.java | 14 +-- .../SPDF/service/PdfMetadataService.java | 1 - .../software/SPDF/service/PostHogService.java | 1 - .../misc/ReplaceAndInvertColorService.java | 9 +- .../software/SPDF/utils/FileMonitor.java | 2 - 106 files changed, 302 insertions(+), 796 deletions(-) diff --git a/src/main/java/stirling/software/SPDF/EE/KeygenLicenseVerifier.java b/src/main/java/stirling/software/SPDF/EE/KeygenLicenseVerifier.java index e4bd06312..473f5f385 100644 --- a/src/main/java/stirling/software/SPDF/EE/KeygenLicenseVerifier.java +++ b/src/main/java/stirling/software/SPDF/EE/KeygenLicenseVerifier.java @@ -9,7 +9,6 @@ import java.util.Base64; import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters; import org.bouncycastle.crypto.signers.Ed25519Signer; import org.bouncycastle.util.encoders.Hex; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.fasterxml.jackson.databind.JsonNode; @@ -17,6 +16,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.posthog.java.shaded.org.json.JSONException; import com.posthog.java.shaded.org.json.JSONObject; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.ApplicationProperties; @@ -24,6 +24,7 @@ import stirling.software.SPDF.utils.GeneralUtils; @Service @Slf4j +@RequiredArgsConstructor public class KeygenLicenseVerifier { enum License { @@ -47,40 +48,35 @@ public class KeygenLicenseVerifier { private static final ObjectMapper objectMapper = new ObjectMapper(); private final ApplicationProperties applicationProperties; - @Autowired - public KeygenLicenseVerifier(ApplicationProperties applicationProperties) { - this.applicationProperties = applicationProperties; - } - public License verifyLicense(String licenseKeyOrCert) { - License license; + License license; - if (isCertificateLicense(licenseKeyOrCert)) { - log.info("Detected certificate-based license. Processing..."); - boolean isValid = verifyCertificateLicense(licenseKeyOrCert); - if (isValid) { - license = isEnterpriseLicense ? License.ENTERPRISE : License.PRO; - } else { - license = License.NORMAL; - } - } else if (isJWTLicense(licenseKeyOrCert)) { - log.info("Detected JWT-style license key. Processing..."); - boolean isValid = verifyJWTLicense(licenseKeyOrCert); - if (isValid) { - license = isEnterpriseLicense ? License.ENTERPRISE : License.PRO; - } else { - license = License.NORMAL; - } - } else { - log.info("Detected standard license key. Processing..."); - boolean isValid = verifyStandardLicense(licenseKeyOrCert); - if (isValid) { - license = isEnterpriseLicense ? License.ENTERPRISE : License.PRO; - } else { - license = License.NORMAL; - } - } - return license; + if (isCertificateLicense(licenseKeyOrCert)) { + log.info("Detected certificate-based license. Processing..."); + boolean isValid = verifyCertificateLicense(licenseKeyOrCert); + if (isValid) { + license = isEnterpriseLicense ? License.ENTERPRISE : License.PRO; + } else { + license = License.NORMAL; + } + } else if (isJWTLicense(licenseKeyOrCert)) { + log.info("Detected JWT-style license key. Processing..."); + boolean isValid = verifyJWTLicense(licenseKeyOrCert); + if (isValid) { + license = isEnterpriseLicense ? License.ENTERPRISE : License.PRO; + } else { + license = License.NORMAL; + } + } else { + log.info("Detected standard license key. Processing..."); + boolean isValid = verifyStandardLicense(licenseKeyOrCert); + if (isValid) { + license = isEnterpriseLicense ? License.ENTERPRISE : License.PRO; + } else { + license = License.NORMAL; + } + } + return license; } private boolean isEnterpriseLicense = false; @@ -123,7 +119,7 @@ public class KeygenLicenseVerifier { } // Verify license file algorithm - if (!algorithm.equals("base64+ed25519")) { + if (!"base64+ed25519".equals(algorithm)) { log.error( "Unsupported algorithm: {}. Only base64+ed25519 is supported.", algorithm); return false; @@ -193,8 +189,6 @@ public class KeygenLicenseVerifier { private boolean processCertificateData(String certData) { try { - - JSONObject licenseData = new JSONObject(certData); JSONObject metaObj = licenseData.optJSONObject("meta"); if (metaObj != null) { @@ -208,7 +202,8 @@ public class KeygenLicenseVerifier { if (issued.isAfter(now)) { log.error( - "License file issued date is in the future. Please adjust system time or request a new license"); + "License file issued date is in the future. Please adjust system" + + " time or request a new license"); return false; } @@ -248,8 +243,8 @@ public class KeygenLicenseVerifier { // Check license status if available String status = attributesObj.optString("status", null); if (status != null - && !status.equals("ACTIVE") - && !status.equals("EXPIRING")) { // Accept "EXPIRING" status as valid + && !"ACTIVE".equals(status) + && !"EXPIRING".equals(status)) { // Accept "EXPIRING" status as valid log.error("License status is not active: {}", status); return false; } @@ -273,7 +268,8 @@ public class KeygenLicenseVerifier { String[] parts = licenseData.split("\\.", 2); if (parts.length != 2) { log.error( - "Invalid ED25519_SIGN license format. Expected format: key/payload.signature"); + "Invalid ED25519_SIGN license format. Expected format:" + + " key/payload.signature"); return false; } @@ -354,7 +350,7 @@ public class KeygenLicenseVerifier { // Check expiry date String expiryStr = licenseObj.optString("expiry", null); - if (expiryStr != null && !expiryStr.equals("null")) { + if (expiryStr != null && !"null".equals(expiryStr)) { java.time.Instant expiry = java.time.Instant.parse(expiryStr); java.time.Instant now = java.time.Instant.now(); @@ -397,8 +393,7 @@ public class KeygenLicenseVerifier { } else { // Try to get users from metadata if present Object metadataObj = policyObj.opt("metadata"); - if (metadataObj instanceof JSONObject) { - JSONObject metadata = (JSONObject) metadataObj; + if (metadataObj instanceof JSONObject metadata) { users = metadata.optInt("users", 1); applicationProperties.getPremium().setMaxUsers(users); log.info("License allows for {} users (from metadata)", users); @@ -411,7 +406,6 @@ public class KeygenLicenseVerifier { log.info("Using default of 1 user for license"); } } - } return true; @@ -438,7 +432,8 @@ public class KeygenLicenseVerifier { || "NO_MACHINES".equals(code) || "FINGERPRINT_SCOPE_MISMATCH".equals(code)) { log.info( - "License not activated for this machine. Attempting to activate..."); + "License not activated for this machine. Attempting to" + + " activate..."); boolean activated = activateMachine(licenseKey, licenseId, machineFingerprint); if (activated) { diff --git a/src/main/java/stirling/software/SPDF/EE/LicenseKeyChecker.java b/src/main/java/stirling/software/SPDF/EE/LicenseKeyChecker.java index d788504c5..8e5633f41 100644 --- a/src/main/java/stirling/software/SPDF/EE/LicenseKeyChecker.java +++ b/src/main/java/stirling/software/SPDF/EE/LicenseKeyChecker.java @@ -5,7 +5,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -27,7 +26,6 @@ public class LicenseKeyChecker { private License premiumEnabledResult = License.NORMAL; - @Autowired public LicenseKeyChecker( KeygenLicenseVerifier licenseService, ApplicationProperties applicationProperties) { this.licenseService = licenseService; diff --git a/src/main/java/stirling/software/SPDF/config/AppConfig.java b/src/main/java/stirling/software/SPDF/config/AppConfig.java index 1c850b2de..f07368527 100644 --- a/src/main/java/stirling/software/SPDF/config/AppConfig.java +++ b/src/main/java/stirling/software/SPDF/config/AppConfig.java @@ -20,8 +20,7 @@ import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.thymeleaf.spring6.SpringTemplateEngine; -import com.posthog.java.shaded.kotlin.text.Regex; - +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.ApplicationProperties; @@ -29,14 +28,11 @@ import stirling.software.SPDF.model.ApplicationProperties; @Configuration @Lazy @Slf4j +@RequiredArgsConstructor public class AppConfig { private final ApplicationProperties applicationProperties; - public AppConfig(ApplicationProperties applicationProperties) { - this.applicationProperties = applicationProperties; - } - @Bean @ConditionalOnProperty(name = "system.customHTMLFiles", havingValue = "true") public SpringTemplateEngine templateEngine(ResourceLoader resourceLoader) { diff --git a/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java b/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java index 08da2fa3c..2a89cc99f 100644 --- a/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java +++ b/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java @@ -6,7 +6,6 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; @@ -24,7 +23,6 @@ public class EndpointConfiguration { private Map> endpointGroups = new ConcurrentHashMap<>(); private final boolean runningProOrHigher; - @Autowired public EndpointConfiguration( ApplicationProperties applicationProperties, @Qualifier("runningProOrHigher") boolean runningProOrHigher) { diff --git a/src/main/java/stirling/software/SPDF/config/EndpointInspector.java b/src/main/java/stirling/software/SPDF/config/EndpointInspector.java index 6019ca665..d9ceb0f9d 100644 --- a/src/main/java/stirling/software/SPDF/config/EndpointInspector.java +++ b/src/main/java/stirling/software/SPDF/config/EndpointInspector.java @@ -8,7 +8,6 @@ import java.util.TreeSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; @@ -18,7 +17,10 @@ import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.mvc.method.RequestMappingInfo; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; +import lombok.RequiredArgsConstructor; + @Component +@RequiredArgsConstructor public class EndpointInspector implements ApplicationListener { private static final Logger logger = LoggerFactory.getLogger(EndpointInspector.class); @@ -26,11 +28,6 @@ public class EndpointInspector implements ApplicationListener validGetEndpoints = new HashSet<>(); private boolean endpointsDiscovered = false; - @Autowired - public EndpointInspector(ApplicationContext applicationContext) { - this.applicationContext = applicationContext; - } - @Override public void onApplicationEvent(ContextRefreshedEvent event) { if (!endpointsDiscovered) { diff --git a/src/main/java/stirling/software/SPDF/config/EndpointInterceptor.java b/src/main/java/stirling/software/SPDF/config/EndpointInterceptor.java index aa3fce4c7..52fb42e07 100644 --- a/src/main/java/stirling/software/SPDF/config/EndpointInterceptor.java +++ b/src/main/java/stirling/software/SPDF/config/EndpointInterceptor.java @@ -6,18 +6,16 @@ import org.springframework.web.servlet.HandlerInterceptor; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @Component @Slf4j +@RequiredArgsConstructor public class EndpointInterceptor implements HandlerInterceptor { private final EndpointConfiguration endpointConfiguration; - public EndpointInterceptor(EndpointConfiguration endpointConfiguration) { - this.endpointConfiguration = endpointConfiguration; - } - @Override public boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler) diff --git a/src/main/java/stirling/software/SPDF/config/InitialSetup.java b/src/main/java/stirling/software/SPDF/config/InitialSetup.java index 4c3131a1c..44de07d38 100644 --- a/src/main/java/stirling/software/SPDF/config/InitialSetup.java +++ b/src/main/java/stirling/software/SPDF/config/InitialSetup.java @@ -14,6 +14,7 @@ import io.micrometer.common.util.StringUtils; import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.ApplicationProperties; @@ -22,14 +23,11 @@ import stirling.software.SPDF.utils.GeneralUtils; @Component @Slf4j @Order(Ordered.HIGHEST_PRECEDENCE + 1) +@RequiredArgsConstructor public class InitialSetup { private final ApplicationProperties applicationProperties; - public InitialSetup(ApplicationProperties applicationProperties) { - this.applicationProperties = applicationProperties; - } - @PostConstruct public void init() throws IOException { initUUIDKey(); diff --git a/src/main/java/stirling/software/SPDF/config/LocaleConfiguration.java b/src/main/java/stirling/software/SPDF/config/LocaleConfiguration.java index 94c3392f9..ab37c3c5e 100644 --- a/src/main/java/stirling/software/SPDF/config/LocaleConfiguration.java +++ b/src/main/java/stirling/software/SPDF/config/LocaleConfiguration.java @@ -10,17 +10,16 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; import org.springframework.web.servlet.i18n.SessionLocaleResolver; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.ApplicationProperties; @Configuration +@RequiredArgsConstructor public class LocaleConfiguration implements WebMvcConfigurer { private final ApplicationProperties applicationProperties; - public LocaleConfiguration(ApplicationProperties applicationProperties) { - this.applicationProperties = applicationProperties; - } - @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(localeChangeInterceptor()); @@ -52,7 +51,7 @@ public class LocaleConfiguration implements WebMvcConfigurer { defaultLocale = tempLocale; } else { System.err.println( - "Invalid APP_LOCALE environment variable value. Falling back to default Locale.UK."); + "Invalid SYSTEM_DEFAULTLOCALE environment variable value. Falling back to default en-GB."); } } } diff --git a/src/main/java/stirling/software/SPDF/config/MetricsFilter.java b/src/main/java/stirling/software/SPDF/config/MetricsFilter.java index d187502c8..586374cbe 100644 --- a/src/main/java/stirling/software/SPDF/config/MetricsFilter.java +++ b/src/main/java/stirling/software/SPDF/config/MetricsFilter.java @@ -2,7 +2,6 @@ package stirling.software.SPDF.config; import java.io.IOException; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; @@ -15,18 +14,16 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.utils.RequestUriUtils; @Component +@RequiredArgsConstructor public class MetricsFilter extends OncePerRequestFilter { private final MeterRegistry meterRegistry; - @Autowired - public MetricsFilter(MeterRegistry meterRegistry) { - this.meterRegistry = meterRegistry; - } - @Override protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) diff --git a/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java b/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java index 0734b2317..d98c33257 100644 --- a/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java +++ b/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java @@ -9,16 +9,20 @@ import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.ApplicationProperties; @Configuration +@RequiredArgsConstructor public class OpenApiConfig { private final ApplicationProperties applicationProperties; - public OpenApiConfig(ApplicationProperties applicationProperties) { - this.applicationProperties = applicationProperties; - } + private static final String DEFAULT_TITLE = "Stirling PDF API"; + private static final String DEFAULT_DESCRIPTION = + "API documentation for all Server-Side processing.\n" + + "Please note some functionality might be UI only and missing from here."; @Bean public OpenAPI customOpenAPI() { @@ -27,29 +31,27 @@ public class OpenApiConfig { // default version if all else fails version = "1.0.0"; } - SecurityScheme apiKeyScheme = - new SecurityScheme() - .type(SecurityScheme.Type.APIKEY) - .in(SecurityScheme.In.HEADER) - .name("X-API-KEY"); if (!applicationProperties.getSecurity().getEnableLogin()) { return new OpenAPI() .components(new Components()) .info( new Info() - .title("Stirling PDF API") + .title(DEFAULT_TITLE) .version(version) - .description( - "API documentation for all Server-Side processing.\nPlease note some functionality might be UI only and missing from here.")); + .description(DEFAULT_DESCRIPTION)); } else { + SecurityScheme apiKeyScheme = + new SecurityScheme() + .type(SecurityScheme.Type.APIKEY) + .in(SecurityScheme.In.HEADER) + .name("X-API-KEY"); return new OpenAPI() .components(new Components().addSecuritySchemes("apiKey", apiKeyScheme)) .info( new Info() - .title("Stirling PDF API") + .title(DEFAULT_TITLE) .version(version) - .description( - "API documentation for all Server-Side processing.\nPlease note some functionality might be UI only and missing from here.")) + .description(DEFAULT_DESCRIPTION)) .addSecurityItem(new SecurityRequirement().addList("apiKey")); } } diff --git a/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java b/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java index 68d3fbbe4..63957fd0f 100644 --- a/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java +++ b/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java @@ -5,15 +5,14 @@ import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import lombok.RequiredArgsConstructor; + @Configuration +@RequiredArgsConstructor public class WebMvcConfig implements WebMvcConfigurer { private final EndpointInterceptor endpointInterceptor; - public WebMvcConfig(EndpointInterceptor endpointInterceptor) { - this.endpointInterceptor = endpointInterceptor; - } - @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(endpointInterceptor); diff --git a/src/main/java/stirling/software/SPDF/config/security/AppUpdateAuthService.java b/src/main/java/stirling/software/SPDF/config/security/AppUpdateAuthService.java index c8a133223..23ac9d761 100644 --- a/src/main/java/stirling/software/SPDF/config/security/AppUpdateAuthService.java +++ b/src/main/java/stirling/software/SPDF/config/security/AppUpdateAuthService.java @@ -6,24 +6,21 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.config.interfaces.ShowAdminInterface; import stirling.software.SPDF.model.ApplicationProperties; import stirling.software.SPDF.model.User; import stirling.software.SPDF.repository.UserRepository; @Service +@RequiredArgsConstructor class AppUpdateAuthService implements ShowAdminInterface { private final UserRepository userRepository; private final ApplicationProperties applicationProperties; - public AppUpdateAuthService( - UserRepository userRepository, ApplicationProperties applicationProperties) { - this.userRepository = userRepository; - this.applicationProperties = applicationProperties; - } - @Override public boolean getShowUpdateOnlyAdmins() { boolean showUpdate = applicationProperties.getSystem().isShowUpdate(); @@ -35,7 +32,7 @@ class AppUpdateAuthService implements ShowAdminInterface { if (authentication == null || !authentication.isAuthenticated()) { return !showUpdateOnlyAdmin; } - if (authentication.getName().equalsIgnoreCase("anonymousUser")) { + if ("anonymousUser".equalsIgnoreCase(authentication.getName())) { return !showUpdateOnlyAdmin; } Optional user = userRepository.findByUsername(authentication.getName()); diff --git a/src/main/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandler.java b/src/main/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandler.java index b570d625d..d59ba5d16 100644 --- a/src/main/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandler.java +++ b/src/main/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandler.java @@ -19,7 +19,7 @@ import com.coveo.saml.SamlException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.SPDFApplication; @@ -32,7 +32,7 @@ import stirling.software.SPDF.model.provider.KeycloakProvider; import stirling.software.SPDF.utils.UrlUtils; @Slf4j -@AllArgsConstructor +@RequiredArgsConstructor public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler { public static final String LOGOUT_PATH = "/login?logout=true"; diff --git a/src/main/java/stirling/software/SPDF/config/security/CustomUserDetailsService.java b/src/main/java/stirling/software/SPDF/config/security/CustomUserDetailsService.java index d0ee65f30..74c3fb9a4 100644 --- a/src/main/java/stirling/software/SPDF/config/security/CustomUserDetailsService.java +++ b/src/main/java/stirling/software/SPDF/config/security/CustomUserDetailsService.java @@ -11,23 +11,20 @@ import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.Authority; import stirling.software.SPDF.model.User; import stirling.software.SPDF.repository.UserRepository; @Service +@RequiredArgsConstructor public class CustomUserDetailsService implements UserDetailsService { private final UserRepository userRepository; private final LoginAttemptService loginAttemptService; - public CustomUserDetailsService( - UserRepository userRepository, LoginAttemptService loginAttemptService) { - this.userRepository = userRepository; - this.loginAttemptService = loginAttemptService; - } - @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = diff --git a/src/main/java/stirling/software/SPDF/config/security/IPRateLimitingFilter.java b/src/main/java/stirling/software/SPDF/config/security/IPRateLimitingFilter.java index ed269c4d1..25f27d658 100644 --- a/src/main/java/stirling/software/SPDF/config/security/IPRateLimitingFilter.java +++ b/src/main/java/stirling/software/SPDF/config/security/IPRateLimitingFilter.java @@ -7,8 +7,11 @@ import java.util.concurrent.atomic.AtomicInteger; import jakarta.servlet.*; import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.utils.RequestUriUtils; +@RequiredArgsConstructor public class IPRateLimitingFilter implements Filter { private final ConcurrentHashMap requestCounts = @@ -17,11 +20,6 @@ public class IPRateLimitingFilter implements Filter { private final int maxRequests; private final int maxGetRequests; - public IPRateLimitingFilter(int maxRequests, int maxGetRequests) { - this.maxRequests = maxRequests; - this.maxGetRequests = maxGetRequests; - } - @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { diff --git a/src/main/java/stirling/software/SPDF/config/security/InitialSecuritySetup.java b/src/main/java/stirling/software/SPDF/config/security/InitialSecuritySetup.java index 9299d4773..9339405da 100644 --- a/src/main/java/stirling/software/SPDF/config/security/InitialSecuritySetup.java +++ b/src/main/java/stirling/software/SPDF/config/security/InitialSecuritySetup.java @@ -7,6 +7,7 @@ import org.springframework.stereotype.Component; import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.config.interfaces.DatabaseInterface; @@ -16,6 +17,7 @@ import stirling.software.SPDF.model.exception.UnsupportedProviderException; @Slf4j @Component +@RequiredArgsConstructor public class InitialSecuritySetup { private final UserService userService; @@ -24,15 +26,6 @@ public class InitialSecuritySetup { private final DatabaseInterface databaseService; - public InitialSecuritySetup( - UserService userService, - ApplicationProperties applicationProperties, - DatabaseInterface databaseService) { - this.userService = userService; - this.applicationProperties = applicationProperties; - this.databaseService = databaseService; - } - @PostConstruct public void init() { try { diff --git a/src/main/java/stirling/software/SPDF/config/security/LoginAttemptService.java b/src/main/java/stirling/software/SPDF/config/security/LoginAttemptService.java index f036acfd4..d65557822 100644 --- a/src/main/java/stirling/software/SPDF/config/security/LoginAttemptService.java +++ b/src/main/java/stirling/software/SPDF/config/security/LoginAttemptService.java @@ -7,6 +7,7 @@ import org.springframework.stereotype.Service; import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.ApplicationProperties; @@ -14,6 +15,7 @@ import stirling.software.SPDF.model.AttemptCounter; @Service @Slf4j +@RequiredArgsConstructor public class LoginAttemptService { private final ApplicationProperties applicationProperties; @@ -26,10 +28,6 @@ public class LoginAttemptService { private boolean isBlockedEnabled = true; - public LoginAttemptService(ApplicationProperties applicationProperties) { - this.applicationProperties = applicationProperties; - } - @PostConstruct public void init() { MAX_ATTEMPT = applicationProperties.getSecurity().getLoginAttemptCount(); diff --git a/src/main/java/stirling/software/SPDF/config/security/RateLimitResetScheduler.java b/src/main/java/stirling/software/SPDF/config/security/RateLimitResetScheduler.java index a3641a701..5751ec871 100644 --- a/src/main/java/stirling/software/SPDF/config/security/RateLimitResetScheduler.java +++ b/src/main/java/stirling/software/SPDF/config/security/RateLimitResetScheduler.java @@ -3,15 +3,14 @@ package stirling.software.SPDF.config.security; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import lombok.RequiredArgsConstructor; + @Component +@RequiredArgsConstructor public class RateLimitResetScheduler { private final IPRateLimitingFilter rateLimitingFilter; - public RateLimitResetScheduler(IPRateLimitingFilter rateLimitingFilter) { - this.rateLimitingFilter = rateLimitingFilter; - } - @Scheduled(cron = "0 0 0 * * MON") // At 00:00 every Monday TODO: configurable public void resetRateLimit() { rateLimitingFilter.resetRequestCounts(); diff --git a/src/main/java/stirling/software/SPDF/config/security/UserService.java b/src/main/java/stirling/software/SPDF/config/security/UserService.java index cc12332a6..d90539171 100644 --- a/src/main/java/stirling/software/SPDF/config/security/UserService.java +++ b/src/main/java/stirling/software/SPDF/config/security/UserService.java @@ -19,6 +19,7 @@ import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.config.interfaces.DatabaseInterface; @@ -32,6 +33,7 @@ import stirling.software.SPDF.repository.UserRepository; @Service @Slf4j +@RequiredArgsConstructor public class UserService implements UserServiceInterface { private final UserRepository userRepository; @@ -48,23 +50,6 @@ public class UserService implements UserServiceInterface { private final ApplicationProperties applicationProperties; - public UserService( - UserRepository userRepository, - AuthorityRepository authorityRepository, - PasswordEncoder passwordEncoder, - MessageSource messageSource, - SessionPersistentRegistry sessionRegistry, - DatabaseInterface databaseService, - ApplicationProperties applicationProperties) { - this.userRepository = userRepository; - this.authorityRepository = authorityRepository; - this.passwordEncoder = passwordEncoder; - this.messageSource = messageSource; - this.sessionRegistry = sessionRegistry; - this.databaseService = databaseService; - this.applicationProperties = applicationProperties; - } - @Transactional public void migrateOauth2ToSSO() { userRepository diff --git a/src/main/java/stirling/software/SPDF/config/security/database/ScheduledTasks.java b/src/main/java/stirling/software/SPDF/config/security/database/ScheduledTasks.java index c318f1d97..a0c4af046 100644 --- a/src/main/java/stirling/software/SPDF/config/security/database/ScheduledTasks.java +++ b/src/main/java/stirling/software/SPDF/config/security/database/ScheduledTasks.java @@ -6,20 +6,19 @@ import org.springframework.context.annotation.Conditional; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.config.interfaces.DatabaseInterface; import stirling.software.SPDF.controller.api.H2SQLCondition; import stirling.software.SPDF.model.exception.UnsupportedProviderException; @Component @Conditional(H2SQLCondition.class) +@RequiredArgsConstructor public class ScheduledTasks { private final DatabaseInterface databaseService; - public ScheduledTasks(DatabaseInterface databaseService) { - this.databaseService = databaseService; - } - @Scheduled(cron = "0 0 0 * * ?") public void performBackup() throws SQLException, UnsupportedProviderException { databaseService.exportDatabase(); diff --git a/src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java b/src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java index 4ee49aed4..1b320c2c7 100644 --- a/src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java +++ b/src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java @@ -15,6 +15,8 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.config.security.LoginAttemptService; import stirling.software.SPDF.config.security.UserService; import stirling.software.SPDF.model.ApplicationProperties; @@ -23,6 +25,7 @@ import stirling.software.SPDF.model.AuthenticationType; import stirling.software.SPDF.model.exception.UnsupportedProviderException; import stirling.software.SPDF.utils.RequestUriUtils; +@RequiredArgsConstructor public class CustomOAuth2AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { @@ -30,15 +33,6 @@ public class CustomOAuth2AuthenticationSuccessHandler private final ApplicationProperties applicationProperties; private final UserService userService; - public CustomOAuth2AuthenticationSuccessHandler( - LoginAttemptService loginAttemptService, - ApplicationProperties applicationProperties, - UserService userService) { - this.applicationProperties = applicationProperties; - this.userService = userService; - this.loginAttemptService = loginAttemptService; - } - @Override public void onAuthenticationSuccess( HttpServletRequest request, HttpServletResponse response, Authentication authentication) diff --git a/src/main/java/stirling/software/SPDF/config/security/saml2/CustomSaml2ResponseAuthenticationConverter.java b/src/main/java/stirling/software/SPDF/config/security/saml2/CustomSaml2ResponseAuthenticationConverter.java index 3a576aea5..4a9cdd284 100644 --- a/src/main/java/stirling/software/SPDF/config/security/saml2/CustomSaml2ResponseAuthenticationConverter.java +++ b/src/main/java/stirling/software/SPDF/config/security/saml2/CustomSaml2ResponseAuthenticationConverter.java @@ -13,6 +13,7 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider.ResponseToken; import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.config.security.UserService; @@ -20,15 +21,12 @@ import stirling.software.SPDF.model.User; @Slf4j @ConditionalOnProperty(name = "security.saml2.enabled", havingValue = "true") +@RequiredArgsConstructor public class CustomSaml2ResponseAuthenticationConverter implements Converter { private final UserService userService; - public CustomSaml2ResponseAuthenticationConverter(UserService userService) { - this.userService = userService; - } - private Map> extractAttributes(Assertion assertion) { Map> attributes = new HashMap<>(); diff --git a/src/main/java/stirling/software/SPDF/config/security/saml2/SAML2Configuration.java b/src/main/java/stirling/software/SPDF/config/security/saml2/SAML2Configuration.java index a6b487ec6..58c0a1637 100644 --- a/src/main/java/stirling/software/SPDF/config/security/saml2/SAML2Configuration.java +++ b/src/main/java/stirling/software/SPDF/config/security/saml2/SAML2Configuration.java @@ -21,6 +21,7 @@ import org.springframework.security.saml2.provider.service.web.authentication.Op import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.ApplicationProperties; @@ -29,14 +30,11 @@ import stirling.software.SPDF.model.ApplicationProperties.Security.SAML2; @Configuration @Slf4j @ConditionalOnProperty(value = "security.saml2.enabled", havingValue = "true") +@RequiredArgsConstructor public class SAML2Configuration { private final ApplicationProperties applicationProperties; - public SAML2Configuration(ApplicationProperties applicationProperties) { - this.applicationProperties = applicationProperties; - } - @Bean @ConditionalOnProperty(name = "security.saml2.enabled", havingValue = "true") public RelyingPartyRegistrationRepository relyingPartyRegistrations() throws Exception { diff --git a/src/main/java/stirling/software/SPDF/config/security/session/CustomHttpSessionListener.java b/src/main/java/stirling/software/SPDF/config/security/session/CustomHttpSessionListener.java index 3d97181ab..09868eff9 100644 --- a/src/main/java/stirling/software/SPDF/config/security/session/CustomHttpSessionListener.java +++ b/src/main/java/stirling/software/SPDF/config/security/session/CustomHttpSessionListener.java @@ -1,6 +1,5 @@ package stirling.software.SPDF.config.security.session; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import jakarta.servlet.http.HttpSessionEvent; @@ -14,7 +13,6 @@ public class CustomHttpSessionListener implements HttpSessionListener { private SessionPersistentRegistry sessionPersistentRegistry; - @Autowired public CustomHttpSessionListener(SessionPersistentRegistry sessionPersistentRegistry) { super(); this.sessionPersistentRegistry = sessionPersistentRegistry; diff --git a/src/main/java/stirling/software/SPDF/config/security/session/SessionPersistentRegistry.java b/src/main/java/stirling/software/SPDF/config/security/session/SessionPersistentRegistry.java index 18b037164..9e249f3a4 100644 --- a/src/main/java/stirling/software/SPDF/config/security/session/SessionPersistentRegistry.java +++ b/src/main/java/stirling/software/SPDF/config/security/session/SessionPersistentRegistry.java @@ -12,10 +12,13 @@ import org.springframework.stereotype.Component; import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal; import stirling.software.SPDF.model.SessionEntity; @Component +@RequiredArgsConstructor public class SessionPersistentRegistry implements SessionRegistry { private final SessionRepository sessionRepository; @@ -23,10 +26,6 @@ public class SessionPersistentRegistry implements SessionRegistry { @Value("${server.servlet.session.timeout:30m}") private Duration defaultMaxInactiveInterval; - public SessionPersistentRegistry(SessionRepository sessionRepository) { - this.sessionRepository = sessionRepository; - } - @Override public List getAllPrincipals() { List sessions = sessionRepository.findAll(); diff --git a/src/main/java/stirling/software/SPDF/config/security/session/SessionScheduled.java b/src/main/java/stirling/software/SPDF/config/security/session/SessionScheduled.java index 9710316e3..46c17a77e 100644 --- a/src/main/java/stirling/software/SPDF/config/security/session/SessionScheduled.java +++ b/src/main/java/stirling/software/SPDF/config/security/session/SessionScheduled.java @@ -9,15 +9,14 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.security.core.session.SessionInformation; import org.springframework.stereotype.Component; +import lombok.RequiredArgsConstructor; + @Component +@RequiredArgsConstructor public class SessionScheduled { private final SessionPersistentRegistry sessionPersistentRegistry; - public SessionScheduled(SessionPersistentRegistry sessionPersistentRegistry) { - this.sessionPersistentRegistry = sessionPersistentRegistry; - } - @Scheduled(cron = "0 0/5 * * * ?") public void expireSessions() { Instant now = Instant.now(); diff --git a/src/main/java/stirling/software/SPDF/controller/api/AdditionalLanguageJsController.java b/src/main/java/stirling/software/SPDF/controller/api/AdditionalLanguageJsController.java index 8475d1f20..e5d3ba884 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/AdditionalLanguageJsController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/AdditionalLanguageJsController.java @@ -14,18 +14,17 @@ import io.swagger.v3.oas.annotations.Hidden; import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.service.LanguageService; @RestController @RequestMapping("/js") +@RequiredArgsConstructor public class AdditionalLanguageJsController { private final LanguageService languageService; - public AdditionalLanguageJsController(LanguageService languageService) { - this.languageService = languageService; - } - @Hidden @GetMapping(value = "/additionalLanguageCode.js", produces = "application/javascript") public void generateAdditionalLanguageJs(HttpServletResponse response) throws IOException { diff --git a/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java b/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java index 2406e1168..75f61e64e 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java @@ -11,27 +11,24 @@ import org.apache.pdfbox.pdmodel.PDPageTree; import org.apache.pdfbox.pdmodel.encryption.PDEncryption; import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation; import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.PDFFile; import stirling.software.SPDF.service.CustomPDFDocumentFactory; @RestController @RequestMapping("/api/v1/analysis") @Tag(name = "Analysis", description = "Analysis APIs") +@RequiredArgsConstructor public class AnalysisController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public AnalysisController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(value = "/page-count", consumes = "multipart/form-data") @Operation( summary = "Get PDF page count", diff --git a/src/main/java/stirling/software/SPDF/controller/api/CropController.java b/src/main/java/stirling/software/SPDF/controller/api/CropController.java index 68c3a44f3..ad16c460e 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/CropController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/CropController.java @@ -10,7 +10,6 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -20,6 +19,8 @@ import org.springframework.web.bind.annotation.RestController; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.general.CropPdfForm; import stirling.software.SPDF.service.CustomPDFDocumentFactory; import stirling.software.SPDF.utils.WebResponseUtils; @@ -27,15 +28,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @RequestMapping("/api/v1/general") @Tag(name = "General", description = "General APIs") +@RequiredArgsConstructor public class CropController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public CropController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(value = "/crop", consumes = "multipart/form-data") @Operation( summary = "Crops a PDF document", diff --git a/src/main/java/stirling/software/SPDF/controller/api/DatabaseController.java b/src/main/java/stirling/software/SPDF/controller/api/DatabaseController.java index 79138721c..8e3484f23 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/DatabaseController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/DatabaseController.java @@ -24,6 +24,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.config.security.database.DatabaseService; @@ -34,14 +35,11 @@ import stirling.software.SPDF.config.security.database.DatabaseService; @PreAuthorize("hasRole('ROLE_ADMIN')") @Conditional(H2SQLCondition.class) @Tag(name = "Database", description = "Database APIs for backup, import, and management") +@RequiredArgsConstructor public class DatabaseController { private final DatabaseService databaseService; - public DatabaseController(DatabaseService databaseService) { - this.databaseService = databaseService; - } - @Operation( summary = "Import a database backup file", description = "Uploads and imports a database backup SQL file.") diff --git a/src/main/java/stirling/software/SPDF/controller/api/MergeController.java b/src/main/java/stirling/software/SPDF/controller/api/MergeController.java index 279dd2489..a226bd02d 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/MergeController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/MergeController.java @@ -18,7 +18,6 @@ import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; import org.apache.pdfbox.pdmodel.interactive.form.PDField; import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -29,6 +28,7 @@ import org.springframework.web.multipart.MultipartFile; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.general.MergePdfsRequest; @@ -40,15 +40,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @Slf4j @RequestMapping("/api/v1/general") @Tag(name = "General", description = "General APIs") +@RequiredArgsConstructor public class MergeController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public MergeController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - // Merges a list of PDDocument objects into a single PDDocument public PDDocument mergeDocuments(List documents) throws IOException { PDDocument mergedDoc = pdfDocumentFactory.createNewDocument(); diff --git a/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java b/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java index 73bbe98a9..f8f4bd73c 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java @@ -11,7 +11,6 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; import org.apache.pdfbox.util.Matrix; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -23,6 +22,8 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.general.MergeMultiplePagesRequest; import stirling.software.SPDF.service.CustomPDFDocumentFactory; import stirling.software.SPDF.utils.WebResponseUtils; @@ -30,15 +31,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @RequestMapping("/api/v1/general") @Tag(name = "General", description = "General APIs") +@RequiredArgsConstructor public class MultiPageLayoutController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public MultiPageLayoutController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(value = "/multi-page-layout", consumes = "multipart/form-data") @Operation( summary = "Merge multiple pages of a PDF document into a single page", diff --git a/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java b/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java index fce61d3e5..a9d66106d 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java @@ -4,7 +4,6 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import org.apache.pdfbox.pdmodel.PDDocument; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -14,6 +13,8 @@ import org.springframework.web.bind.annotation.RestController; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.PDFFile; import stirling.software.SPDF.service.CustomPDFDocumentFactory; import stirling.software.SPDF.service.PdfImageRemovalService; @@ -26,6 +27,7 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @RequestMapping("/api/v1/general") @Tag(name = "General", description = "General APIs") +@RequiredArgsConstructor public class PdfImageRemovalController { // Service for removing images from PDFs @@ -33,19 +35,6 @@ public class PdfImageRemovalController { private final CustomPDFDocumentFactory pdfDocumentFactory; - /** - * Constructor for dependency injection of PdfImageRemovalService. - * - * @param pdfImageRemovalService The service used for removing images from PDFs. - */ - @Autowired - public PdfImageRemovalController( - PdfImageRemovalService pdfImageRemovalService, - CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfImageRemovalService = pdfImageRemovalService; - this.pdfDocumentFactory = pdfDocumentFactory; - } - /** * Endpoint to remove images from a PDF file. * diff --git a/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java b/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java index 996ed45bb..60a398305 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java @@ -12,7 +12,6 @@ import java.util.Map; import org.apache.pdfbox.Loader; import org.apache.pdfbox.multipdf.Overlay; import org.apache.pdfbox.pdmodel.PDDocument; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -25,6 +24,8 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.general.OverlayPdfsRequest; import stirling.software.SPDF.service.CustomPDFDocumentFactory; import stirling.software.SPDF.utils.GeneralUtils; @@ -33,15 +34,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @RequestMapping("/api/v1/general") @Tag(name = "General", description = "General APIs") +@RequiredArgsConstructor public class PdfOverlayController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public PdfOverlayController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(value = "/overlay-pdfs", consumes = "multipart/form-data") @Operation( summary = "Overlay PDF files in various modes", diff --git a/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java b/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java index 342d3cb8b..0ce0c1e24 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java @@ -7,7 +7,6 @@ import java.util.List; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -19,6 +18,7 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.SortTypes; @@ -32,15 +32,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RequestMapping("/api/v1/general") @Slf4j @Tag(name = "General", description = "General APIs") +@RequiredArgsConstructor public class RearrangePagesPDFController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public RearrangePagesPDFController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/remove-pages") @Operation( summary = "Remove pages from a PDF file", diff --git a/src/main/java/stirling/software/SPDF/controller/api/RotationController.java b/src/main/java/stirling/software/SPDF/controller/api/RotationController.java index b029450ef..4b1a221a9 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/RotationController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/RotationController.java @@ -5,7 +5,6 @@ import java.io.IOException; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageTree; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -17,6 +16,8 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.general.RotatePDFRequest; import stirling.software.SPDF.service.CustomPDFDocumentFactory; import stirling.software.SPDF.utils.WebResponseUtils; @@ -24,15 +25,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @RequestMapping("/api/v1/general") @Tag(name = "General", description = "General APIs") +@RequiredArgsConstructor public class RotationController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public RotationController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/rotate-pdf") @Operation( summary = "Rotate a PDF file", diff --git a/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java b/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java index 48e3c0f44..65a10c77e 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java @@ -12,7 +12,6 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; import org.apache.pdfbox.util.Matrix; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -24,6 +23,8 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.general.ScalePagesRequest; import stirling.software.SPDF.service.CustomPDFDocumentFactory; import stirling.software.SPDF.utils.WebResponseUtils; @@ -31,15 +32,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @RequestMapping("/api/v1/general") @Tag(name = "General", description = "General APIs") +@RequiredArgsConstructor public class ScalePagesController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public ScalePagesController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(value = "/scale-pages", consumes = "multipart/form-data") @Operation( summary = "Change the size of a PDF page/document", diff --git a/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java b/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java index 25c198a8a..a64379a64 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/SettingsController.java @@ -14,6 +14,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.config.EndpointConfiguration; import stirling.software.SPDF.config.InstallationPathConfig; import stirling.software.SPDF.model.ApplicationProperties; @@ -22,19 +24,13 @@ import stirling.software.SPDF.utils.GeneralUtils; @Controller @Tag(name = "Settings", description = "Settings APIs") @RequestMapping("/api/v1/settings") +@RequiredArgsConstructor @Hidden public class SettingsController { private final ApplicationProperties applicationProperties; private final EndpointConfiguration endpointConfiguration; - public SettingsController( - ApplicationProperties applicationProperties, - EndpointConfiguration endpointConfiguration) { - this.applicationProperties = applicationProperties; - this.endpointConfiguration = endpointConfiguration; - } - @PostMapping("/update-enable-analytics") @Hidden public ResponseEntity updateApiKey(@RequestBody Boolean enabled) throws IOException { diff --git a/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java b/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java index 696482b63..af7fda04a 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java @@ -12,7 +12,6 @@ import java.util.zip.ZipOutputStream; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -25,6 +24,7 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.PDFWithPageNums; @@ -35,15 +35,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RequestMapping("/api/v1/general") @Slf4j @Tag(name = "General", description = "General APIs") +@RequiredArgsConstructor public class SplitPDFController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public SplitPDFController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/split-pages") @Operation( summary = "Split a PDF file into separate documents", diff --git a/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java b/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java index 698e2b50e..5e0f1d012 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java @@ -12,7 +12,6 @@ import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline; import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -29,6 +28,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.PdfMetadata; @@ -41,19 +41,13 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RequestMapping("/api/v1/general") @Slf4j @Tag(name = "General", description = "General APIs") +@RequiredArgsConstructor public class SplitPdfByChaptersController { private final PdfMetadataService pdfMetadataService; private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public SplitPdfByChaptersController( - PdfMetadataService pdfMetadataService, CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfMetadataService = pdfMetadataService; - this.pdfDocumentFactory = pdfDocumentFactory; - } - private static List extractOutlineItems( PDDocument sourceDocument, PDOutlineItem current, diff --git a/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java b/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java index 83f0cb0e9..a2b0e2add 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java @@ -17,7 +17,6 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; import org.apache.pdfbox.util.Matrix; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -30,6 +29,8 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.SplitPdfBySectionsRequest; import stirling.software.SPDF.service.CustomPDFDocumentFactory; import stirling.software.SPDF.utils.WebResponseUtils; @@ -37,15 +38,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @RequestMapping("/api/v1/general") @Tag(name = "General", description = "General APIs") +@RequiredArgsConstructor public class SplitPdfBySectionsController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public SplitPdfBySectionsController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(value = "/split-pdf-by-sections", consumes = "multipart/form-data") @Operation( summary = "Split PDF pages into smaller sections", diff --git a/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java b/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java index fb5375ef3..1049e02bc 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java @@ -9,7 +9,6 @@ import java.util.zip.ZipOutputStream; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -22,6 +21,7 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.general.SplitPdfBySizeOrCountRequest; @@ -33,15 +33,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RequestMapping("/api/v1/general") @Slf4j @Tag(name = "General", description = "General APIs") +@RequiredArgsConstructor public class SplitPdfBySizeController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public SplitPdfBySizeController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(value = "/split-by-size-or-count", consumes = "multipart/form-data") @Operation( summary = "Auto split PDF pages into separate documents based on size or count", diff --git a/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java b/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java index f6b0ed947..b3ae43071 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java @@ -10,7 +10,6 @@ import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -20,6 +19,8 @@ import org.springframework.web.bind.annotation.RestController; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.PDFFile; import stirling.software.SPDF.service.CustomPDFDocumentFactory; import stirling.software.SPDF.utils.WebResponseUtils; @@ -27,15 +28,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @RequestMapping("/api/v1/general") @Tag(name = "General", description = "General APIs") +@RequiredArgsConstructor public class ToSinglePageController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public ToSinglePageController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/pdf-to-single-page") @Operation( summary = "Convert a multi-page PDF into a single long page PDF", diff --git a/src/main/java/stirling/software/SPDF/controller/api/UserController.java b/src/main/java/stirling/software/SPDF/controller/api/UserController.java index 06dc76658..ce4770499 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/UserController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/UserController.java @@ -27,6 +27,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.config.security.UserService; @@ -43,6 +44,7 @@ import stirling.software.SPDF.model.exception.UnsupportedProviderException; @Tag(name = "User", description = "User APIs") @RequestMapping("/api/v1/user") @Slf4j +@RequiredArgsConstructor public class UserController { private static final String LOGIN_MESSAGETYPE_CREDSUPDATED = "/login?messageType=credsUpdated"; @@ -50,15 +52,6 @@ public class UserController { private final SessionPersistentRegistry sessionRegistry; private final ApplicationProperties applicationProperties; - public UserController( - UserService userService, - SessionPersistentRegistry sessionRegistry, - ApplicationProperties applicationProperties) { - this.userService = userService; - this.sessionRegistry = sessionRegistry; - this.applicationProperties = applicationProperties; - } - @PreAuthorize("!hasAuthority('ROLE_DEMO_USER')") @PostMapping("/register") public String register(@ModelAttribute UsernameAndPass requestModel, Model model) diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java index 52b124e53..bfd67ef76 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java +++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java @@ -1,6 +1,5 @@ package stirling.software.SPDF.controller.api.converters; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -12,6 +11,8 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.config.RuntimePathConfig; import stirling.software.SPDF.model.ApplicationProperties; import stirling.software.SPDF.model.api.converters.HTMLToPdfRequest; @@ -22,6 +23,7 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @Tag(name = "Convert", description = "Convert APIs") @RequestMapping("/api/v1/convert") +@RequiredArgsConstructor public class ConvertHtmlToPDF { private final CustomPDFDocumentFactory pdfDocumentFactory; @@ -30,17 +32,6 @@ public class ConvertHtmlToPDF { private final RuntimePathConfig runtimePathConfig; - @Autowired - public ConvertHtmlToPDF( - CustomPDFDocumentFactory pdfDocumentFactory, - ApplicationProperties applicationProperties, - RuntimePathConfig runtimePathConfig) { - this.pdfDocumentFactory = pdfDocumentFactory; - - this.applicationProperties = applicationProperties; - this.runtimePathConfig = runtimePathConfig; - } - @PostMapping(consumes = "multipart/form-data", value = "/html/pdf") @Operation( summary = "Convert an HTML or ZIP (containing HTML and CSS) to PDF", diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java index c64084bf4..2fad77e37 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java @@ -15,7 +15,6 @@ import org.apache.commons.io.FileUtils; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.rendering.ImageType; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -28,6 +27,7 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.converters.ConvertToImageRequest; @@ -40,15 +40,11 @@ import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult; @RequestMapping("/api/v1/convert") @Slf4j @Tag(name = "Convert", description = "Convert APIs") +@RequiredArgsConstructor public class ConvertImgPDFController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public ConvertImgPDFController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/pdf/img") @Operation( summary = "Convert PDF to image(s)", diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java index 547d9c646..b8a190f90 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java +++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java @@ -10,7 +10,6 @@ import org.commonmark.node.Node; import org.commonmark.parser.Parser; import org.commonmark.renderer.html.AttributeProvider; import org.commonmark.renderer.html.HtmlRenderer; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -22,6 +21,8 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.config.RuntimePathConfig; import stirling.software.SPDF.model.ApplicationProperties; import stirling.software.SPDF.model.api.GeneralFile; @@ -32,6 +33,7 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @Tag(name = "Convert", description = "Convert APIs") @RequestMapping("/api/v1/convert") +@RequiredArgsConstructor public class ConvertMarkdownToPdf { private final CustomPDFDocumentFactory pdfDocumentFactory; @@ -39,17 +41,6 @@ public class ConvertMarkdownToPdf { private final ApplicationProperties applicationProperties; private final RuntimePathConfig runtimePathConfig; - @Autowired - public ConvertMarkdownToPdf( - CustomPDFDocumentFactory pdfDocumentFactory, - ApplicationProperties applicationProperties, - RuntimePathConfig runtimePathConfig) { - this.pdfDocumentFactory = pdfDocumentFactory; - - this.applicationProperties = applicationProperties; - this.runtimePathConfig = runtimePathConfig; - } - @PostMapping(consumes = "multipart/form-data", value = "/markdown/pdf") @Operation( summary = "Convert a Markdown file to PDF", diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java index 46bf4c033..38a0ac16e 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java @@ -10,7 +10,6 @@ import java.util.List; import org.apache.commons.io.FilenameUtils; import org.apache.pdfbox.pdmodel.PDDocument; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -22,6 +21,8 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.config.RuntimePathConfig; import stirling.software.SPDF.model.api.GeneralFile; import stirling.software.SPDF.service.CustomPDFDocumentFactory; @@ -32,18 +33,12 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @Tag(name = "Convert", description = "Convert APIs") @RequestMapping("/api/v1/convert") +@RequiredArgsConstructor public class ConvertOfficeController { private final CustomPDFDocumentFactory pdfDocumentFactory; private final RuntimePathConfig runtimePathConfig; - @Autowired - public ConvertOfficeController( - CustomPDFDocumentFactory pdfDocumentFactory, RuntimePathConfig runtimePathConfig) { - this.pdfDocumentFactory = pdfDocumentFactory; - this.runtimePathConfig = runtimePathConfig; - } - public File convertToPdf(MultipartFile inputFile) throws IOException, InterruptedException { // Check for valid file extension String originalFilename = Filenames.toSimpleFileName(inputFile.getOriginalFilename()); diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java index f603aa277..76f0b9286 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java +++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java @@ -4,7 +4,6 @@ import java.io.IOException; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.text.PDFTextStripper; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -17,6 +16,8 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.PDFFile; import stirling.software.SPDF.model.api.converters.PdfToPresentationRequest; import stirling.software.SPDF.model.api.converters.PdfToTextOrRTFRequest; @@ -28,15 +29,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @RequestMapping("/api/v1/convert") @Tag(name = "Convert", description = "Convert APIs") +@RequiredArgsConstructor public class ConvertPDFToOffice { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public ConvertPDFToOffice(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/pdf/presentation") @Operation( summary = "Convert PDF to Presentation format", diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java index 941d55795..9ef490e9a 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java +++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java @@ -7,7 +7,6 @@ import java.util.ArrayList; import java.util.List; import org.apache.pdfbox.pdmodel.PDDocument; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -17,6 +16,7 @@ import org.springframework.web.bind.annotation.RestController; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.config.RuntimePathConfig; @@ -32,22 +32,13 @@ import stirling.software.SPDF.utils.WebResponseUtils; @Tag(name = "Convert", description = "Convert APIs") @Slf4j @RequestMapping("/api/v1/convert") +@RequiredArgsConstructor public class ConvertWebsiteToPDF { private final CustomPDFDocumentFactory pdfDocumentFactory; private final RuntimePathConfig runtimePathConfig; private final ApplicationProperties applicationProperties; - @Autowired - public ConvertWebsiteToPDF( - CustomPDFDocumentFactory pdfDocumentFactory, - RuntimePathConfig runtimePathConfig, - ApplicationProperties applicationProperties) { - this.pdfDocumentFactory = pdfDocumentFactory; - this.runtimePathConfig = runtimePathConfig; - this.applicationProperties = applicationProperties; - } - @PostMapping(consumes = "multipart/form-data", value = "/url/pdf") @Operation( summary = "Convert a URL to a PDF", diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java index 06cc45094..878936534 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java @@ -13,7 +13,6 @@ import java.util.zip.ZipOutputStream; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.QuoteMode; import org.apache.pdfbox.pdmodel.PDDocument; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ContentDisposition; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; @@ -26,6 +25,7 @@ import org.springframework.web.bind.annotation.RestController; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.PDFWithPageNums; @@ -41,15 +41,11 @@ import technology.tabula.extractors.SpreadsheetExtractionAlgorithm; @RequestMapping("/api/v1/convert") @Tag(name = "Convert", description = "Convert APIs") @Slf4j +@RequiredArgsConstructor public class ExtractCSVController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public ExtractCSVController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(value = "/pdf/csv", consumes = "multipart/form-data") @Operation( summary = "Extracts a CSV document from a PDF", diff --git a/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java b/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java index 006598bd1..935118a7d 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java @@ -5,7 +5,6 @@ import java.io.IOException; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.common.PDRectangle; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -17,6 +16,8 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.PDFComparisonAndCount; import stirling.software.SPDF.model.api.PDFWithPageNums; import stirling.software.SPDF.model.api.filter.ContainsTextRequest; @@ -30,15 +31,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @RequestMapping("/api/v1/filter") @Tag(name = "Filter", description = "Filter APIs") +@RequiredArgsConstructor public class FilterController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public FilterController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/filter-contains-text") @Operation( summary = "Checks if a PDF contains set text, returns true if does", diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java index 1d71d94b7..5d6ce4516 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java @@ -8,7 +8,6 @@ import java.util.List; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.text.PDFTextStripper; import org.apache.pdfbox.text.TextPosition; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -20,6 +19,7 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.misc.ExtractHeaderRequest; @@ -30,18 +30,14 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RequestMapping("/api/v1/misc") @Slf4j @Tag(name = "Misc", description = "Miscellaneous APIs") +@RequiredArgsConstructor public class AutoRenameController { - private static final float TITLE_FONT_SIZE_THRESHOLD = 20.0f; + // private static final float TITLE_FONT_SIZE_THRESHOLD = 20.0f; private static final int LINE_LIMIT = 200; private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public AutoRenameController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/auto-rename") @Operation( summary = "Extract header from PDF file", diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java index 7a5c730fe..4e976d12d 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java @@ -16,7 +16,6 @@ import java.util.zip.ZipOutputStream; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.rendering.PDFRenderer; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -32,6 +31,7 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.misc.AutoSplitPdfRequest; @@ -42,6 +42,7 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RequestMapping("/api/v1/misc") @Slf4j @Tag(name = "Misc", description = "Miscellaneous APIs") +@RequiredArgsConstructor public class AutoSplitPdfController { private static final Set VALID_QR_CONTENTS = @@ -53,11 +54,6 @@ public class AutoSplitPdfController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public AutoSplitPdfController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - private static String decodeQRCode(BufferedImage bufferedImage) { LuminanceSource source; diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java index c50c0a685..c341a49fc 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java @@ -13,7 +13,6 @@ import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageTree; import org.apache.pdfbox.rendering.PDFRenderer; import org.apache.pdfbox.text.PDFTextStripper; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; @@ -27,6 +26,7 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.misc.RemoveBlankPagesRequest; @@ -38,15 +38,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RequestMapping("/api/v1/misc") @Slf4j @Tag(name = "Misc", description = "Miscellaneous APIs") +@RequiredArgsConstructor public class BlankPageController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public BlankPageController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - public static boolean isBlankImage( BufferedImage image, int threshold, double whitePercent, int blurSize) { if (image == null) { diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java index 090b2b2e1..bceb9e58b 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java @@ -10,7 +10,6 @@ import org.apache.pdfbox.cos.*; import org.apache.pdfbox.io.IOUtils; import org.apache.pdfbox.pdfwriter.compress.CompressParameters; import org.apache.pdfbox.pdmodel.PDDocument; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -22,6 +21,7 @@ import org.springframework.web.multipart.MultipartFile; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.PDFFile; @@ -32,15 +32,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RequestMapping("/api/v1/misc") @Slf4j @Tag(name = "Misc", description = "Miscellaneous APIs") +@RequiredArgsConstructor public class DecompressPdfController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public DecompressPdfController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(value = "/decompress-pdf", consumes = "multipart/form-data") @Operation( summary = "Decompress PDF streams", diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java index fb27bf75a..67019559e 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java @@ -16,7 +16,6 @@ import javax.imageio.ImageIO; import org.apache.commons.io.FileUtils; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.rendering.PDFRenderer; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; @@ -29,6 +28,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.misc.ExtractImageScansRequest; @@ -42,17 +42,13 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RequestMapping("/api/v1/misc") @Slf4j @Tag(name = "Misc", description = "Miscellaneous APIs") +@RequiredArgsConstructor public class ExtractImageScansController { private static final String REPLACEFIRST = "[.][^.]+$"; private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public ExtractImageScansController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/extract-image-scans") @Operation( summary = "Extract image scans from an input file", diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java index af865f8f4..187eda305 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java @@ -24,7 +24,6 @@ import org.apache.pdfbox.cos.COSName; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -37,6 +36,7 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.PDFExtractImagesRequest; @@ -48,15 +48,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RequestMapping("/api/v1/misc") @Slf4j @Tag(name = "Misc", description = "Miscellaneous APIs") +@RequiredArgsConstructor public class ExtractImagesController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public ExtractImagesController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/extract-images") @Operation( summary = "Extract images from a PDF file", diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java index 8ddfa1657..e81fa23f2 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java @@ -11,7 +11,6 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; import org.apache.pdfbox.rendering.ImageType; import org.apache.pdfbox.rendering.PDFRenderer; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -23,6 +22,7 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.misc.FlattenRequest; @@ -33,15 +33,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RequestMapping("/api/v1/misc") @Slf4j @Tag(name = "Misc", description = "Miscellaneous APIs") +@RequiredArgsConstructor public class FlattenController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public FlattenController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/flatten") @Operation( summary = "Flatten PDF form fields or full page", diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java index 66ac528eb..10e4f6fdd 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java @@ -10,7 +10,6 @@ import java.util.Map.Entry; import org.apache.pdfbox.cos.COSName; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocumentInformation; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.*; @@ -20,6 +19,7 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.misc.MetadataRequest; @@ -31,15 +31,11 @@ import stirling.software.SPDF.utils.propertyeditor.StringToMapPropertyEditor; @RequestMapping("/api/v1/misc") @Slf4j @Tag(name = "Misc", description = "Miscellaneous APIs") +@RequiredArgsConstructor public class MetadataController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public MetadataController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - private String checkUndefined(String entry) { // Check if the string is "undefined" if ("undefined".equals(entry)) { diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java index e96a29c4b..558ac1fbb 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java @@ -28,6 +28,7 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.ApplicationProperties; @@ -38,19 +39,13 @@ import stirling.software.SPDF.service.CustomPDFDocumentFactory; @RequestMapping("/api/v1/misc") @Tag(name = "Misc", description = "Miscellaneous APIs") @Slf4j +@RequiredArgsConstructor public class OCRController { private final ApplicationProperties applicationProperties; private final CustomPDFDocumentFactory pdfDocumentFactory; - public OCRController( - ApplicationProperties applicationProperties, - CustomPDFDocumentFactory pdfDocumentFactory) { - this.applicationProperties = applicationProperties; - this.pdfDocumentFactory = pdfDocumentFactory; - } - /** Gets the list of available Tesseract languages from the tessdata directory */ public List getAvailableTesseractLanguages() { String tessdataDir = applicationProperties.getSystem().getTessdataDir(); @@ -61,7 +56,7 @@ public class OCRController { return Arrays.stream(files) .filter(file -> file.getName().endsWith(".traineddata")) .map(file -> file.getName().replace(".traineddata", "")) - .filter(lang -> !lang.equalsIgnoreCase("osd")) + .filter(lang -> !"osd".equalsIgnoreCase(lang)) .toList(); } diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java index a953586fb..51ca9f9ff 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java @@ -2,7 +2,6 @@ package stirling.software.SPDF.controller.api.misc; import java.io.IOException; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -15,6 +14,7 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.misc.OverlayImageRequest; @@ -26,15 +26,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RequestMapping("/api/v1/misc") @Slf4j @Tag(name = "Misc", description = "Miscellaneous APIs") +@RequiredArgsConstructor public class OverlayImageController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public OverlayImageController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/add-image") @Operation( summary = "Overlay image onto a PDF file", diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java index c66b55d73..cdae7dfad 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java @@ -10,7 +10,6 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.font.PDType1Font; import org.apache.pdfbox.pdmodel.font.Standard14Fonts; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -23,6 +22,8 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.misc.AddPageNumbersRequest; import stirling.software.SPDF.service.CustomPDFDocumentFactory; import stirling.software.SPDF.utils.GeneralUtils; @@ -31,15 +32,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @RequestMapping("/api/v1/misc") @Tag(name = "Misc", description = "Miscellaneous APIs") +@RequiredArgsConstructor public class PageNumbersController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public PageNumbersController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(value = "/add-page-numbers", consumes = "multipart/form-data") @Operation( summary = "Add page numbers to a PDF document", diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java index e75a2e20d..1a358b08e 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java @@ -6,7 +6,6 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.List; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -18,6 +17,8 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.PDFFile; import stirling.software.SPDF.service.CustomPDFDocumentFactory; import stirling.software.SPDF.utils.ProcessExecutor; @@ -27,15 +28,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @RequestMapping("/api/v1/misc") @Tag(name = "Misc", description = "Miscellaneous APIs") +@RequiredArgsConstructor public class RepairController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public RepairController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/repair") @Operation( summary = "Repair a PDF file", diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/ReplaceAndInvertColorController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/ReplaceAndInvertColorController.java index 65085b1d6..927b3a51f 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/ReplaceAndInvertColorController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/ReplaceAndInvertColorController.java @@ -2,7 +2,6 @@ package stirling.software.SPDF.controller.api.misc; import java.io.IOException; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; @@ -15,22 +14,19 @@ import org.springframework.web.bind.annotation.RestController; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.misc.ReplaceAndInvertColorRequest; import stirling.software.SPDF.service.misc.ReplaceAndInvertColorService; @RestController @RequestMapping("/api/v1/misc") @Tag(name = "Misc", description = "Miscellaneous APIs") +@RequiredArgsConstructor public class ReplaceAndInvertColorController { private ReplaceAndInvertColorService replaceAndInvertColorService; - @Autowired - public ReplaceAndInvertColorController( - ReplaceAndInvertColorService replaceAndInvertColorService) { - this.replaceAndInvertColorService = replaceAndInvertColorService; - } - @PostMapping(consumes = "multipart/form-data", value = "/replace-invert-pdf") @Operation( summary = "Replace-Invert Color PDF", diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java b/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java index ca5370b32..400650be3 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java @@ -6,7 +6,6 @@ import java.util.Map; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.common.PDNameTreeNode; import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -19,6 +18,8 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.PDFFile; import stirling.software.SPDF.service.CustomPDFDocumentFactory; import stirling.software.SPDF.utils.WebResponseUtils; @@ -26,15 +27,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @RequestMapping("/api/v1/misc") @Tag(name = "Misc", description = "Miscellaneous APIs") +@RequiredArgsConstructor public class ShowJavascript { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public ShowJavascript(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/show-javascript") @Operation( summary = "Grabs all JS from a PDF and returns a single JS file with all code", diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java index e23635b82..1ceddba83 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java @@ -24,7 +24,6 @@ import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState; import org.apache.pdfbox.util.Matrix; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -37,6 +36,8 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.misc.AddStampRequest; import stirling.software.SPDF.service.CustomPDFDocumentFactory; import stirling.software.SPDF.utils.WebResponseUtils; @@ -44,15 +45,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @RequestMapping("/api/v1/misc") @Tag(name = "Misc", description = "Miscellaneous APIs") +@RequiredArgsConstructor public class StampController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public StampController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/add-stamp") @Operation( summary = "Add stamp to a PDF file", diff --git a/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java b/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java index 6df02f24d..f8b05f576 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java @@ -23,6 +23,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.PipelineConfig; @@ -36,6 +37,7 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RequestMapping("/api/v1/pipeline") @Slf4j @Tag(name = "Pipeline", description = "Pipeline APIs") +@RequiredArgsConstructor public class PipelineController { private final PipelineProcessor processor; @@ -44,13 +46,6 @@ public class PipelineController { private final PostHogService postHogService; - public PipelineController( - PipelineProcessor processor, ObjectMapper objectMapper, PostHogService postHogService) { - this.processor = processor; - this.objectMapper = objectMapper; - this.postHogService = postHogService; - } - @PostMapping(value = "/handleData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntity handleData(@ModelAttribute HandleDataRequest request) throws JsonMappingException, JsonProcessingException { diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java b/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java index 4a8981142..7e1f2601f 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java @@ -52,7 +52,6 @@ import org.bouncycastle.operator.InputDecryptorProvider; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo; import org.bouncycastle.pkcs.PKCSException; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -65,6 +64,7 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.security.SignPDFWithCertRequest; @@ -75,6 +75,7 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RequestMapping("/api/v1/security") @Slf4j @Tag(name = "Security", description = "Security APIs") +@RequiredArgsConstructor public class CertSignController { static { @@ -83,11 +84,6 @@ public class CertSignController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public CertSignController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - private static void sign( CustomPDFDocumentFactory pdfDocumentFactory, MultipartFile input, diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java b/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java index 3ce586491..ef82a2942 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java @@ -43,7 +43,6 @@ import org.apache.xmpbox.XMPMetadata; import org.apache.xmpbox.xml.DomXmpParser; import org.apache.xmpbox.xml.XmpParsingException; import org.apache.xmpbox.xml.XmpSerializer; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -59,6 +58,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.PDFFile; @@ -69,17 +69,13 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RequestMapping("/api/v1/security") @Slf4j @Tag(name = "Security", description = "Security APIs") +@RequiredArgsConstructor public class GetInfoOnPDF { static ObjectMapper objectMapper = new ObjectMapper(); private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public GetInfoOnPDF(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - private static void addOutlinesToArray(PDOutlineItem outline, ArrayNode arrayNode) { if (outline == null) return; diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java b/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java index 386e938b9..830810628 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java @@ -5,7 +5,6 @@ import java.io.IOException; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.encryption.AccessPermission; import org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -17,6 +16,8 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.security.AddPasswordRequest; import stirling.software.SPDF.model.api.security.PDFPasswordRequest; import stirling.software.SPDF.service.CustomPDFDocumentFactory; @@ -25,15 +26,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @RequestMapping("/api/v1/security") @Tag(name = "Security", description = "Security APIs") +@RequiredArgsConstructor public class PasswordController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public PasswordController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/remove-password") @Operation( summary = "Remove password from a PDF file", diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java b/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java index deec98e4e..0c8a7f7e6 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java @@ -14,7 +14,6 @@ import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.PDPageTree; import org.apache.pdfbox.pdmodel.common.PDRectangle; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; @@ -28,6 +27,7 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.PDFText; @@ -45,15 +45,11 @@ import stirling.software.SPDF.utils.propertyeditor.StringToArrayListPropertyEdit @RequestMapping("/api/v1/security") @Slf4j @Tag(name = "Security", description = "Security APIs") +@RequiredArgsConstructor public class RedactController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public RedactController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor( diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java b/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java index ddead4338..5761e854f 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java @@ -7,7 +7,6 @@ import org.apache.pdfbox.pdmodel.PDDocumentCatalog; import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; import org.apache.pdfbox.pdmodel.interactive.form.PDField; import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -19,6 +18,8 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.PDFFile; import stirling.software.SPDF.service.CustomPDFDocumentFactory; import stirling.software.SPDF.utils.WebResponseUtils; @@ -26,15 +27,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @RequestMapping("/api/v1/security") @Tag(name = "Security", description = "Security APIs") +@RequiredArgsConstructor public class RemoveCertSignController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public RemoveCertSignController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/remove-cert-sign") @Operation( summary = "Remove digital signature from PDF", diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java b/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java index 9615c82af..42dbfef64 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java @@ -12,7 +12,6 @@ import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink; import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget; import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; import org.apache.pdfbox.pdmodel.interactive.form.PDField; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; @@ -24,6 +23,8 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.security.SanitizePdfRequest; import stirling.software.SPDF.service.CustomPDFDocumentFactory; import stirling.software.SPDF.utils.WebResponseUtils; @@ -31,15 +32,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @RequestMapping("/api/v1/security") @Tag(name = "Security", description = "Security APIs") +@RequiredArgsConstructor public class SanitizeController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public SanitizeController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/sanitize-pdf") @Operation( summary = "Sanitize a PDF file", diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java b/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java index 400bdf44a..361bc1e3f 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java @@ -21,7 +21,6 @@ import org.bouncycastle.cms.SignerInformation; import org.bouncycastle.cms.SignerInformationStore; import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; import org.bouncycastle.util.Store; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -33,6 +32,8 @@ import org.springframework.web.multipart.MultipartFile; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.security.SignatureValidationRequest; import stirling.software.SPDF.model.api.security.SignatureValidationResult; import stirling.software.SPDF.service.CertificateValidationService; @@ -41,19 +42,12 @@ import stirling.software.SPDF.service.CustomPDFDocumentFactory; @RestController @RequestMapping("/api/v1/security") @Tag(name = "Security", description = "Security APIs") +@RequiredArgsConstructor public class ValidateSignatureController { private final CustomPDFDocumentFactory pdfDocumentFactory; private final CertificateValidationService certValidationService; - @Autowired - public ValidateSignatureController( - CustomPDFDocumentFactory pdfDocumentFactory, - CertificateValidationService certValidationService) { - this.pdfDocumentFactory = pdfDocumentFactory; - this.certValidationService = certValidationService; - } - @Operation( summary = "Validate PDF Digital Signature", description = diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java b/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java index 7ed8a5a04..c477a88f8 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java @@ -22,7 +22,6 @@ import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState; import org.apache.pdfbox.util.Matrix; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -35,6 +34,8 @@ import io.github.pixee.security.Filenames; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.api.security.AddWatermarkRequest; import stirling.software.SPDF.service.CustomPDFDocumentFactory; import stirling.software.SPDF.utils.PdfUtils; @@ -43,15 +44,11 @@ import stirling.software.SPDF.utils.WebResponseUtils; @RestController @RequestMapping("/api/v1/security") @Tag(name = "Security", description = "Security APIs") +@RequiredArgsConstructor public class WatermarkController { private final CustomPDFDocumentFactory pdfDocumentFactory; - @Autowired - public WatermarkController(CustomPDFDocumentFactory pdfDocumentFactory) { - this.pdfDocumentFactory = pdfDocumentFactory; - } - @PostMapping(consumes = "multipart/form-data", value = "/add-watermark") @Operation( summary = "Add watermark to a PDF file", diff --git a/src/main/java/stirling/software/SPDF/controller/web/DatabaseWebController.java b/src/main/java/stirling/software/SPDF/controller/web/DatabaseWebController.java index c3bd4f2a3..738db8d89 100644 --- a/src/main/java/stirling/software/SPDF/controller/web/DatabaseWebController.java +++ b/src/main/java/stirling/software/SPDF/controller/web/DatabaseWebController.java @@ -12,19 +12,18 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.config.security.database.DatabaseService; import stirling.software.SPDF.utils.FileInfo; @Controller @Tag(name = "Database Management", description = "Database management and security APIs") +@RequiredArgsConstructor public class DatabaseWebController { private final DatabaseService databaseService; - public DatabaseWebController(DatabaseService databaseService) { - this.databaseService = databaseService; - } - @PreAuthorize("hasRole('ROLE_ADMIN')") @GetMapping("/database") public String database(HttpServletRequest request, Model model, Authentication authentication) { diff --git a/src/main/java/stirling/software/SPDF/controller/web/HomeWebController.java b/src/main/java/stirling/software/SPDF/controller/web/HomeWebController.java index 0fdd8e9ce..9a3b2b3e2 100644 --- a/src/main/java/stirling/software/SPDF/controller/web/HomeWebController.java +++ b/src/main/java/stirling/software/SPDF/controller/web/HomeWebController.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.oas.annotations.Hidden; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.ApplicationProperties; @@ -26,14 +27,11 @@ import stirling.software.SPDF.model.Dependency; @Controller @Slf4j +@RequiredArgsConstructor public class HomeWebController { private final ApplicationProperties applicationProperties; - public HomeWebController(ApplicationProperties applicationProperties) { - this.applicationProperties = applicationProperties; - } - @GetMapping("/about") @Hidden public String gameForm(Model model) { diff --git a/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java b/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java index 0fabeeae4..52c79073f 100644 --- a/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java +++ b/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java @@ -19,6 +19,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.config.EndpointInspector; @@ -29,6 +30,7 @@ import stirling.software.SPDF.model.ApplicationProperties; @RequestMapping("/api/v1/info") @Tag(name = "Info", description = "Info APIs") @Slf4j +@RequiredArgsConstructor public class MetricsController { private final ApplicationProperties applicationProperties; @@ -36,15 +38,6 @@ public class MetricsController { private final EndpointInspector endpointInspector; private boolean metricsEnabled; - public MetricsController( - ApplicationProperties applicationProperties, - MeterRegistry meterRegistry, - EndpointInspector endpointInspector) { - this.applicationProperties = applicationProperties; - this.meterRegistry = meterRegistry; - this.endpointInspector = endpointInspector; - } - @PostConstruct public void init() { Boolean metricsEnabled = applicationProperties.getMetrics().getEnabled(); diff --git a/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java b/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java index a4b2cc962..94fc85f82 100644 --- a/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java +++ b/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java @@ -13,19 +13,18 @@ import org.springframework.web.servlet.ModelAndView; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.model.ApplicationProperties; import stirling.software.SPDF.utils.CheckProgramInstall; @Controller @Tag(name = "Misc", description = "Miscellaneous APIs") +@RequiredArgsConstructor public class OtherWebController { private final ApplicationProperties applicationProperties; - public OtherWebController(ApplicationProperties applicationProperties) { - this.applicationProperties = applicationProperties; - } - @GetMapping("/compress-pdf") @Hidden public String compressPdfForm(Model model) { @@ -122,7 +121,7 @@ public class OtherWebController { return Arrays.stream(files) .filter(file -> file.getName().endsWith(".traineddata")) .map(file -> file.getName().replace(".traineddata", "")) - .filter(lang -> !lang.equalsIgnoreCase("osd")) + .filter(lang -> !"osd".equalsIgnoreCase(lang)) .sorted() .toList(); } diff --git a/src/main/java/stirling/software/SPDF/model/ApiEndpoint.java b/src/main/java/stirling/software/SPDF/model/ApiEndpoint.java index 0d707e3b1..dfb06f0d8 100644 --- a/src/main/java/stirling/software/SPDF/model/ApiEndpoint.java +++ b/src/main/java/stirling/software/SPDF/model/ApiEndpoint.java @@ -6,9 +6,9 @@ import java.util.Map; import com.fasterxml.jackson.databind.JsonNode; public class ApiEndpoint { - private String name; + private final String name; private Map parameters; - private String description; + private final String description; public ApiEndpoint(String name, JsonNode postNode) { this.name = name; diff --git a/src/main/java/stirling/software/SPDF/model/Authority.java b/src/main/java/stirling/software/SPDF/model/Authority.java index be250e8b8..4a0ed7255 100644 --- a/src/main/java/stirling/software/SPDF/model/Authority.java +++ b/src/main/java/stirling/software/SPDF/model/Authority.java @@ -2,10 +2,22 @@ package stirling.software.SPDF.model; import java.io.Serializable; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; + +import lombok.Getter; +import lombok.Setter; @Entity @Table(name = "authorities") +@Getter +@Setter public class Authority implements Serializable { private static final long serialVersionUID = 1L; @@ -28,28 +40,4 @@ public class Authority implements Serializable { this.user = user; user.getAuthorities().add(this); } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getAuthority() { - return authority; - } - - public void setAuthority(String authority) { - this.authority = authority; - } - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } } diff --git a/src/main/java/stirling/software/SPDF/model/PersistentLogin.java b/src/main/java/stirling/software/SPDF/model/PersistentLogin.java index cc94eea28..c0990199c 100644 --- a/src/main/java/stirling/software/SPDF/model/PersistentLogin.java +++ b/src/main/java/stirling/software/SPDF/model/PersistentLogin.java @@ -7,8 +7,11 @@ import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Table; +import lombok.Data; + @Entity @Table(name = "persistent_logins") +@Data public class PersistentLogin { @Id @@ -23,38 +26,4 @@ public class PersistentLogin { @Column(name = "last_used", nullable = false) private Date lastUsed; - - public String getSeries() { - return series; - } - - public void setSeries(String series) { - this.series = series; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getToken() { - return token; - } - - public void setToken(String token) { - this.token = token; - } - - public Date getLastUsed() { - return lastUsed; - } - - public void setLastUsed(Date lastUsed) { - this.lastUsed = lastUsed; - } - - // Getters, setters, etc. } diff --git a/src/main/java/stirling/software/SPDF/model/PipelineConfig.java b/src/main/java/stirling/software/SPDF/model/PipelineConfig.java index efb9b232c..b0d3a3e7d 100644 --- a/src/main/java/stirling/software/SPDF/model/PipelineConfig.java +++ b/src/main/java/stirling/software/SPDF/model/PipelineConfig.java @@ -4,6 +4,9 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@Data public class PipelineConfig { private String name; @@ -14,36 +17,4 @@ public class PipelineConfig { @JsonProperty("outputFileName") private String outputPattern; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public List getOperations() { - return operations; - } - - public void setOperations(List operations) { - this.operations = operations; - } - - public String getOutputDir() { - return outputDir; - } - - public void setOutputDir(String outputDir) { - this.outputDir = outputDir; - } - - public String getOutputPattern() { - return outputPattern; - } - - public void setOutputPattern(String outputPattern) { - this.outputPattern = outputPattern; - } } diff --git a/src/main/java/stirling/software/SPDF/model/PipelineOperation.java b/src/main/java/stirling/software/SPDF/model/PipelineOperation.java index f61835056..30a5ad52b 100644 --- a/src/main/java/stirling/software/SPDF/model/PipelineOperation.java +++ b/src/main/java/stirling/software/SPDF/model/PipelineOperation.java @@ -2,28 +2,10 @@ package stirling.software.SPDF.model; import java.util.Map; +import lombok.Data; + +@Data public class PipelineOperation { private String operation; private Map parameters; - - public String getOperation() { - return operation; - } - - public void setOperation(String operation) { - this.operation = operation; - } - - public Map getParameters() { - return parameters; - } - - public void setParameters(Map parameters) { - this.parameters = parameters; - } - - @Override - public String toString() { - return "PipelineOperation [operation=" + operation + ", parameters=" + parameters + "]"; - } } diff --git a/src/main/java/stirling/software/SPDF/model/Role.java b/src/main/java/stirling/software/SPDF/model/Role.java index 78f93d867..7d45e3da3 100644 --- a/src/main/java/stirling/software/SPDF/model/Role.java +++ b/src/main/java/stirling/software/SPDF/model/Role.java @@ -3,6 +3,11 @@ package stirling.software.SPDF.model; import java.util.LinkedHashMap; import java.util.Map; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor public enum Role { // Unlimited access @@ -33,13 +38,6 @@ public enum Role { private final int webCallsPerDay; private final String roleName; - Role(String roleId, int apiCallsPerDay, int webCallsPerDay, String roleName) { - this.roleId = roleId; - this.apiCallsPerDay = apiCallsPerDay; - this.webCallsPerDay = webCallsPerDay; - this.roleName = roleName; - } - public static String getRoleNameByRoleId(String roleId) { // Using the fromString method to get the Role enum based on the roleId Role role = fromString(roleId); @@ -65,20 +63,4 @@ public enum Role { } throw new IllegalArgumentException("No Role defined for id: " + roleId); } - - public String getRoleId() { - return roleId; - } - - public int getApiCallsPerDay() { - return apiCallsPerDay; - } - - public int getWebCallsPerDay() { - return webCallsPerDay; - } - - public String getRoleName() { - return roleName; - } } diff --git a/src/main/java/stirling/software/SPDF/model/User.java b/src/main/java/stirling/software/SPDF/model/User.java index 233347243..1eb9da991 100644 --- a/src/main/java/stirling/software/SPDF/model/User.java +++ b/src/main/java/stirling/software/SPDF/model/User.java @@ -9,8 +9,19 @@ import java.util.stream.Collectors; import jakarta.persistence.*; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + @Entity @Table(name = "users") +@NoArgsConstructor +@Getter +@Setter +@EqualsAndHashCode(onlyExplicitlyIncluded = true) +@ToString(onlyExplicitlyIncluded = true) public class User implements Serializable { private static final long serialVersionUID = 1L; @@ -63,76 +74,16 @@ public class User implements Serializable { this.isFirstLogin = isFirstLogin; } - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getApiKey() { - return apiKey; - } - - public void setApiKey(String apiKey) { - this.apiKey = apiKey; - } - - public Map getSettings() { - return settings; - } - - public void setSettings(Map settings) { - this.settings = settings; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public String getAuthenticationType() { - return authenticationType; - } - public void setAuthenticationType(AuthenticationType authenticationType) { this.authenticationType = authenticationType.toString().toLowerCase(); } - public Set getAuthorities() { - return authorities; - } - - public void setAuthorities(Set authorities) { - this.authorities = authorities; - } - public void addAuthorities(Set authorities) { this.authorities.addAll(authorities); } - public void addAuthority(Authority authorities) { - this.authorities.add(authorities); + public void addAuthority(Authority authority) { + this.authorities.add(authority); } public String getRolesAsString() { diff --git a/src/main/java/stirling/software/SPDF/model/api/GeneralFile.java b/src/main/java/stirling/software/SPDF/model/api/GeneralFile.java index 1c0581cd1..068978fac 100644 --- a/src/main/java/stirling/software/SPDF/model/api/GeneralFile.java +++ b/src/main/java/stirling/software/SPDF/model/api/GeneralFile.java @@ -6,11 +6,9 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; @Data @EqualsAndHashCode -@NoArgsConstructor public class GeneralFile { @Schema(description = "The input file") diff --git a/src/main/java/stirling/software/SPDF/model/api/HandleDataRequest.java b/src/main/java/stirling/software/SPDF/model/api/HandleDataRequest.java index d4a4a6bd6..27a0dc3bb 100644 --- a/src/main/java/stirling/software/SPDF/model/api/HandleDataRequest.java +++ b/src/main/java/stirling/software/SPDF/model/api/HandleDataRequest.java @@ -6,10 +6,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; @Data -@NoArgsConstructor @EqualsAndHashCode public class HandleDataRequest { diff --git a/src/main/java/stirling/software/SPDF/model/api/ImageFile.java b/src/main/java/stirling/software/SPDF/model/api/ImageFile.java index fdc0e6dcf..9719e2372 100644 --- a/src/main/java/stirling/software/SPDF/model/api/ImageFile.java +++ b/src/main/java/stirling/software/SPDF/model/api/ImageFile.java @@ -6,10 +6,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; @Data -@NoArgsConstructor @EqualsAndHashCode public class ImageFile { @Schema(description = "The input image file") diff --git a/src/main/java/stirling/software/SPDF/model/api/MultiplePDFFiles.java b/src/main/java/stirling/software/SPDF/model/api/MultiplePDFFiles.java index 00a34b748..fbca980e2 100644 --- a/src/main/java/stirling/software/SPDF/model/api/MultiplePDFFiles.java +++ b/src/main/java/stirling/software/SPDF/model/api/MultiplePDFFiles.java @@ -6,10 +6,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; @Data -@NoArgsConstructor @EqualsAndHashCode public class MultiplePDFFiles { @Schema(description = "The input PDF files", type = "array", format = "binary") diff --git a/src/main/java/stirling/software/SPDF/model/api/PDFComparison.java b/src/main/java/stirling/software/SPDF/model/api/PDFComparison.java index 47377188c..a2702c3f8 100644 --- a/src/main/java/stirling/software/SPDF/model/api/PDFComparison.java +++ b/src/main/java/stirling/software/SPDF/model/api/PDFComparison.java @@ -4,10 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; @Data -@NoArgsConstructor @EqualsAndHashCode(callSuper = true) public class PDFComparison extends PDFFile { diff --git a/src/main/java/stirling/software/SPDF/model/api/PDFComparisonAndCount.java b/src/main/java/stirling/software/SPDF/model/api/PDFComparisonAndCount.java index 04042bd81..d850b94ae 100644 --- a/src/main/java/stirling/software/SPDF/model/api/PDFComparisonAndCount.java +++ b/src/main/java/stirling/software/SPDF/model/api/PDFComparisonAndCount.java @@ -4,10 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; @Data -@NoArgsConstructor @EqualsAndHashCode(callSuper = true) public class PDFComparisonAndCount extends PDFComparison { @Schema(description = "Count") diff --git a/src/main/java/stirling/software/SPDF/model/api/PDFWithPageNums.java b/src/main/java/stirling/software/SPDF/model/api/PDFWithPageNums.java index 0148b7a72..39ace7f1e 100644 --- a/src/main/java/stirling/software/SPDF/model/api/PDFWithPageNums.java +++ b/src/main/java/stirling/software/SPDF/model/api/PDFWithPageNums.java @@ -10,14 +10,10 @@ import io.swagger.v3.oas.annotations.media.Schema.RequiredMode; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.utils.GeneralUtils; @Data -@NoArgsConstructor -@Slf4j @EqualsAndHashCode(callSuper = true) public class PDFWithPageNums extends PDFFile { @@ -32,8 +28,7 @@ public class PDFWithPageNums extends PDFFile { @Hidden public List getPageNumbersList(PDDocument doc, boolean oneBased) { - int pageCount = 0; - pageCount = doc.getNumberOfPages(); + int pageCount = doc.getNumberOfPages(); return GeneralUtils.parsePageList(pageNumbers, pageCount, oneBased); } } diff --git a/src/main/java/stirling/software/SPDF/model/api/SplitPdfByChaptersRequest.java b/src/main/java/stirling/software/SPDF/model/api/SplitPdfByChaptersRequest.java index 17ed03e89..03930009e 100644 --- a/src/main/java/stirling/software/SPDF/model/api/SplitPdfByChaptersRequest.java +++ b/src/main/java/stirling/software/SPDF/model/api/SplitPdfByChaptersRequest.java @@ -4,10 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; @Data -@NoArgsConstructor @EqualsAndHashCode(callSuper = false) public class SplitPdfByChaptersRequest extends PDFFile { @Schema(description = "Whether to include Metadata or not", example = "true") diff --git a/src/main/java/stirling/software/SPDF/model/api/SplitPdfBySectionsRequest.java b/src/main/java/stirling/software/SPDF/model/api/SplitPdfBySectionsRequest.java index 1ff834b4c..e8557c692 100644 --- a/src/main/java/stirling/software/SPDF/model/api/SplitPdfBySectionsRequest.java +++ b/src/main/java/stirling/software/SPDF/model/api/SplitPdfBySectionsRequest.java @@ -4,10 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; @Data -@NoArgsConstructor @EqualsAndHashCode(callSuper = true) public class SplitPdfBySectionsRequest extends PDFFile { @Schema(description = "Number of horizontal divisions for each PDF page", example = "2") diff --git a/src/main/java/stirling/software/SPDF/model/api/user/UpdateUserDetails.java b/src/main/java/stirling/software/SPDF/model/api/user/UpdateUserDetails.java index d8cbf7903..80dd2d14e 100644 --- a/src/main/java/stirling/software/SPDF/model/api/user/UpdateUserDetails.java +++ b/src/main/java/stirling/software/SPDF/model/api/user/UpdateUserDetails.java @@ -4,10 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; @Data -@NoArgsConstructor @EqualsAndHashCode(callSuper = true) public class UpdateUserDetails extends UpdateUserUsername { diff --git a/src/main/java/stirling/software/SPDF/model/api/user/UpdateUserUsername.java b/src/main/java/stirling/software/SPDF/model/api/user/UpdateUserUsername.java index 8b457605b..c0c14fc08 100644 --- a/src/main/java/stirling/software/SPDF/model/api/user/UpdateUserUsername.java +++ b/src/main/java/stirling/software/SPDF/model/api/user/UpdateUserUsername.java @@ -4,10 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; @Data -@NoArgsConstructor @EqualsAndHashCode(callSuper = true) public class UpdateUserUsername extends UsernameAndPass { diff --git a/src/main/java/stirling/software/SPDF/model/api/user/Username.java b/src/main/java/stirling/software/SPDF/model/api/user/Username.java index 167df1b1b..d29a544b7 100644 --- a/src/main/java/stirling/software/SPDF/model/api/user/Username.java +++ b/src/main/java/stirling/software/SPDF/model/api/user/Username.java @@ -4,11 +4,9 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; @Data @EqualsAndHashCode -@NoArgsConstructor public class Username { @Schema(description = "username of user") diff --git a/src/main/java/stirling/software/SPDF/model/api/user/UsernameAndPass.java b/src/main/java/stirling/software/SPDF/model/api/user/UsernameAndPass.java index d925eef1f..ec8f5c08a 100644 --- a/src/main/java/stirling/software/SPDF/model/api/user/UsernameAndPass.java +++ b/src/main/java/stirling/software/SPDF/model/api/user/UsernameAndPass.java @@ -4,10 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; @Data -@NoArgsConstructor @EqualsAndHashCode(callSuper = true) public class UsernameAndPass extends Username { diff --git a/src/main/java/stirling/software/SPDF/service/CustomPDFDocumentFactory.java b/src/main/java/stirling/software/SPDF/service/CustomPDFDocumentFactory.java index 3a3198fbf..e5bb50d73 100644 --- a/src/main/java/stirling/software/SPDF/service/CustomPDFDocumentFactory.java +++ b/src/main/java/stirling/software/SPDF/service/CustomPDFDocumentFactory.java @@ -19,6 +19,7 @@ import org.apache.pdfbox.pdmodel.PDDocument; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import stirling.software.SPDF.model.api.PDFFile; @@ -29,6 +30,7 @@ import stirling.software.SPDF.model.api.PDFFile; */ @Component @Slf4j +@RequiredArgsConstructor public class CustomPDFDocumentFactory { private final PdfMetadataService pdfMetadataService; @@ -63,10 +65,6 @@ public class CustomPDFDocumentFactory { // Counter for tracking temporary resources private static final AtomicLong tempCounter = new AtomicLong(0); - public CustomPDFDocumentFactory(PdfMetadataService pdfMetadataService) { - this.pdfMetadataService = pdfMetadataService; - } - /** * Main entry point for loading a PDF document from a file. Automatically selects the most * appropriate loading strategy. diff --git a/src/main/java/stirling/software/SPDF/service/MetricsAggregatorService.java b/src/main/java/stirling/software/SPDF/service/MetricsAggregatorService.java index 1a61d03bd..8cc0a243f 100644 --- a/src/main/java/stirling/software/SPDF/service/MetricsAggregatorService.java +++ b/src/main/java/stirling/software/SPDF/service/MetricsAggregatorService.java @@ -6,16 +6,18 @@ import java.util.concurrent.ConcurrentHashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.search.Search; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.config.EndpointInspector; @Service +@RequiredArgsConstructor public class MetricsAggregatorService { private static final Logger logger = LoggerFactory.getLogger(MetricsAggregatorService.class); @@ -24,16 +26,6 @@ public class MetricsAggregatorService { private final EndpointInspector endpointInspector; private final Map lastSentMetrics = new ConcurrentHashMap<>(); - @Autowired - public MetricsAggregatorService( - MeterRegistry meterRegistry, - PostHogService postHogService, - EndpointInspector endpointInspector) { - this.meterRegistry = meterRegistry; - this.postHogService = postHogService; - this.endpointInspector = endpointInspector; - } - @Scheduled(fixedRate = 7200000) // Run every 2 hours public void aggregateAndSendMetrics() { Map metrics = new HashMap<>(); diff --git a/src/main/java/stirling/software/SPDF/service/PdfMetadataService.java b/src/main/java/stirling/software/SPDF/service/PdfMetadataService.java index 173de33f4..b44ba59be 100644 --- a/src/main/java/stirling/software/SPDF/service/PdfMetadataService.java +++ b/src/main/java/stirling/software/SPDF/service/PdfMetadataService.java @@ -19,7 +19,6 @@ public class PdfMetadataService { private final UserServiceInterface userService; private final boolean runningProOrHigher; - @Autowired public PdfMetadataService( ApplicationProperties applicationProperties, @Qualifier("StirlingPDFLabel") String stirlingPDFLabel, diff --git a/src/main/java/stirling/software/SPDF/service/PostHogService.java b/src/main/java/stirling/software/SPDF/service/PostHogService.java index 51faba5be..69cb52061 100644 --- a/src/main/java/stirling/software/SPDF/service/PostHogService.java +++ b/src/main/java/stirling/software/SPDF/service/PostHogService.java @@ -29,7 +29,6 @@ public class PostHogService { private final Environment env; private boolean configDirMounted; - @Autowired public PostHogService( PostHog postHog, @Qualifier("UUID") String uuid, diff --git a/src/main/java/stirling/software/SPDF/service/misc/ReplaceAndInvertColorService.java b/src/main/java/stirling/software/SPDF/service/misc/ReplaceAndInvertColorService.java index 29df742a3..20c20eb7b 100644 --- a/src/main/java/stirling/software/SPDF/service/misc/ReplaceAndInvertColorService.java +++ b/src/main/java/stirling/software/SPDF/service/misc/ReplaceAndInvertColorService.java @@ -2,25 +2,22 @@ package stirling.software.SPDF.service.misc; import java.io.IOException; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.InputStreamResource; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; +import lombok.RequiredArgsConstructor; + import stirling.software.SPDF.Factories.ReplaceAndInvertColorFactory; import stirling.software.SPDF.model.api.misc.HighContrastColorCombination; import stirling.software.SPDF.model.api.misc.ReplaceAndInvert; import stirling.software.SPDF.utils.misc.ReplaceAndInvertColorStrategy; @Service +@RequiredArgsConstructor public class ReplaceAndInvertColorService { private ReplaceAndInvertColorFactory replaceAndInvertColorFactory; - @Autowired - public ReplaceAndInvertColorService(ReplaceAndInvertColorFactory replaceAndInvertColorFactory) { - this.replaceAndInvertColorFactory = replaceAndInvertColorFactory; - } - public InputStreamResource replaceAndInvertColor( MultipartFile file, ReplaceAndInvert replaceAndInvertOption, diff --git a/src/main/java/stirling/software/SPDF/utils/FileMonitor.java b/src/main/java/stirling/software/SPDF/utils/FileMonitor.java index 214f430e4..e0b3fc2cf 100644 --- a/src/main/java/stirling/software/SPDF/utils/FileMonitor.java +++ b/src/main/java/stirling/software/SPDF/utils/FileMonitor.java @@ -12,7 +12,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.function.Predicate; import java.util.stream.Stream; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -38,7 +37,6 @@ public class FileMonitor { * @param pathFilter the filter to apply to the paths, return true if the path should be * monitored, false otherwise */ - @Autowired public FileMonitor( @Qualifier("directoryFilter") Predicate pathFilter, RuntimePathConfig runtimePathConfig) From 29803562ebd808a36692c50f45010de4350ffce3 Mon Sep 17 00:00:00 2001 From: "pixeebot[bot]" <104101892+pixeebot[bot]@users.noreply.github.com> Date: Sat, 26 Apr 2025 23:25:03 +0100 Subject: [PATCH 4/5] (Snyk) Fixed finding: "Improper Neutralization of CRLF Sequences in HTTP Headers" (#3424) ## Remediation This change fixes "Improper Neutralization of CRLF Sequences in HTTP Headers" (id = java/HttpResponseSplitting) identified by Snyk. ## Details This change ensures that HTTP response header values can't contain newline characters, leaving you vulnerable to HTTP response splitting and other attacks. If malicious users can get newline characters into an HTTP response header, they can inject and forge new header values that look like they came from the server, and trick web gateways, proxies, and browsers. This leads to vulnerabilities like Cross-site Scripting (XSS), HTTP response splitting, and more attacks from there. Our change simply makes sure that if the string passed to be a new response header value is non-null, all the newline characters (CR and LF) will be removed: ```diff + import io.github.pixee.security.Newlines; ... String orderId = getUserOrderId(); - response.setHeader("X-Acme-Order-ID", orderId); + response.setHeader("X-Acme-Order-ID", Newlines.stripAll(orderId)); ``` Note: Many modern application servers will sanitize these values, but it's almost never specified in documentation, and thus there is little guarantee against regression. Given that, we still recommend this practice.
More reading * [https://cwe.mitre.org/data/definitions/113](https://cwe.mitre.org/data/definitions/113) * [https://www.netsparker.com/blog/web-security/crlf-http-header/](https://www.netsparker.com/blog/web-security/crlf-http-header/) * [https://owasp.org/www-community/attacks/HTTP_Response_Splitting](https://owasp.org/www-community/attacks/HTTP_Response_Splitting) * [https://regilero.github.io/security/english/2015/10/04/http_smuggling_in_2015_part_one/](https://regilero.github.io/security/english/2015/10/04/http_smuggling_in_2015_part_one/)
Co-authored-by: pixeebot[bot] <104101892+pixeebot[bot]@users.noreply.github.com> --- .../SPDF/config/security/UserBasedRateLimitingFilter.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/stirling/software/SPDF/config/security/UserBasedRateLimitingFilter.java b/src/main/java/stirling/software/SPDF/config/security/UserBasedRateLimitingFilter.java index 1c725c9f2..7bc0cc9bd 100644 --- a/src/main/java/stirling/software/SPDF/config/security/UserBasedRateLimitingFilter.java +++ b/src/main/java/stirling/software/SPDF/config/security/UserBasedRateLimitingFilter.java @@ -121,7 +121,7 @@ public class UserBasedRateLimitingFilter extends OncePerRequestFilter { if (probe.isConsumed()) { response.setHeader( "X-Rate-Limit-Remaining", - Newlines.stripAll(Long.toString(probe.getRemainingTokens()))); + stripNewlines(Newlines.stripAll(Long.toString(probe.getRemainingTokens())))); filterChain.doFilter(request, response); } else { long waitForRefill = probe.getNanosToWaitForRefill() / 1_000_000_000; @@ -141,4 +141,8 @@ public class UserBasedRateLimitingFilter extends OncePerRequestFilter { .build(); return Bucket.builder().addLimit(limit).build(); } + + private static String stripNewlines(final String s) { + return s.replaceAll("[\n\r]", ""); + } } From 0b81dfdf7c220ce3e7f6c546d23ce9fd9b651fc9 Mon Sep 17 00:00:00 2001 From: Ludy Date: Sun, 27 Apr 2025 17:17:07 +0200 Subject: [PATCH 5/5] Upgrade Gradle to 8.14 in CI Workflows and Gradle Wrapper (#3425) # Description of Changes This pull request upgrades the Gradle build system from version 8.12 to 8.14 across the Stirling-PDF project to enhance build stability, compatibility, and performance. The changes include: - **What was changed**: - Updated the Gradle wrapper version in `gradle/wrapper/gradle-wrapper.properties` from `8.12` to `8.14`. - Modified the `tasks.wrapper` configuration in `build.gradle` to specify `gradleVersion = "8.14"`. - Updated Gradle version references in GitHub Actions workflows (`multiOSReleases.yml`, `push-docker.yml`, `releaseArtifacts.yml`) from `8.12` to `8.14` to ensure consistent CI/CD builds. - **Why the change was made**: - Gradle 8.14 includes bug fixes, performance improvements, and enhanced compatibility with newer JDK versions (e.g., Java 17 and 21, as supported by Stirling-PDF). - Ensures alignment with the latest Gradle features and security patches, reducing potential build issues in development and CI/CD environments. - Supports the project's recommendation to use newer JDK versions (e.g., Java 21) and improves integration with the Foojay Toolchains Plugin. - **Challenges encountered**: - Verified compatibility of Gradle 8.14 with existing plugins (e.g., `org.springframework.boot`, `org.sonarqube`, `com.diffplug.spotless`) to ensure no breaking changes. - Tested CI/CD workflows to confirm that the updated Gradle version does not introduce failures in build, test, or deployment pipelines. - Ensured the Gradle wrapper distribution URL is correctly updated to avoid download issues. --- ## Checklist ### General - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [x] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md) (if applicable) - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [x] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing) for more details. --- .github/workflows/multiOSReleases.yml | 4 ++-- .github/workflows/push-docker.yml | 2 +- .github/workflows/releaseArtifacts.yml | 2 +- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 43583 -> 43764 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 6 +++--- gradlew.bat | 4 ++-- settings.gradle | 4 ++++ testing/test_webpages.sh | 12 ++++++------ 10 files changed, 21 insertions(+), 17 deletions(-) diff --git a/.github/workflows/multiOSReleases.yml b/.github/workflows/multiOSReleases.yml index 5f5d509bc..a2ffb5667 100644 --- a/.github/workflows/multiOSReleases.yml +++ b/.github/workflows/multiOSReleases.yml @@ -70,7 +70,7 @@ jobs: - uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1 with: - gradle-version: 8.12 + gradle-version: 8.14 - name: Generate jar (With Security=${{ matrix.enable_security }}) run: ./gradlew clean createExe @@ -158,7 +158,7 @@ jobs: - uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1 with: - gradle-version: 8.12 + gradle-version: 8.14 # Install Windows dependencies - name: Install WiX Toolset diff --git a/.github/workflows/push-docker.yml b/.github/workflows/push-docker.yml index 9d97e3225..dec93bad9 100644 --- a/.github/workflows/push-docker.yml +++ b/.github/workflows/push-docker.yml @@ -32,7 +32,7 @@ jobs: - uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1 with: - gradle-version: 8.12 + gradle-version: 8.14 - name: Run Gradle Command run: ./gradlew clean build diff --git a/.github/workflows/releaseArtifacts.yml b/.github/workflows/releaseArtifacts.yml index 225e5142b..f35d6f7c9 100644 --- a/.github/workflows/releaseArtifacts.yml +++ b/.github/workflows/releaseArtifacts.yml @@ -37,7 +37,7 @@ jobs: - uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1 with: - gradle-version: 8.12 + gradle-version: 8.14 - name: Generate jar (With Security=${{ matrix.enable_security }}) run: ./gradlew clean createExe diff --git a/build.gradle b/build.gradle index 078ea9071..c0adcf012 100644 --- a/build.gradle +++ b/build.gradle @@ -404,7 +404,7 @@ sonar { // rules=['unused-dependency'] // } tasks.wrapper { - gradleVersion = "8.12" + gradleVersion = "8.14" distributionType = Wrapper.DistributionType.ALL } //tasks.withType(JavaCompile) { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a4b76b9530d66f5e68d973ea569d8e19de379189..1b33c55baabb587c669f562ae36f953de2481846 100644 GIT binary patch delta 34943 zcmXuKV_+Rz)3%+)Y~1X)v28cDZQE*`9qyPrXx!Mg8{4+s*nWFo&-eXbzt+q-bFO1% zb$T* z+;w-h{ce+s>j$K)apmK~8t5)PdZP3^U%(^I<0#3(!6T+vfBowN0RfQ&0iMAo055!% z04}dC>M#Z2#PO7#|Fj;cQ$sH}E-n7nQM_V}mtmG_)(me#+~0gf?s@gam)iLoR#sr( zrR9fU_ofhp5j-5SLDQP{O+SuE)l8x9_(9@h%eY-t47J-KX-1(`hh#A6_Xs+4(pHhy zuZ1YS9axk`aYwXuq;YN>rYv|U`&U67f=tinhAD$+=o+MWXkx_;qIat_CS1o*=cIxs zIgeoK0TiIa7t`r%%feL8VieY63-Aakfi~qlE`d;ZOn8hFZFX|i^taCw6xbNLb2sOS z?PIeS%PgD)?bPB&LaQDF{PbxHrJQME<^cU5b!Hir(x32zy{YzNzE%sx;w=!C z_(A>eZXkQ1w@ASPXc|CWMNDP1kFQuMO>|1X;SHQS8w<@D;5C@L(3r^8qbbm$nTp%P z&I3Ey+ja9;ZiMbopUNc2txS9$Jf8UGS3*}Y3??(vZYLfm($WlpUGEUgQ52v@AD<~Y z#|B=mpCPt3QR%gX*c^SX>9dEqck79JX+gVPH87~q0-T;ota!lQWdt3C-wY1Ud}!j8 z*2x5$^dsTkXj}%PNKs1YzwK$-gu*lxq<&ko(qrQ_na(82lQ$ z7^0Pgg@Shn!UKTD4R}yGxefP2{8sZ~QZY)cj*SF6AlvE;^5oK=S}FEK(9qHuq|Cm! zx6ILQBsRu(=t1NRTecirX3Iv$-BkLxn^Zk|sV3^MJ1YKJxm>A+nk*r5h=>wW*J|pB zgDS%&VgnF~(sw)beMXXQ8{ncKX;A;_VLcq}Bw1EJj~-AdA=1IGrNHEh+BtIcoV+Te z_sCtBdKv(0wjY{3#hg9nf!*dpV5s7ZvNYEciEp2Rd5P#UudfqXysHiXo`pt27R?Rk zOAWL-dsa+raNw9^2NLZ#Wc^xI=E5Gwz~_<&*jqz0-AVd;EAvnm^&4Ca9bGzM_%(n{>je5hGNjCpZJ%5#Z3&4}f3I1P!6?)d65 z-~d}g{g!&`LkFK9$)f9KB?`oO{a0VXFm1`W{w5bAIC5CsyOV=q-Q7Z8YSmyo;$T?K za96q@djtok=r#TdUkd#%`|QlBywo>ifG69&;k%Ahfic6drRP;K{V8ea_t2qbY48uYWlB3Hf6hnqsCO?kYFhV+{i> zo&AE+)$%ag^)ijm!~gU78tD%tB63b_tbv9gfWzS&$r@i4q|PM+!hS+o+DpKfnnSe{ zewFbI3Jc0?=Vz}3>KmVj$qTWkoUS8@k63XRP2m^e50x-5PU<4X!I#q(zj@EyT9K_E z9P%@Sy6Mq`xD<-E!-<3@MLp2Dq8`x}F?@}V6E#A9v6xm%@x1U3>OoFY{fX5qpxngY z+=2HbnEErBv~!yl%f`Eq2%&K%JTwgN1y@FZ#=ai+TFMFlG?UV{M1#%uCi#Knkb_h| z&ivG$>~NQ4Ou2-gy=8JdRe8`nJDsqYYs?)(LJkJ}NHOj|3gZxVQJWWp>+`H?8$$J5 z*_)+tlyII%x#dId3w(oXo`YEm^-|tFNNj-0rbEuUc2-=pZDk7fxWUlw;|@M9s1 zmK9*C)1Q?F5@NPUJOYOAe`GHnYB%G37_sg3dxAttqLs6Bro)4z ziy8j%C7KKDNL8r#Oj6!IHx|N(?%Zvo31y4;*L1%_KJh$v$6XhFkw*E|fEu9`or?JD_ z13X4g92;TZm0jA0!2R5qPD$W^U z`5XK|Y^27y_Q%D>wWGtF=K00-N0;=svka>o`(;~dOS(eT0gwsP{=Rq+-e2Ajq?D<)zww5V36u6^Ta8YT4cDaw} zfuGnhr_5?)D*1+*q<3tVhg(AsKhR1Di=nsJzt_si+)uac_7zx_pl#t(dh816IM zvToHR%D)$!Zj4Q^$s8A%HLRYa>q9dpbh=*kcF7nkM0RhMIOGq^7Tgn|Fvs)A% zznI7nlbWoA2=rHHbUZ4PJMXf{T$@>W1Tt4lb|Or4L;O!oFj8Op8KEE`^x^*VSJ`9~ z;Pe~{V3x*-2c|jBrvSV8s+*Y3VqFKa@Napr#JAd}4l7;sgn|Q#M!(<|IX1<)z!AC3 zv<5YpN58Fs4NYi|ndYcb=jVO6Ztpwd={@3Yp6orUYe6EG#s{qhX+L^7zMK+@cX1hh?gbp56>jX*_Z|2u9 zb*glt!xK>j!LyLnFtxs&1SLkyiL%xbMqgxywI-U*XV%%qwa5oiufFerY!wn*GgMq` zZ6mFf8MukDPHVaCQk#oyg^dhl*9p@Jc+4Q9+0iv?{}=}+&=>n+q{o z#rEZ<&Ku65y+1eRHwcl3G7bR`e{&~^fGg|0))$uW?B@;_sWSls!ctnjH6ykmM8WJx};hvdXZ>YKLS($5`yBK38HULv}&PKRo9k zdFzj>`CDIUbq8GxeIJ?8=61G-XO?7dYZ;xqtlG?qr`wzbh7YyaD=>eup7bVH`q*N5 z)0&n)!*wW$G<3A&l$vJ^Z-%1^NF$n3iPgqr6Yn_SsAsFQw?9fj z&AvH|_-6zethC3^$mLF7mF$mTKT<_$kbV6jMK0f0UonRN_cY?yM6v&IosO?RN=h z{IqdUJvZd#@5qsr_1xVnaRr`ba-7MyU4<_XjIbr$PmPBYO6rLrxC`|5MN zD8ae4rTxau=7125zw|TQsJpqm`~hLs@w_iUd%eMY6IR9{(?;$f^?`&l?U%JfX%JyV z$IdA`V)5CkvPA0yljj4!Ja&Hjx`zIkg_ceQ;4)vhoyBeW$3D<_LDR~M-DPzQQ?&!L*PUNb^moIz|QXB=S z9^9NnEpF+>_Oh6+Xr55ZLJ7`V=H}@D<70NiNGH{~^QE-U)*Sg@O}M|%{Rcpn z{0nD@D%@8!dE*mndd2g!-q9;)jb=IUED<(Pxh`9B>V3z#f>82~&CVZASC?|;C-VKy zJU35T|3jd(p8F|#n@T~Wh2l1yURI=LC>Uj_!8i7-DE_IaSKIMAx`WMEq8kN%8sAx% zOQs~R1v12(=_ghVxzylsYZum-%8QmjM3-s2V!jY|w#ccP)}OSW?MWhNu@o-t0eTg{ zyy`}x+}GObZC(k>-upb2C6#S*NOfWbKEyReP%gay8MT!pJpsx4jwCu%>7%sY}1L6Vybj_P+;yP`YS92 z^o_G!Gr_NP!ixe7d&82H&achfi83L;le3Fs?u%E*xbeOKkJr7mp=)RXjZF;h*hR<= zP_cs1hjc}0JlHal=enmG&G8wsn%Sm$5Wcgs=Zc}}A%3i6_<4k_`-$k2E5f6QV{a$V zg3VZO36o^w5q`q2ASwJw#?n7pBJyGt3R<`Sd8d|52=h&`|CPq&1Cz&42rRCHNjDZL z$}Y*L+#N;!K2Ov){~fmQM8hVYzj3H@{yS>?q3QhhDHWfNAJ#q@qko|rhlaGG4Qrvh zmHpmg&7YvgRuI|i78-{)|wFx(R^_ z{ag(}Kbbbx=UW42sAu}kg3yB#96dJlOB{+or<(51ylVwpXII7Hrlztq!pefQ?6pQhqSb76y=sQx zOC-swAJaqnL_ok{74u_IHojFk;RSSFfjdLrfqq{syUxA$Ld6D2#TMX(Phf~dvSuuX zmN2xzjwZxWHmbvK2M#OhE#{`urOzs=>%ku}nxymK-dB~smas?Z(YM^>x#K)M@?<&L zeagMnj!XK4=Mid$NvJ+JfSjvc`4rX9mTo^+iFs0q7ntZ{gfU3oSAbK_yzW3WA^`6x zWgPSLXlEVvh!G^fOzZ-O{C_v;V6=;DE+ZqRT4mbCq}xeQ0o z98Cho%25r#!cT_ozTd~FK^@AB3OnrAAEDI4==}#I_v}iw0nhA{y99mFRG*1kxFkZP z+are- z8D|3WoYE>s0<=h)^)0>^up+nPeu}Sv-A($6t3AUedFczOLn;NW5_xM0tMvvrOSZ}) zA2YG1m4GxLAHZ5k>%}pHYtf-caXMGcYmH8ZPLX9VCew0;@Pi-8zkH^#}Cu$%FmKJb=!)Twj!PgBmY0+>VUsyyT}Jy>vMt zo<^5lmPo5Jt-=)z2-F{2{jB{CpW2JDj%~JnP*rq^=(okNQpH=}#{kqMUw{&=e-5;G z!FwJVQTDS7YGL&|=vJ+xhg{dMika2m2A#l@$PazLQ<6$GLC+>4B37`4aW3&MgENJ% z#*tOQsg{>zmcuSgU?peLA}!Rlu&K3LTc@drSBaI?91dK75;_`(V`NHjkMj``jwjJx zcm_!liUxn=^!~0|#{g2#AuX9%;GTBq&k+Jz!~Cc+r?S}y=Q1okG0PRIi3C3wgP8F| zO2jcmnVbGXp*Mu&e#a9Q5a}w7$sITx@)8b}sh(v9#V(H$3GLHF@k!Wh+)kNueq;+r zFtj+^b1TQe?R#Y8{m!7~e6%83hbPKoizd2LIg3yS5=X2HE^l4_|(2q#LB zeNv&njrS$?=zzG?0Min#kY+3A)H1uMfogMYSm|vT%3i<_d9X&~N*ZCL4iB@YaJuo; zq}-;EGx~T43kq-UHmTn!@sc z3bwcs$rp?~73h*uZl_ysD*WK3_PS1G3N^t3U=KoRm_Gz@C?M>+x9HRMk(cA4m&L`! z=Lb~4*9zt*SHJgsAMAcTy*!1W^B>4T_doWvNw7UwmyA=Wq&kE{*GVHp9Yk5goUO;k zVb_3ARrFPG;&>Jv@P&`z%}t!*M|2127pm{S)gs~f_ID^lOH@nIW9DgU$=FjqNW0pv z&GYdoxe@)RAWWx^j|$N}sj*p)_bFpk`Y=NilvsI(>!Z&KBo&I+wb*kM5Vvkkr#;q< z3CobbF+GJ#MxL?rMldP0@XiC~yQCR57=wW_<$j!SY*$5J+^v{Pn!1{&@R-lHCiK8@ z&O=XQ=V?hjM;h&qCitHmHKJ_$=`v%;jixnQrve^x9{ykWs(;!Q9mlr#{VYVE93oaW z&z+vBD}!tBghkriZy7gX7xJp8c}ajR4;JDu^0#RdQo2itM^~uc==~eBgwx5-m7vLj zP)vE#k%~*N$bT#^>(C1sohq+DwAC{U*z(D)qjgghKKSy#$dPih`R09rfbfI-FLE!` zn!tg71Wr(D7ZV*4R@GqG&7)2K*Zc6_CMJoGu#Yc>9D#{eyZ>u-mrWG@4Hk(je3lnH zu9qvXdq+!`5R1mlzWjV^jvaHl>-^Z+g^s5dy49yem$0$>341=EGuOY=W5PCFBTbNN^19iIQ57C3KcV}z~z#Rvngs#j;g2gswC(TLWlViYW}tB5T#g4 z%vDUYTo1@+&zE&`P%fXc^@prE5z;E@;; zKtpEFYftJq-c0sD6lKYoEQ;O1X4uFZZ;3gdgfAKqIc=Dj6>unXAdM}DD*@a5LHk~o zyJjW@aK;XG%qr<)7Rqh7NdUpnTR6jc;6{FKcK_v_#h{IO{mez>^^70DAWB5whqq!J zevvLUotE;I?IWWf!ieJ-Hx`TqY5)ND>K0NCb7IW40Jk*J* z^#m%kIA~Go2=R|y5zM|*ehJxyuX;lOQZkArKVbQV(XmidUH|8U^q`wP(7%F}=uG}U z2~&~CLebE`c%SCdeU(l&hryL~+Y)6I^d@|||6F15IAGo`G+CdVf zc+!EycZnQH)OBE zyTd8k{(_v9d2}osA$*>Q>Q&OB(7ShxA$}p8ChVnYlXl5My$HlVx@ATprrj0}6)ycK zcQy#bwOms1CnS+xd26}k?J;WI{HR_U+1T^I!$B^S=pJkT705QaMF88VJp!s%`?y9z8f$&Xw(A}3u_(n5G{!)yH&zN)S?c1$SZlo>XieJ zyEFa>_p9B*cY){ct8=dq>uQTf# zd4vB4)(ebwQHlSAu}(6GCe28H32pz^}l%Zqs;Yl|B=l2d9HrCcUf%wxLYs4CBqJ#{gz*u6V$>?9IT@uSf~2Rgk6CNw;C21ZbNkm>ZTc@2zeOSXVE^>i5!2>t%!1cI z{FZA`*o4=dTDG3&{v$3xVr%g;3d(!SFJU}w6x_Re(ohlni)I54Wg{t zWLK{A(}qEIH@pamgtr3serA{THlp_IR(gt0CFguk={|Ochh10)7UV4DcnO7fvL<=x z^WCMg_TI?U8(loaUnAe+Nc9I1JIO#_C`=kJG(&wy%Cr9vRFcY9^8{A3A>GuSW~Zk( zMA#t~0Dw?;3^Ue|lhSp4p%YvYmw-&3ey3}+{6Uhz?l1D|6nYNok6?4N_C!OSR=QtS z2X&QtWlkZshPo#-dXBOlSqh3D;#*_`hyohR>vl$W+QC>HPOs0zwHKN`?zIKqCTw&w&NUGNS|abulHe{D+{q z`WvLw?C4K97cd}6V6f2NtfIAO;=c>qi^+y4#oMjK?5Hy9$Tg1#S~Cxoo-Zdpnt2kG^n}`9)Df-Spvx&Oi+6xXT=N*0l|d`p!ZU ziQo9$y}PYIF~Zqh^?6QZ8YS*JtD^gynifSLMlVYRhBi*f-mJFS<>l%5sp5$V$p*X9?V-0r4bKYvo3n@XkCm4vO-_v? zOsLkR?)>ogb>Ys*m^2>*6%Db0!J?Qvpyd+ODlbslPci9r#W>d~%vcU7J_V;#Um1+` zG0>Q$TrOLUF0%a3g=PaCdQVoUUWXgk>($39-P;tusnMlJ=Dz}#S|E== zl6b3bbYaYguw3Bpv|O(YR2aBk?(jo+QqN*^6f0x+to-@2uj!nu6X{qLK>*PxM!i0C zZwrQ}prOw6Ghz?ApvM`!L3Dzc@6mp<2hO0y{_`lqtt!FcUmBG+PBwl?>0Mwu)Ey{L zU;A{ywkT}jCZpPKH4`_o0$#4*^L7=29%)~!L4*czG!bAva#7ZCDR|6@lBE&cyy5eE zlKHwzv7R9gKZTF<8}3*8uVtI)!HE%AZRD-iW!AJI7oY43@9Z$0^MO@Egj1c?o(BwF ziz1|k#WOgAG?^r1 z>+p=DK?cA-RLIvcdmwq$q?R;ina0SPj@;Mus}W_V2xHnYhOq~=sxzA`yTUOsJ`8`VOSTE=IZ!x`cZYqHbgPijF>J>N7( zqbNsHK50vkB1NI52gyb^PflpU0DRw{&v7Y}Hy2>pV@W2f1EOd2j;H?|WiV%2?Dk7u zS(NrEUDl81<}yY9J#OCwM)N?x&PB-%1{oD*`_ZLiBJ=16uR{n+Lk~!t(&9U#>ZfVd8Iqn&idGd>uo?L@sjm>c|Lk z12d3Y>N9U`342@xaHl&Q@oE5V-f$s`04q983f0#m_WF=X_A89W8C#{uCdTNUZ+))$ zakPyNU)?MDayCKxWh0(-v~1rd8FxocW=Dc6B1%N4^SgQj$?ZMoAMQ-35)IMgf&)M?c@}4QG7=DTq{nHc7yp=CZ z1dh~VkK%OTr23U1mJ*a-DxX0Psvh_13t^YcPl9t?_^$pPEhhwGp}s~f=GFR;4@;@f z@B;R1U6Df?yl#Y=BgYTlP&<|8K27||rx_?{s|L);GM3^{Nn8HZp zFqxiG6s3Nb;PW3O=u;(-o(*q!^2i)jHY%N@;O5Hder~_@$zh4xG#-7?#S^-&M~yc} zh5Y=ltLBnTzt;Y%YNqi2d1M1LOz?MJbZ|Nc6>x19&l_S*2Rgk$DhaP7Y-C)4_uPzf zQm)OY)$AFfE1(0SxkbbN4}CHnlU`RqYFGIE7S9ipx_Q0vkE5JRq4Uc%zV7$?y(x$y zV^)5zwjH~+4?xN z9s@x~w`C_cS}khfI14K4Xgn^iuBxkd^u}3cY=VZI@-8iWHolPtt?JD5lZ1V=@g6yR zj0>bd7Z(dw+@)v#r!xpZaAxgT?4Ton(h`0}fkfF!ZDSu{f*r#{ZRp^oOrO3iB|Fa- z;|+PpW5JKZxJ-kjHf`-7ohmnO=a)Xl9lhI8&$)g6R#6PBIN$QSC8kT=4zj?w&=`!qjkCvvz;ypOfR7P)w^ z-7LFhXd6GLrFa_vGLwR5MRvcV*(r!NhQ@}T-ikBGy!fHaiePD$iA{|Q1$kct2`qHz z6nAyERuqvM6i2^?g@w7W2LLr~3s?pBDk6ce8@CxV;b%4%-rXK-GOk+($sSNK;_FBku zm89B}tpzL-x{dPS-IAjwyL*t7N%7~2E)9OsWJJWHc|}BNa5Xwdx(j7i7AmZhs?#zi z5{y$uQdx?O8x3>+5MR05HwUa-YZa*|UVLOb`T)KHk|~Gmwx8MfBUtM|afuM$0wb7m zR+_lU9=W~Y$uNlxt&(@&1;6t!r69A|W%;k3-%SzLlBzc0 z`b?Jmo`8{LI=d|I3JDAa|iK*D6=I_3q?%xFSLg1 zI^!pA=K}l1joBBj8aa8XHp^;Lf`9xNa&Cv+twW&$_HAwZfHrVcNUrRccn_ z1+L!z$k@LK28nc1VB|Fbwm$wO;B~yEdww1EUn|s&{-Tu;@$d94BLL(OQYx|aCa|&2WPT{qJzbNU!ep>j){o5=6le6 z>~Amqs+mCuOR2)aB!#sK5fuui7LsO!Qzl)lz?Lm!QoQFWbNIkfdkrn|)YbSu8WwxZ zO{}a~wE2Cu)`a3X+KI#LHm(Mi+}bOB6@N~H2}Y)e*}w8_z^Sx`c?CWvu*2{K#yqGo zx!Cu*+8&tdw!eiKqZIQlJg5Cb^hZ^Zh~Mb0l(4m4hc1mP&>oTdt7eS-bEz8mU~oObme{^%56|ou~EPOSFBa7VpUZC z0gVc<@IUeo~q)&?o zU@=bz-qfWm)&0Qn@W_fc9{wx={&-#8>0xHJ-+Ijl#P&1qB-%*KUU*DCPkKCLzF*#t z0U_vrk1(&Vwy6Vm8@#Th3J5J%5ZWd)G0mifB3onY8dA&%g6Hir5gqMH|hnEBL0VVvl~aJjdljF$-X@a zMg=J-bI?2LGw-8mHVF7Jbsk1K4LgWi7U>~QovGT2*t^U&XF#iDs_E$~G+t;U;tZn_@73Y6x>vU%x` z6?l`$@U4JYYe#|GcI^f+rsy|MdB|`PQunKSKkja4IGtj9G6buN&ZSnYi|ieaf{k5q z@ABM@!S(A6Y}Sv~YJcB;9JeqsM|-fPIZZfOgc*FSzIpEdT=YYT(R(z{(~X&x%6ZM1 zY0(|PepBl4dK*@9n6@`rUMd)K^^0!^?U-1rrB*b?LEZe<5taFp!NoC^lc>}YUy?5FjT9tFmC+%%DYNa+L zWr)zMB%y_6L{S%;dk6bJPO!wmT=wPPK1b$%+ffWcO8;2T+7C28T?{!96{%d`0G~j3 z)6g<%$dC{vAKJ22nY)fnxlD>P_Xb&@>wrG+ZpfQ%RX=R2kd@bH3N*M8=BO zi|Z$Z5e`0NcU5&aN_DST8O@4v3vroq3t<_5hBX;d)*AJgWPb~p=qx4}^Ms6pgyY`) zu z^|u7XSP^~b1)*61r(}zd!JOny@$KviSp>L|jSR!u*1IgKwId5jmAi2`qe%u+XCTwU z;a62_a~Z}TqDJ?6lje5hblv1f1(6U@kWpc)z|&nRBV*UIieQR{Rru*|$L2SzxtL&| z7abeg@xniYhexYoN6zxY{nI^*xKW0Gz8D~}tE>O4iCkpWn8wt4?S`(Ftv?<8vIvbw z(FFd5`p4~#m<(3uv2+pv7uVC$R(iZuhnxFEY{o}BxPg2nYK zzOjuMR`}t3{8z#zfLXy||4JCt|1nv5VFjS#|JEhRLI>(-;Rh~J7gK{as*K1{IJ%7F zoZnXx&Y54ABfp9q!HDWAJlvFFdSC9}J*llUYXFDN8meEa<0}s z8M~X?%iKLB$*-a}G_$rTh;U{M0vc<}N#PVAE1vQdL#9a-`uH3*cbJZ~u9ag-fny$i z8aCs;3E85mgVK&vWM6}FH9o^WI#G!=%YOB#gT`1^VttnSVf4$YKja@-;zARB-`7v< z*imICw^KX73Gq-go6e?w^os0U0HSxH>60JLWhFbDeGT&Z$d3;9NWy;WvICuoZaKMi z=UvTpLDrtssbhiK&A3EuWf6!)>$sUlRcn5?Pk^OCtvApB=6suN42uKN-Xs7u7EjXh zG|>-1Rp>w1KB%sI*b5dGwFbuHNN=|})sR(dekHBL=>I~l@Nao%H=w0q==`3$zP>!I zmgoBoi7ylm<9Fw6s3&T%wJ%>VQmx(H)!iq?ABhdSzitwHlFNGcBW4sc&9DmTThb^qz`diS`xzQT# zhZff!yj2#rS>yfS5?}{inV5BfcZw zF5uh!Z8b#76;GcBDp7^zWtzQ%J;D}es(iWWWQNA{SvyhO`X8oyNL?j8Afn=x(zHct z7)3c%RKTPAyKS0gwVpGLqR2_%EowBpk>rW}MFfsR9>#2aOL!HKZtg$bAOe+#;;w?3*If zQk=HPWSlX7cF?h1PVE1D>LL{K&Ze4d!#Y2qN+^N-`~RG(O^Gjg~EsZbW^ipD9*+uf$K4Cq=H zxnYj(#+^eUa_1nRDkJJH|9$VB>+n4c)jji1MPz$dV4Ojf;)iYjgw#m+4puPdwgLSj zubNnwfz=z1DqFmy@X!!7D}kTo6yBjVFYT`CisjAgjS^cO%|(B2vzWb5PcrnxTK4xu zm?ZZkCy>+)-K8*)fo5JCWa@}^R!iI}a6OA*S&ibX6V zKk0=}K_M7m$#QEMW=_j=4tDXgH{_l5u?oFF?CXKmk73#~&>ha8CH{7jDKT2WoJ&sW zD1wk_C4Q6m{-YEWeAg*gP5`2Yl>4S@DAbob$M?&Gk2@2%+H*H2wu_)XL3fn{D8ljl zh41$!&_(kR($}4zJj3?zH-A0f2$4;9tH|N9XT48P;?coFH~9`z4S_35{xiUZC4&-3 zo3Yt|ee&RI&qBF zW$mPrwbqtHO$6De21%1=8zUX5=uMV*>#k-H>d5vP zz8OPyI|HLGKn`U2i>k8-dUX}5DJ(|Oy>)cK%QOwU>>~+Wn?bp?yFpx?yE;9q{;DTa$CFGK2S&xDNk$24GuzOgK{np ztsuRfjYmLjvhn$}jK3F_+!AtM`LVw=u&FUIGIU6>0@nqZq~REsb}_1w!VB5-wbS#J zYPBNKKJcnu^LTORcjX|sa8KU?rH5RRhfJ&l7@AtLVi|n8R7-?$+OVx!2BrQCD8{a)Kc#rtcWIC2(YYu=0edjgP9sFpp0=(eKUE2*>jc+n@q? zKTY!?h-S?Ms1kNuRAjowlnTQZF=#1S3XPx<()Wc1>r=QN?#W;6OL z2|Y0fxO0y=?Qi#F4?$+-Qpt&J>-JT?;d6ITN&7R`s4l(v17J7rOD3#Mu@anT`A z88>nZmkgV5o2{_IQ^TOFu9g}ImZrc~3yltx&sdaLvM=bAFpUK=XGx*;5U2#%A{^-G zEpT(GF(}NVJNzn$I*!S`&mA<1j#FEw4`lJ|^Ii?VA+!l%tC)`Q6kS&`LD*!rp)SSZ z!fOJa=BWFG0rWJE<~c2SnT{ykD23&sE?h7iTM20!s3!XMY*WJK_oA3FzU zScKW==wTvjelr=iu2>(0OLprW-Pv$m4wZ7v>;gB4M5m0(gOK>_@aIy}t&Y`H8crZ% zbo1L-*2^hdvzq`~_{<=PT=3jZ#UgMI*bQbOCzf~T53X2F9_QJ+KHwwQCpU%g4AGP z7i4m>KYOFyVXw`L5P#h};Q56X@OHZ-P-1qabm)G~GS>9sP0ToSI#43Q5iDCjG6r<1 zyJZa^U&>SXTW+bvJNB5oHW0xNpCGimZgaFJSb^??Uz1|jbXP-h<65N`CgZYX8jM3^ zSJ2tNSxr8>9)`mMi8nHw1aDz_?+ZRuMO@tou|Q9z11zdD#ka!jZfeXi(bGK&_vVQ^ z?b#6fYLRy70Mb9>3LcE``^rMcoxj~!hvBT%&cQK#L#nhF)C)iw(B$hY1fwak15v#J z-<0Kg=Zh1uk_^yGnO~&Hl|4?14*DFz9!$a(EAbT!5(<}0xUlYlC%`_JfofaWqfWNEfhlbLb2Ds@#m_oKXUJ0 zdSUbdO-BOnM!b2U2o3t3AQ&HGTzjL}LBTpwM2|gf3<(USB~4unKD6^_G>?@N%R2V zE+a}P6(vB@x|W>|ol!d5vws)e>m=0+2Y~#n1%kb=NXlT+^$#v9N z0Lt8wQ#?o)_j$PRavtm~z!aRPQ85^H^}u0bjlfDm(!3xG(oMQY?(DW6m1QdXq-PG; z7jW?rNj(vW&SZZ>B^q=2mU!8NLql4|nTI;pSkw9gbip(A^U<9DVj%Sjd-T0)ldwku z!O)$tFvVGRJnSI!t*v+U;QlSXfMu%J>v5B@Rq<`V$DQ>YTCkc=so?hUx&dda4;A1r z>~5vZ0E0M|B&lv|71*mTuRX`GB3G>9RzF7}+2HIgGrV-?p|bN%&4si|xxb+z1S}F2 zOBQ37uO?>1n_T3UF8nYp?uWnU&+53X|N94hR8WunjZ{}VH({S=x7sRbdLq7vyftJ? z2@;dF{)x|0nI%sYQ|%pe)%r zxP>}6S+ylPH{St~1KGov%?}z^A&&&(B(s+ngv{wKZ_L(*D^+nzoie`$NZ_*#zQ@&T zeLY@LZ5;akVZ}L=Qc=fIphsO^5%YJ0FQWW3*3|ahxk16yr=ZgTqunNMFFko^CZVSh zlk<_(ZLf{~ks&04%zz`tNla=O_`5r6W>d-%mdkEryHLIgIZyrq88$=4=Im4xR_}|) zZ!?V3+6QZ7$+wYJ=>nqKQ2L_gKw%=9`ds2Mdo6`avM-uO$tdP}7Jandkx0}XQhkn# zzq9uFBxvJ^#%sW$s)6J+j5 zXmAN{4mTo60nJnc2C6XtOBsVbJYc5&a0nZ|e?0yj+kThaCezk^Cm!F<|A=cu`uO@u zMai;5H6<@WD$n?-1{?Pzr2mF?F||EI+58#(N9dB2U*+$o$gl7(T>0jTu!?94mCA7^eb%}7cOyZN?nfVx+L$x~x>^tyJj$vmKZOXBKkU?mdopygE`0+rPi zx3F#q)PBC|6M{n@2|m%_24@G{?ql$@S=PPaEh1sG9v zxo35;K!!nAr&^P|c$6z+&vUa@eX|Uw&nednN1SCQSFNx={#kvzFb``4ixf3m zIY=2lKDmS2WGQx#gfP0BOAD4i?UoNdWtRz&Q=#>Y75@;X*z^@rxbLVa`YnIz{oaTE zNGmThd0`N_?*0!a>=f<^TOdF{&|-km!E9iB4IUs0KsvY|y6}%EN>L%XAjjOs+WGAJ z=wAmEmK)JGoI&Uq$`1%&(sh$n^lmT{o9pDd>t(CQ;o9Sr;gFtdZ>-qZg7jbc*P~uh_&U$wOO;{P3h!F3|a}dH-WoGGsXGBvB2c7p<>_CnJAYP}_#gD0t)$ z$Is_In%83bCJkJDij^-Lbnh)JKexs8f3E|dDy=BUEES;}7{*+oxV&iNODhNv#y<$} z=-mY})V@*#j#N6^A*B940E$3$zfmk;3ReX3DO;=d*_(!|f4FL$#0mL1ToWidl)O|S z_mi9mELAQ#S-D7+a2+=an87R;9t|U~1&sgF{`AZ#ZsOL+=sb67R?kPP;SQrDJP#F^ zsr<9}0#5FYl#3;3$mekh_XV=g`LVN$408Oz1ZU^F@kv7gMcyAWTE+yQfcY<&di4?0 z09J)>xHkZoQg!{E*RBSy?JCKOX7n%2$6 z-dzz8T10-8&ZG00yi<2%x`4@L8oj$ZXP|WgZ7E%-(h>@kqIJqt!{ou4J@Anf#HcEw zPSv)TmeUHAmeK2Am3|mkp+~W?)6eVg;c7e2H48x zBw;iPnvFX(a}Y+nn8^W#;6K4qA&N3hg$HYE=n|Dy)1^$6Gxud`0!yZ0d*p;(03ud^ zy^hvb&{_%?^-|c8>2fAn_!5YCX`?Ov6`*x_BAqZdP7`m!E4|c0ttvHBo2}NJT1HQs ze_rYk1e$5HO|)A}>0a7uufbmK{SDV?ndJ&?hXXVWWefy|nb5Neb%C#pK9tl%P-U{v z%DOV=mf@tF5qHo|q4_JBR-PLXOPn6TUrQ#9e83Sw*iIv zU^kn1C|EKWK_mS%Ah;Pks|+@@OxM8{T4o@Zf(mvI z55b=nM5d)6kW5m_Lx%`#@%0J~At8s1=`iJf)}P0CE6_pa-@`H5WIHbP7t4>QJLNX9vAkd8^)UWbAP6$@LZXWxAVbOYkgCYh!Pi4lzTy1%B>Pf9ZYnAH}3- z*{;*nGg_ZWZvV-oB*dF(WQ0^x71UW+hk8Cp_g2sc=tD&+CHpenk8FnaqFX;|TH%e* z9ifj@(1+=xs1s>xxwM`XyvIu)rw0VwCz$GAQ(yL@$J9)4{viA{r49G#c+Z$S3LaiI z8H1fq(Zeb|M4x7oLLr4te=>z$^SG9N2w2ERGL4D=I9HuNqS6>W3ax}f`>ts|P^Zvm z@RHI@6xXbm9v9ry(J7RMY_2a`aPR71XW4B1S$a}He-4?~NS8>v_Z&;WYl>KnqBJ7-hpw*<(4p-DB;Erm4B)LPDS{#kCnL(dCt zzl#E4aVwa$czprcYdPwIDCcme_C!|1U))PSuuI$zk*W(Ap#uWp$Ho58;-{sE*^$YJ zfcvRRKNF?1B4(sbe>9@m?fS5nel8lSJLrFy&YLbuYc7$Di~9RZ6dwe@uT*+bv?gxR zf2UDHLuJLEg$yM9E&WcA_+R7?)37(a^as(%yhwk9vCtzREf&@5r9ab0gl1l{v<@{6 zC3O?M!(VOl{tcWYFh zcWyW`&qG3pOe@HR0(&Pf@bG-DEH=)i05VspTrF}nH!FPJEICoc3S)q%V+;_aFop)l zP;Po#SxD2ff0q4{T+T}wqs1MJ(W0uHR%OPB;l?2?$s`KN)CwvpIWi|N=M^e1V@wxw zhcbE=o-@%8PA~qV;Cea8wH_!IqWp_Sb&NfdNz}9rhH)r2Br^t) zMeQA%TY4kA4{q7j(jMtJ*xS>w>)_TMT^(L-L2JjGxOJj&ZV-)ggVi{5yFFtT>@y74 zJf{=@f2D8cEh09yg6#A&72XCLgRGuD?B$3Jh}mU9;ruBh4ewxD7AzgZW*I&BN(>mh ziz!$}F_R7^NNhzIC6VZOw|xa*NB`8Izi`@_wbT62%UAIpm3#SWG=pW%ix>j~;()!P z=|~#* zs~lrgJ~te{KY{96l8>ex)n>uuGMb%`c#snwpktC*Tn4EfgILng;xZ@8J7YPjGNU7z ziy8fhkvX(Gk4lucz zopwj%<+s`80do~2D`Ae3vs%C2n@KP&f1Tw*W`gvc{0^aDj8k(=qot>B`xmPR?nWM%F_Tp@8f$^zMC-x zxq5eR4y{vI3_c*+I&2E>TUd_fzE&@Pkna^rKrwaahT_Qipb*^GDr(jJ{9!?Jf23IL z(A^If6~w*; z?}1Z(f$4(T18(_hnK5l-&KgXmo>nd-3e?K(mCc5>6~3tQ)BGjdE37LV)Q^&pwQ#S) z&+u1NlKHDJYC|%1Na3%+nyEu^jPYK6&d&RoKPnRF@-yfpj11b3Z`tb@e>%>eq_``W zHjyW%v=QIIjMQf2l5wjwh-GwmTwut$YYW7S)B^oRCLq)v5C#Y+jB#TgxNhmo8p)ig z+m?O7x>V%vtNgs^JCwARHbhpo8tiRe{t^FJ)aIYKNc@@Cy2(NO%_oXe2h_a_mDEVt zmb7j{8H0tCIim0{RsMyjf5xg%)u5J6>nIZ!1*crg#_ZLsWwQbZRQGHCjX?b^(~`4- z%8a=}HZ#K!NGa0IY^23L=>CEKsPgamPfQ#BAATw`rjrHMokCmE$m&;$>$>FdWOl&m z)`l3}takOU{5O^V!Y`N18@mT#Hk8i4BUNORx;`YLf13b*mCvaBe-8<>i!%lf^-2;U z9Xu^Lie6DxK3T%#A{V~ncqJJ#j^vgU*fE*tQzR9Izl^818it9apbd#{E7lZ_VRf}E zc~xnS$S$5Fa)vkpeqLJ|acM0jlw*p5vTxcoxin9j54VyQ6lcuBR|hLNBB)YOqvR9U z!GXe8h=^BOD85uIf0M*0GA*2n7=9$tiDqrej<}AS5rg&?cv&o6pi1XUOT5%!|GH4f zvaj?*$t>7b&`TGoQk8_MWDe?v2r}Dt(=V&+RUEinS|JRG@uWH{KKj7Hj+!Oxo*$h3 zJSiyE3UmxBOJT8wLQ9;~a_QJ0+H$+Y7xq%5dSM}87BbO_f7fWu3%N;ZkQ#*^Fy;8l z+=R>08U>@C^*y3XHwO(!x~UB1eKROeJu9R4i#yRqn*t8KOlnf8LRwpLV^InvOY4y& z6Y0aoAta#nWk$@|ua--OGHHW!xhjPv3`wq-h()h-g$Rf$X%kb&Wa>o&%jl;Juf;h@YL`0DJV={S3<~|Q zxVKlNt>PnLnaimuw=2>%bOF+Krp5q#4}8Z1N3?_qAS?S%)arm{Ww3y0Sj8X=>X^3N zqTq|)7_lk>iEJQee_T8ouuaPZ z`ZGo<5HsR>A7m?9YOlD%ISXt11#1V2EoPx>=owC%+R@3XD;+F;=(T8c8;0RJ zTsm&wf4E6n@v_B&nSvZcHW#06QG>Wc4M@NZjXq_R6tyGE%uPgmQ2BjdC;x_^K7e<&Sro+Qon7}Z6ij>=e%vr_NLQ=+o& zBpJok>#>>@t9yzoIjkHJE78hf09L;KB)w^jj*Zi;(XexzZjXje(A)F$&QZE+l#Y+n z`=Vi2$nPAb_di1SF@@cJ_apQ%rsI6t?-IX1$@BzBhvht-IL`O`<;uJelNOBA7;pvZ zfB49mXR!WQo}M^PexS)v&gcE|!8|>kr>}-xBWE7K{@1Mi2C+ZCIZxkg5`fhJ{k9ES z?Q&jg{rY^Kz9*250O|V{Qa~U%CqezPdlGEt!}O!OX%T>bVgb8HsA8Oc79FMkJ{1BQ zAj1lz_A7b%#c`?Pf$=T5(=0B&}8~QNxNwRw*HCGxKs7 zAbuqb0wZTm!A@E!voDKNVzcs90B98$d1mpu$?pVH>>OjYdz|h7=c8OvnalIse-rG> z^TJ7MQ)h{-eY_~oi=$1-J+wg3^YM~AU$kfB%yWKA6u<1KR)jRN^V))`t?f_yozaju za%E*q=!xg(Q{=;$gM(CgBtI%caf_(Rsq{@aD+#S}=pC z86ka~*GGN4VU#aFW&hkLem=}?e|vn~F~*%Z>oir1(1J)V;P~B;pF%#~KE~a%?9Q`R zT%aOCGZYoCbw1uX$~|Kog$!cB?q~!dDf0Qo*L&^G+IB- z%c7$kALW4)e5h-jQveUupWrMkF~&y@j`9uT{Dx>3B5#~;1W8xjD8D&0f6BK2KH7bP zZxi%s6BzdKTl4((Xp?-8aO}B$ceSl^VLKn+QQT7@lRQFm{BB3JY*{801(`8^XP)m0 zD?Wbj7{5On_W1Gh19`qL&mS4*kHL?eO-i0WS*?JlPt9MR=TBSiCFAu3oJ*WezdvZZ zSy&eKQ%>+G2tl=09#H+Rf3Rl+Zi1CZ#ESIpy09nYSNtA9DI^G;;Ll9Z5|JT@L8pS6 z=LDaMhSef9kKYv$QmRE_E9?E9x+#R7EG1O<>7Jl@f=`e0)6s|@lKP$XQ0bTR{H&FQ zqg^6St}cX+CEqrS#MdXVu^sKs^EdCN)gfU|nuEu;t&|cN=jWpWf4BaikH05EkAG0a z`{60><}kwSr&av3l#hRYOk3;XuMV}FV=&DU*-9CmLvT+ z+WizQMWlnqEBL#Bo<24v@d&Bg{c`sRFGPy!hJDXGw0(p%#G{63F=LblwcdY3eAs2Vm zpQhd8QdM++1Q6AEX;GK+F4-R9ZGBt;ETo9?DCrv0D+1IDFD2JwEAD ztgpk0jFnYAjJJ(@@>0vEgx;*>?T$KtwXGVHwg{EYV4k~Ae-(8Mq(-WYZ0p$a#PooH1&29;1t$_t9$S2(58GNS8RjOP4xdqRX7GP!mS( zwXWr~Th0}t^{$I4?CPWqt{rr_D@Dz&!?e*gOjo$xOPgE|Qj5EaTHR}@&3zZOyYHqB z_w%$_-a=dCx6@YnYt$*fK-=U$L01^rp)ZLX{|8V@2MEVi07E4e007D}b)$q0%WLwQzAecs$;-Nd zASxmv2qLK4kS~#nq5^hlp^Wh%1BQZAKtXf}4pBfw6cmwp&P}qWT{hR>FFo(vkMniU z{hxF9eEi_U02Ygt0^2UTZ1s{$s=JNge?~JFs`gh0d#dZJgLbsfiWrV%$9z#cWYT!t zjF?8kq{&_*;S2Vf!HtPzG*RvEF(L`GzPc~$iyD1Ci)C~-H!lhd7@Lg7h!G1np548{3_1!t0yE`k(y=0q zK|2;q#^YwpX>6fwMt8(ipwh-oMr2;Z4jPg3t-iFjiEVP5Wj8W^l0Y%930Vneg%uYl z%W`q6JIRq+8;=~^6f>R1wX0ice^UuBBdtAFI2o4_6~UJ^kg?F#!|# zYr2j}n9N@@1>7~fuMD#_D5w%BpwLtNrqnEG8-Ir6ou2E2f_VZH!ltvzf8c{mpVs8; z#;m70j=`}S=A%Yn>Zr&LhjZ?R7!(;@XXOpGy-LRkte_4{1m@;F!7*B7==^LD=cSdP zjHE!>@hvj2=j%8b%Xsz_e=^rfuoNB3(?h2TOd@BOcPH#f(lJ*VPOpv?Y41)Ks62d1 zDEI_jNFx|D6O@q)DJR1``t~a28pcUU-Hb zr2w4G3E7TSV_>3VOTsau3RY9(%sAca@`GltA}bxT)ik1H!5XYBe?kY&r90kZSdnDh zJd5IBgehf8^CirA2(Y&E2`TajRIr|su8#*Igb3yNQi%@vQ|Qug0WPFt3=sf32k5POw*CcHVT&e?km<5rfT#*GFEMn@M&;M?CEXnO;5$&MkH%LTOA|6AF?7MP{_m z+0sTkD8^Y27Oe4f``K{+ti76n(*d037~VYDfUe=5dU+nO0CJFdc)it$BU zO%5G8uizR=3aYQ|=4MC7SFo%Y*Wx+?$Cw=WD(3RQ4HU_UDH>}?$Qz?#n3%XpD7%RuqWbW)B70MGJctpNfASD{o7H++vZu$4o1xXFA?ww{ zbWYj1)>vOM11H((N3yjpV{pzA1&`%9C|O8;qTz8oAyBw>%}U=A6;BG(jxNlRaoAGy zw1!8qhjHlOwzNr^`JZaog`d$CAt|9Y>il#($06H=pOe~P#7@x2FSr@lgz zs*2f8e^n2IOcmXU-YNne%Gnnv>GNc2HZc_ZisGIydd#(P!m?R4 zivLigs3CR?D@I^FJ=eFEUL)RNUX(Or!8C~c7a#Nf0~EDxE0#HPRnWs=+UPC{6t^VV zf1XabIi-5(-Jyy?!mSgUnpB~XV_Ytcm>sjoUU_Xrk!*W}#(=%bsJCjxKxz05sY_ z@G}Yk3Dc=EH=Dtv!#Ajku0+&I@M|%_fIyc`EM&DL*fHD9e%b4a#j?E+)M{6be`;Ty zj5$`+JbiP}?32xoXwpP8m%f=<^e{tJxy7oghoq4Pa<`(&N{~HO^qjLoRa7tJT!Sk7 zSsgN9G|@;e$Q&I@$3Q{O#Il^uu=VVmiBk!-Mt8Jk<70+$)=(E;&_XY3YUUYE+mq35 zGroo+M7UH)O&>)Tg_BG8Jq8ffe>0TcVv^EJOj3He0dUd!GEAWt_X^@_X}^c)tlGf( z_1=OVsHoe4Y4tl$>Dz%B-ohQ2HH10$f&WTSjk)Q4h1*FdNq1jYJA(Ovw%S2VOJTtX z>H@W0L#UVR!W51#ZKi)IoH&G~gQ!g5)U9Z$OQB^e8fZ@i{VD?~tQIWX*I2w);@?C{sP+OFC4_IfZtP}LT~3FqJG8Qta_S@ zd{Vkvu5N`^@ADRYnG%9GerFINTpiWH}CfKwRa=su8@xYMtWNUdJgtNAiV;Y+Vvf0(n9&Vd3lf?a|2 zyyMZp2p%U3hp@Z!sUbWwglALO>sM2F-mChR0km_#io86qt3HtRNa-qlkvtm4D=F+N z{ry3=vh!+J>Fd(tHxEt;zf#bwmKV7$3^W(rBK+m*wvRirDL}s&QrJB?i6Atd4)_cB zfJ^^8jKAEEf28nXf9Xdl4z_0iFG!aQePzN$eu?%GQ4sL##QTAOx3DYVE)$-Pf-<3Y z6gGQOqPX1C)iER{rbH=aO-fALiUh}@oulAayfieU^rNVS(J z)mTl^2~@tAe^!b)l2(foB|TZJmNY8*#H->Iagn%6(yPU_l3p*iOM0^ymh>U9SJJ)W zd9fc5FN&8WzhAt?)OC&PM)w4HMnSamqf#jJo|Dn53@=S?$ zm$)mKmy~z{%+m=xH=vS$SKv$n;7+))4h8h&FQj*-2UijZ-vAYN5vYCyO)N(-fvhgV zm>{B<=vszJt~HqKx&S4vAWB_fl({a&6!&VByDvb6JBX?7UQBaugx76LJ#Go~?*9Q$ zO9u!}1dt)a<&)icU4Pq312GVW|5&xPuGV_G@op77bzQ0`Ma3II6cj;0@G{*_x6$l@ zWLq!9K8SDOg$Q2w06vsBTNM!*$jtot=1)l8KVIJeY+_#EvERRF+`CN~+)~_fcio`v z*4!Y8Ql(|4lGuxq7O`$fleEN}9cjIwL&2@>M%LYJOKqvn8>I&WVJ`e@>#4mHnuhzUW>Zd%6?zt$4SI~lcxhl zC4TO|$3j~w-G4Q7M%K!ZiRsf{m&+`_EmNcWDpuKnz~ahZga7dAl|W%-^~!;R$uf$l zI4EIk3?ryIC}TXYW(0;0`IS)TrpP}tglbN4Rm~aBg2TZCuXEfjpuhoC)~>H#Ftz@S z>Dn`9pMU{c7+4fO0Z>Z^2t=Mc0&4*P0OtV!08mQ<1d~V*7L&|-M}HA1L$(|qvP}`9 z6jDcE$(EPEf?NsMWp)>mXxB>G$Z3wYX%eT2l*V%1)^uAZjamt$qeSWzyLHo~Y15=< z+Qx3$rdOKYhok&&0FWRF%4wrdA7*Ff&CHwk{`bE(eC0czzD`8jMNZJgbLWP4J>EL1 zrBCT*rZv%;&bG!{(|=Ze!pLc^VVUu~mC-S7>p5L>bWDzGPCPxXr%ySBywjS7eiGK;*?i?^3SIg!6H8!T(g4QQ%tWV0x-GTxc>x`MRw2YvQwFLXi(-2*! zpH1fqj&WM*)ss%^jQh*xx>$V^%w2Z&j!JV31wR!8-t%AmCUa;)Y-AU<8!|LS2%021Y5tmW3yZsi6 zH<#N!hAI1YOn3Won&Sv+4!2kBB?os0>2|tcxyat=z9bOEGV>NELSSm<+>3@EO`so2dTfRpG`DsAVrtljgQiju@ zLi;Ew$mLtxrwweRuSZebVg~sWWptaT7 z4VV)J7hC9B-cNaEhxy8v@MbAw(nN(FFn>3184{8gUtj=V_*gGP(WQby4xL6c6(%y8 z3!VL#8W`a1&e9}n@)*R^Im^+5^aGq99C`xc8L2Ne1WWY>>Fx9mmi@ts)>Sv|Ef~2B zXN7kvbe@6II43cH)FLy+yI?xkdQd-GTC)hTvjO{VdXGXsOz-7Xj=I4e57Lj&0e_C+ zAH@(u#l-zKg!>k+E-Qjf-cLWyx_m%Td}$9YvGPN_@+qVd*Q)5cI$TrLpP-Mh>_<6k zysd!BC`cEXVf*Q0Y(UgdE^PYo5;;FDXeF@IGwN8mf~#|e4$?Ec!zTJEQCEM2VQr*k z8Kzplz+)oH5+-jyAK;GP8!A zSKV>V#gDFTsa`xXt|1Uc3i&PSgl%D=JEwjW^F5vD0l6G!z|~>y03#T)?a;@!*(vAwmBFr?|-8vt&)jK z!?QG5DNz%WTH4H>vbUDpIEl_O19mVOmP_8bVz-kCsYEtX_1Ovb zj+KS444hDHKJfNHwq&hQ29#QGU>;3P1P+D_kVfmXiA~y=y{YGCGep{s6iwTA*ge*SZSH9K;{Gc1^NWT z@{>XOdHMwf#oVVr5e4%x1I%+r&CEE*Qu8V$tmu5mm?%|OR}{L++~wCzm$RIp(7a-4 zuUW|Jw)8G^n5G$)e{tS^RU&@6hKR!RWWQzWdvkgoyCMKT%caX_=zlus#?;Tc<%xwM zJewbXg?^RAe+_wMk=A>m=A@r~0~#Z6hmh`q^b!Z`=jde+%aR2&hxQ>`<7bXmDk+!% ze+$*7qh)2_^In4P`ktr>O8z!|UZGd$clcz~c=h>Hr~z=--z_oAmq3RVC-fGwS&sJu z1-B|M{Jx;us@*hy_J0o)`U?9cH0RlBfikrIP@yl=AE9!T32=5+P-i$<+jN!7%+FG| z&!5nrvTOegUa57UpZ*+hJA>p2ga0MxsK21E^Uo8!3b{#gdjViLw zDj?{%qL2b=fc}>G8S&udSPszN3la#if5csvd~EsYTU;zzV}C*VHpkOH)4w1W41*h( zbOQ8mmEBsPEo@ObLg z93$OR0O5mpOQ~kA@~zx=sm%~6;&yQdTLO>ECg3w&$V;K3Rxm$Mx#E3$#)AP`Y5ET>GF+K7Ons=3AJy$clM99)e@XPVK;DaXeI#{!nwqZB>eS#gwM4Gc z+UQjZ#jeu&%Mv~fw1GC37KsP2q#o_EXrxGY9xc+Ai=@m@d~k~Hixz2HYVc*MpSt<2 z$TixLN>0<8uJ7@5d0V_2pQVkF7Vq{{!dIm33#3Ft_}G2)yjM)!d^I{4d6C{M=mM$U zf6tOXHRy?rH1$Si=)u8jv@ewuk!jjLMIV6_5a7L3EjF@9Y$D=$k&f1(*4c#dO{r8e z(v+H}hoI~Q3P)vOmA?n#aMPBi8^%0|sj#w@`5rIzh zQ!tSbr|=trz3XA)gH(s7qlZqzSnr3Gf1k$a6s-R${PJy>^CsjPC{3BNQR^|!p8G=V zW%6Eb%Fa-3=o*=+gf}`(Z);pdp9v&gz7C z*}oPKd5d(eNI!)2=dpg8p7eD2T72>A&r(Oc#kZr8Zl0T=_oWh8{A0N9vXFPxf7T*> z@F=#&(1(wn_rW1wit#=dQbR@h$qP^^nkv#IIQ!Y8pN*0_p744iBi`tUFE&yiA8GoT zkhf%^=TflG&)tw(+<*mIXdUgu%{CxCbK8#JowN2@0SO=M^#R!H6?`{v`CUe5FJ?Sw zyCTwGaWuckZrbd*cS97n*}$HSe?&KIhht~x@pz>vsk20GwyCM?#|=m*99Q+xzrHv4AaMp^qVvE1qqxlUZ9nHsoy&~b@Pi; zbSxIXMqg&hucX*B)AZGlZ<_wNNMB2M8@&ts^)Xsm@z<+UH@_KAm7Vk&fBsM1e8*q} zC%twfR;0hW%s)2}p$g))S6XPbY}b-1+g56mZJ4@bdpGTo?Oxg^+aw*3?Jyme?QuE* z>k?^{mF+lLvMtd2WXr!S_d)uoY)gJo;16IEvvuH(Z&YlEF~4MtgVERw{mtdnP$YGQ zLX5QNiKcH()87Fhz);gaf8Zxp{{AQY07^yr*Rp8*MAN@Z(f^s9xq-6?{;3ChGh2NJ z5h72l13;O%#FbbiB|~{IS`?nriNJPIz>*(s7WJjAq^m9+Eguv+(JTTuX-2FlipGi# z>xbCfU@qZdcZ!5pBz#h2ErNo*n((t*0g$h4ur7sb6@-iGc#L$?z0#Uu)Xh){P%^cBVZ7wOS8%9=n+@X6!d z0j(RK8a`Hw2l5S1eVl@8los!kPhF(7@ijcCcL%PBB!<=~MKK)m$2=`T0Eu_#R=NXI zH=h{{`4iqLa>{Mue;U1>Y8Hp4#o-&#kU!*$UlB)|#anUx3hcmxfhe0Q0&^ZadKv7! zbC8#@-C);d@h~h3LJ*D3;sie9@`|I)B2%(-WLk{fsNVS{3NYNyg}nR)ue=tyK_MEW zlVVgDvV8=;&C^-g=a&0t>2a|ceQr0P|8{y#_POQ$^YjVXUgwtkpQOvO&n@>kdb!Un z_g|vV%RaZ<|2lm`_POQ$>nH%Z&n^1GBO19cTkgk1x9oGv{j_*W>RF15CZPW_^!Tj4^T{T!k9N#2;RO7iBy{i;&QUo$Tz+ znfE#GOwP=ozrTJ1Sc55We021t`blp}YoGj;%5y1uf!uNG{2U zc(N@c!)lX%wI3y3q;Kp>H=-52V;i3A7>>%(TwkwPYfo4kR?qm|#C16kwWU$vA^EoB z6NQd%bM%nHh`l&oU46V-HClA2e;$PpNH>BcwCIK7lE8cr+NK@KmP_V`PLn)Sf8 zDbz3|Fu5lWrRhrFHeWUO$ci zK|;QNMYU4B-{xxq=2gh0MJ_>CzIO%I2C`dQ0}U%zLwzhCD9eXj_~Pck%ya+e`Xnf; z1j}62O+JMJ**YJ(mx~=JE+{p9z;saHl6M^@O>uaJ(zL_pbbfg95AEkMI{P zQrP_-wu~WeK)#DjC~RTz1jWl>>J%&u_A8uVH0UJwtHj+O|MgSsVS$&sSO#aG3~yMr6^X${<>0 zQle|Lj@}|34Nrzqkl>m>`@k4<9*UKfc&#)tI4W!!rdA{x!$&L15^Z=Vs_fD^%wvtV z4GjkS3$YfV7A6gE;|0p94J`((b7fR@!QilW^Ak`-SZ_W1@A@+aUavpvf)AYzv|)!q z4VaP^lJwjZ|A#8&wqkPDwLy5?V^3lqxn2iXkLKsKp3v z)lw?h02Q#9dcl*)Nir~*8P80hEVZkB@JF-{`qDZ}%ic=6I zm%FuV~79YG9K?LnO!Z^jy-SC}sEQ=yjZJve> zhLEVZ{w5(ZoQbyviJ%i_b(}#LLsvu9$Wy~P3VYSGP5*j5?A-{?qgO|N4=ynDG-o(t zyH$VDmx5O`yrrVG6j*nCTSp%*G6XD#7Z}brjGFxGwwDl7VfqSEf=l#B~g+q=IW=b5Z!M<&ucX9YRuprWo1}sWhaiRi-Z__Z`V_?vU@yo}2(i zFdD}DxXjRbRIlL*gGOwBofG%{2tGu67-Ps#wKfT;#rvpD6d}xUOenjnl!5P12Z*7q zw!2cYy^fD{X!wL7>>Y4wID{LA*tcu0;U>}9^SSiBWz#PcPvS>06_ak^GaXZyW_ZJ^ z=DocXy5lp)=I}XgE9)%v+M=maz{HH12<9-a6nE%cQa3OVKU(g8u^m{zqPmtPawHNk zWR7wCpHO$PtcdUx!|AF`o4_oZJa38m07T<0{69Jm_wcovhi@1zG{6_Cwr^I%)O|y^ zYO*wZw@?12&fKV)RzYoo?-}~1q;zC-qb%&GVmhg#?!i<=i!>0|LdgHijnpTlpo4>E zJ*c*hO|z2vk8U1+%7RKMp{yWG^+$Y3922QYvQ(DNhU(N_cuU6$Dzv>0=5xNOeup?c zNo$t6oTaTgSFPlQTvG0VOE^gcRX<`ALi8~FK&RITk_PxKQN!sc(4M3F**1D|x$G9+ z+(ut+b|{%kY$001J2kwwjltaQEs*i>3w*#Zn|y(f7#?GPoIb8Gtu3 z6l++mVQpv&_A5%Vi@5j`T=XJZe@D@ehm?9h2I}XB_@(}4kR&~YHrm3(cAUT?`X&;S z^aR@e0Z>Z|2MApz`fv6F008!r5R-0yTcB1zlqZ!0#k7KfkdSS=y&hcen!76`8u=i8 z2484mW8w=xfFH^@+q=`!9=6HN?9Tr;yF0V{>-UeJ0FZ%A0-r7~^SKXVk(SPwS{9eZ zQbn8-OIociE7X)VHCfZj4Ci&GFlsOiR;iIJRaxoGXw(dGxk43#&53m>S)=uTq|9>^ zv)ObhvxHhb=kS$=qTqy4rO7l7nJURDW4f$LID5`?1J}a&-2B3PE?H*h;zu740{(*5 z&`a#OtS|ymO_x%VPRj~QUFfu4XL{-O9v0OB=uyFEst^tz2VT!z4g<2#lRmMJ`j5ZM7xZ*AM>%2rvSpe(=Ig+{%mm`qu9D$$nuwfAVtg)wU1D1@Oa-0qBDX0)tL}srdd3AKVr| zu!4652w2`d0fsD36d(v8?%fw448z=eKw!vV=GK+cg<@B0$2aAJ0j^IF7?!T;tpbe1 z;%>zpHr&Lcv2JbrpgXly(as#!?0ARvZ(9Tyw9dPLBI6nnUO(iIoc8&R_JI|#ma!w& zAcT?E9qq-QVS__Pcf=Ea+u?_rKX*`?w+8~YR^5P4}7sOkF z9^v<)Wd+*~+BRU@A=_f}TNYc7Hi#bHH2iMhXaTblw9&-j;qmcz7z^KOLL_{r36tEL z;@)&98f?OhrwP%oz<(i#LEKIdh93L_^e1MUFzdwUAZf=#X!!zWeTi=n`C^CXA?1cg z9Q>gxKI!0TcYM;pGp_iegD<(`iw>T3#itznkvl%+;5k=(+QA>Y9v3?#|5p?&G^NcjljeZ~g^f18y^%J9)Cd^>|=NijQzL5oim< zlYvkmuB9`wBAK$LhSPsqg44Xt6)qW^7KbGx93STK5hI&60&Pi2F?cADNrlr=CM*jZ zLoF@q;~O@SuHKr*C$ow|6UMLxJIZx~e9?Ss^Ty`ZaDtBpPPoAs zJW(yH$N4T<;S2#yPeoF?lu&qNOqVhlu1EGea_2aYXH89ap^|@L(Gh7>iYStriu4X0 z;c?T2YBH74HPSR?ZZItAvUReitVH^z=C?2`C}=rO7dV=-77=68sE%uDQcf{6cFi77 zhpm&o07Yne+0~cxtd5_*)sP&)@HC}ize=e%9 z#0xj(imzo}crbrYe63*c7RTYjDhiU1%Z6##t_Qui5BGbp8h+wH(WFEnJTC%R=pic) zGR)Vxl-NNqUE8ZG40R2ST?P81rl{~1FV5^e_8Pg(x$FW_6(mpMLKFJ(*W5>({#DW*Q zoCKbj>CJyx?{us_MShE|Mu(*hn_8mTv>ROv%chy0TJ@sGvER$E`JN~loQ0D;f|Gu7 zWz6bozzKCPos?s8CQ8kPJJs7yy@Vnhlrv7zVopqhG;I`3KjYvJ7U3Q84o~47P9z6E zG=+Dj6AqqAR72W5+#J*NkpVf)wXA6$(M~T?7#4pzGDBrUrkr3p#=R| z)ud>4j>mb%X;#lOggUgWlJKjV=@*U0pX+Y^LM!$sbuI0$Ut`oayK%Cl!#hQF;YI3S zNlkxGOJ@1oTeu+m*V=%8d-n8%+f;C_H)8o;-_FbP`qm5+m$!#sUS3~az?6UCnEncp zrIoW1GYikZ3^9(J+*73a_E2=I+@yTZzO&nHEt<<$te&=8HKwBfgjml-JG}$lI=92@ z4z$bd>F@tEaq6laA2^*uV=f+<_SYxIZ2lu1)15Avq4jrv%t_4M85a1jrdBbg?&OBO z?w|X;yr%s=o>F|n{!ss|&@a-Ga?>Xp`Tt1WnzOgFxn}QvF`pdqH+A0O6M<{R?*8aI zm|Fe9w=3;hq}hV*9V%VFm_Nouyj`+eMRi@5yyP88PxBQT&vbZ!!)Ky@-W>G*(aL2R zRrh*#Vd#O=-{*82{_t)2Q0>X_c9z?Dty^;DE4*(gK1oaCZ038&qGr3{1N+o{&GW)S zR_RrFeoeXT93w9WTJ=k2WmwRsyZJjz~raN31L?*7OZAKosxIC_$obw$Vto-F(G};KG84}n`sf{TwU%2wY3la+hh1Mo zOk8XAThu>BWiTy&7qj>ZQ^xVsJ)L}CZf)Xc&#mN8-WF1DX4>(>Q`45ejQ0=-ZM4zk z5L6XanSS@s%!u+}4U5KdXED2N1@ELz7MFYE%Vl0?GTZp&z)8j5fxVV0(M{Jk-YLI# zD7^e3@2_*4y-s~w)iFmb?A6PWbS|JU~kQ>A{z z<#_KpR{ZVn&J%Zz?8+_T3iQ3CX&uXK`8Ms6*u@`B+O_xJ&pYz;K_cUp%GV7lwA_XQ7h?=EiYO%jA1g4LkyE%H;C7 zPBKh~SnewUyI}=DY{&pStppCf@lAGIC^PvppTgt~O9f-}d3G+pn zHcEm8XU#X20bkb$bjx(06{tEH6~T)57MRE&F1=%5uthQcpfXUA=H!#g@?du$?pR}B zus~7Bs}5H9dx4fr4CvY|pq0)*@1y!kP7|oePX>Iq6EG0Z0Tmgcm@-Wp?51-IwPcVl z;ju?iv_==K$b6Bx4B|cu^pKur092#|ys(EK0ARQEYY^^{l%|QCuAjeEkp14?q>9h4@!6nkbbJ&fg5yu+?X8=+3#!VJj5-STn zB^PM!VxULuP~>AB87AvHdVm8Jad0aGgFcF?DbAA>SBOrobXEl`gda@_j7wDOI$XgD zA?Lm7ffXYk=VyXqs+K2Iu@*=nEBNf4$p*_rnW}xj5^+A_U=u*+w%i1|eiP93x+o@C zhJh7Ihbe;@`y&KjUXYgX_u)8xbzqD+z9U^n!xP?doXqyT+|nlWGZ zf)zbpp(6wDM6oe2=%E;$(+^UFIrO3?4Q`17gDC*02i4ujCr@1I$qFe_?ym&yj++j) RhRK)Bhkwq`;Yh)md4RrtR%sNbw?F7+wVN@9oT5^KvyxHCChVwDz29-_(~6`YI}kOI zb^sOR2x~T#ZdIJ>Rf@`fWMMck8Z~Fk7!ymA-q=^Hp5eZ$X)}%69EWv#a)HMQBo+#f z36F86&q=PH!h1hfL>Ol{cXt`zy7GFq%Eq79O{IA-u!cH*(wj1wN}D2M4WT6o(qxrW zEB}r}@-+r4&wIr;xO0(AI@=cYWb?m21~K;0A^-T{gEQnxfCN&@N(#Zq#RXZY87O0m z;t0Wp7M~;I&<5qU1T+?pjfUye_TixR_f>$?rT1}+*6u;9Gn0cXM{`4grB6(W zyBDpHwv$&%UIzt(jZMh^e3jZ{I@kE301olpI{yj0+;ZWogmFjno1+v zMW;sMFf7sR(_fhVjl~QhEC!kN?S1GnQ8&fuPw9z{5eDbyAAsT&CyjpUf=RK)X*YhW zwf>HLeXJxlm0mFjo>lB@ni;CUkg)*JRligsG*5>@wN*UJvbS&X^}x zn@^UJmJ90QY)d4OLkji-vg;l*>VWz+eRS?0G0Bg!HhZc?2Wz}S3kMg^_@+65nA?uo zkBwh=aDQVGH8XVK>zh0u{gJbev&iTnS1h3p(pF$?`aC^rhJj2lK`5&HHV#_?kJb zGMSi_SJ(*5xg|k>>Dvgt0#5hN#b8)>x5&pj4Wy_c7=p-XQ=>p*vRykohWoq+vj1uk znu?X~2=n2?uaB_*+Lr;+&434q#3lhbD9@_k1Te#nwy}MM^TTHt=B7p23Hvw*C##@< z$6AnfJ+Ri~X^`J(;3$v;d?J5C5U~zQwBA9#k|t1Y#>7ZrY#I@2J`|kfQ=Sxhc*rH| z{varkusu6HJ$Ca6x^v$ZA6sX;#AVi73(ebp61*3)LCF6yToc0LMMm{D%k+S_eJ<3CTZgjVEpgE=i5mX z0o|kFlPT7$0gM?NfN_Wk=T=zCXFhtz_fJrXuKFQ#uaUzUCWj%}$pz$g05t#ar{-1o z#ZYh6o&A&s>>NA5>#m&gf?X>M)bj>Q7YY}AR8nPC<0CJ`QolY!M*@PhNF4%4$5nFf z4{VxA-;8{~$A&>%Yo@~y4|O}IqYemSgP7Sy?d}}+e`ng%{?_hDUhCm`I`hP=rda|n zVWx~(i&}Q|fj^k+l$Y30zv6ME&AX7HTjy~frLaX)QgCMmQq3_qKEcRyY7nk_fa}Z$ ztrwMjNeJ|A@3=y7o^6LMBj@LkTyHm7pK(Vxq%M=uXr;M7{wWsrG~I1ki5OQ6#92Ih%Quj|8Z|qUzyy6 zUf%s*-I*73e%AX}cTI5r+ZsgVR1jr6I*hnu%*rSWqzs(T0KD7A4U}76 z)lH{eBF=pRy0q*o<*iM4@ojv65`y{#TKm=!5+7PwC>z)to^he4BI9`z60IYcFC8XC zZ<65C;OV<=0*{u4*i@nn?J4m6_p_jauY-;RSof^%yxer|uPQvyzOCP1x_-}6H;)~6 zkQH$^6A(lu&B^q)5vwSypjGu5P`Y#UdzM%Uhuh>vlisoS7c?a}|1hah-vo_i`e5;! z93hb``au;ow+t;(wB3-=ww(pgb`ZrEODvFvfEiQvXaSX6+A0ooWdEx3u-oBf9V((3iwRO z7r|AqsNjl$(oTUVvOf^E%G%WX=xJnm>@^c!%RBGy7j<>%w26$G5`?s89=$6leu-z; zm&YocPl2@2EDw6AVuSU&r>cR{&34@7`cLYzqnX)TU_5wibwZ+NC5dMyxz3f!>0(Y zJDdZUg*VS5udu>$bd~P>Zq^r)bO{ndzlaMiO5{7vEWb3Jf#FOpb7ZDmmnP?5x?`TX z@_zlHn)+{T;BtNeJ1Kdp2+u!?dDx4`{9omcB_-%HYs2n5W-t74WV76()dbBN+P)HN zEpCJy82#5rQM+vTjIbX*7<~F)AB_%L*_LL*fW-7b@ATWT1AoUpajnr9aJ19 zmY}jSdf+bZ;V~9%$rJ-wJ3!DTQ3``rU@M~E-kH$kdWfBiS8QL&(56OM&g*O73qNi( zRjq8{%`~n?-iv!fKL>JDO7S4!aujA}t+u6;A0sxCv_hy~Y2Pbe53I*A1qHMYgSCj0z6O zJ!z}o>nI#-@4ZvRP|M!GqkTNYb7Y)$DPWBF3NCjNU-395FoDOuM6T+OSEwNQn3C`D z-I}Tw$^1)2!XX+o@sZp^B4*!UJ=|lZi63u~M4Q%rQE`2}*SW$b)?||O1ay`#&Xjc! z0RB3AaS%X&szV$SLIsGT@24^$5Z8p%ECKsnE92`h{xp^i(i3o%;W{mjAQmWf(6O8A zf7uXY$J^4o{w}0hV)1am8s1awoz0g%hOx4-7 zx8o@8k%dNJ(lA#*fC+}@0ENA#RLfdZB|fY9dXBb;(hk%{m~8J)QQ7CO5zQ4|)Jo4g z67cMld~VvYe6F!2OjfYz?+gy}S~<7gU@;?FfiET@6~z&q*ec+5vd;KI!tU4``&reW zL3}KkDT;2%n{ph5*uxMj0bNmy2YRohzP+3!P=Z6JA*Crjvb+#p4RTQ=sJAbk@>dP^ zV+h!#Ct4IB`es)P;U!P5lzZCHBH#Q(kD*pgWrlx&qj1p`4KY(+c*Kf7$j5nW^lOB#@PafVap`&1;j9^+4;EDO%G9G4gK zBzrL7D#M1;*$YefD2I-+LH{qgzvY8#|K=-X`LN578mTYqDhU}$>9W&VOs z*wW$@o?Vfqr4R0v4Yo_zlb?HKOFS zU@WY7^A8Y{P)qU9gAz52zB8JHL`Ef!)aK7P)8dct2GxC*y2eQV4gSRoLzW*ovb>hR zb0w+7w?v6Q5x1@S@t%$TP0Wiu2czDS*s8^HFl3HOkm{zwCL7#4wWP6AyUGp_WB8t8 zon>`pPm(j}2I7<SUzI=fltEbSR`iSoE1*F3pH4`ax^yEo<-pi;Os;iXcNrWfCGP^Jmp935cN;!T8bve@Qljm z>3ySDAULgN1!F~X7`sAjokd_;kBL99gBC2yjO+ zEqO##8mjsq`|9xpkae&q&F=J#A}#1%b%i3jK-lptc_O$uVki1KJ?Y=ulf*D$sa)HC z=vNki?1aP~%#31<#s+6US0>wX5}nI zhec(KhqxFhhq%8hS?5p|OZ02EJsNPTf!r5KKQB>C#3||j4cr3JZ%iiKUXDCHr!!{g z=xPxc@U28V8&DpX-UCYz*k~2e)q?lRg<{o%1r;+U)q^{v&abJ9&nc6a32ft(Yk}`j ztiQP@yEKf@Nu3F;yo9O})Roh9P08j7@%ftn7U1y;`mard4+5 zB62wpg$Py_YvQ!PE2HpuC}3el-F3g{*&a z3q{eLy6Xz|F+aMrn8R8IW2NZu{tgsyc(>*TdV79@?V$jG(O+Iz2rnDBc|1cK8gR$Y zthvVTI;(eYhOdjapHe=9KI`|2i;{VIfvnR6`qof=4a=(BTZkev78+6GJW**Z!|yvS zes)T%U573C~Hm`&XJzE=2t7tFIZM`!^r^&z;W?dOj-N+a10^>wV(l~2naa?s; zTxU{z;Go|Ve!vUjUrZ$B#mWH)NSdxi;dWa-@w)-$wBOpo`DEG<;C#W||W}&@z>C`*j9V|`ai)z*2PG`TZt6T{a zj!#m3`Vz5R9wJkNMsJ1`fSCS2mHnizWDT!G0Ukp$%*_^X1=k=%mmO$^_0_d|kc8ek4_DZwomL(>GGtfEB)Wy&cfZ@9-T|hAq&fx;XR$$_yl6iogcR{u zm9g)axS6=_IL4=wQXf|EkzO68$Ms4*JXAt8gFxLCibt^C#C|I|v|U{%A;+NaBX-Yn z`HAmP*x5Ux@@Wkpxest$F~K8v0wlb9$3gHoPU(RMt+!BfjH?`8>KMK|!{28+fAk%6 zWdfyaD;Dr~`aJHn0}HIf^Y9*keGvm6!t?o%;je)wm`Dm$fN?YtdPI7S=Y23+15L{J zr;n3MYg`<50nW^`BM$&M(+PQ7@p7Lvn(kE`cmoNS7UkQmfvXQBs_unhdfM){k`Ho! zHL0#a6}Uzs=(bu;jnBAu>}%LzU3+{sDa6~)q_|pW1~*Is5J(~!lWvX(NpK_$=3Rbn zej|)%uR0imC;D5qF7p}kdg(-e{8#o!D_}?Fa<&{!5#8^b(dQl40ES%O_S(k8Z$?Hs z;~ee=^2*5S#A*gzEJgBkXyn*|;BBH97OOmvaZ>&U&RfU0P(?jgLPyFzybR2)7wG`d zkkwi) zJ^sn7D-;I;%VS+>JLjS6a2bmmL^z^IZTokqBEWpG=9{ zZ@<^lIYqt3hPZgAFLVv6uGt}XhW&^JN!ZUQ|IO5fq;G|b|H@nr{(q!`hDI8ss7%C$ zL2}q02v(8fb2+LAD>BvnEL8L(UXN0um^QCuG@s}4!hCn@Pqn>MNXS;$oza~}dDz>J zx3WkVLJ22a;m4TGOz)iZO;Era%n#Tl)2s7~3%B<{6mR!X`g^oa>z#8i)szD%MBe?uxDud2It3SKV>?7XSimsnk#5p|TaeZ7of*wH>E{djABdP7#qXq- z7iLK+F>>2{EYrg>)K^JAP;>L@gIShuGpaElqp)%cGY2UGfX1E;7jaP6|2dI@cYG%4 zr`K1dRDGg3CuY~h+s&b2*C>xNR_n>ftWSwQDO(V&fXn=Iz`58^tosmz)h73w%~rVOFitWa9sSsrnbp|iY8z20EdnnHIxEX6||k-KWaxqmyo?2Yd?Cu$q4)Qn8~hf0=Lw#TAuOs(*CwL085Qn9qZxg=)ntN*hVHrYCF3cuI2CJk7zS2a%yTNifAL{2M>vhQxo?2 zfu8%hd1$q{Sf0+SPq8pOTIzC&9%Ju9Rc1U9&yjGazlHEDaxY|nnS7rATYCW_NA&U? zN!7-zF#DXu0}k4pjN05yu#>x8o#Jx7|Fk=%OR((ti%UVKWQNH>+JhH#ziW1hD=rk* zD#1j?WuGxd-8VqG@n_Lqj^i=VBOg@GLePo0oHX9P*e7qBzIs1lzyp;}L3tP1 zl5;OiHG&-flQ;rYznH%~hz>fuJ!n*H#O)3NM3`3Z9H|VFfS-_xHRCuLjoIS9wT!F0 zJ-kV3w>7EguDzoBPxW>Rra0#+Y?;Woi7qJ1kpxTad?O?^=1cG@GeNtRZRi8_l-1CS z`(#oF<;VYR(l(gHIYH$y2=rj5m3QL{HQgbW9O!TU*jGj!bFazIL?MYnJEvELf}=I5 zTA6EhkHVTa0U#laMQ6!wT;4Tm4_gN$lp?l~w37UJeMInp}P>2%3b^Pv_E1wcwh zI$`G-I~h!*k^k!)POFjjRQMq+MiE@Woq$h3Dt8A%*8xj1q#x?x%D+o3`s*)JOj2oD7-R4Z*QKknE3S9x z8yA8NsVl&>T`a;qPP9b7l{gF&2x9t5iVUdV-yOC12zJnqe5#5wx0so2I)@8xb$uPG zNmv=X)TjpHG(H!$6Xp>)*S}r538R99Y{Pofv}pAFlUK;xi{E43^->z1srWR=J$8N! z4jRu;EAiLG9R$5#{gR){5?o^W^!t140^f=vCVSs@vK7#`-fv`P*WV|>nX610pK08< z>r#{r)fR?2pNG}8o)?uvX#UJI)YM5CG@0E8s1lEV`rom|kBmf={%h!o|26a=lNJbX z6gkBS7e{-p$-Vubn$(l_IbwS02j;+6h2Q5F7P?Du2N!r;Ql$M>S7Frf*r3M`!bvWU zbTgl2p}E<*fv?`N8=B71Dk03J=K@EEQ^|GY*NoHaB~(}_ zx`Su{onY@5(Owc#f`!=H`+_#I<0#PTT9kxp4Ig;Y4*Zi>!ehJ3AiGpwSGd<{Q7Ddh z8jZ(NQ*Nsz5Mu_F_~rtIK$YnxRsOcP-XzNZ)r|)zZYfkLFE8jK)LV-oH{?#)EM%gW zV^O7T z0Kmc1`!7m_~ zJl!{Cb80G#fuJa1K3>!bT@5&ww_VSVYIh_R#~;If$43z`T4-@R=a1Px7r@*tdBOTw zj-VzI{klG5NP!tNEo#~KLk(n`6CMgiinc1-i79z$SlM+eaorY!WDll+m6%i+5_6Mc zf#5j#MYBbY)Z#rd21gtgo3y@c(zQVYaIYKI%y2oVzbPWm;IE#Cw$8O$fV}v}S%QDA zkwxW{fa#Goh1O|+=CF3h3DWNw+L^ly?BNQ7DY~Eca}5nt^>p#3cc9s3iDub0nh`Wy z?oH|dW8-HG@d5E@U>NWPjnhTjr7C${Iwj#;F2G@++N=Y2tjV;z57RNgE|kXQC)1h- zx8ODU>kk};J8KiSUx5jSsA_XPou1OH8=R~q9{`r>VnHkU6A=!zNOH8IGJoO!+bQys zDS2-H(7+Jfe+&zf#;OSV=83I|^M;0`Kv*#4%%O7x>@BgGMU*@ajUvY>cYw^`*jm@+ z{LZ2lr{OTMoQXn2XUsK-l72oysi9vgV4Sux^1GsW6zTV;?p#J06EvSVyUq5$f4kq< z{Chq5Z?I%ZW}6&uL+f&0uCW#^LyL!Ac2*QRII5TDGfZ43YpXyS^9%6HBqqog$Sal3 zJjI$J+@}ja9Xp)Bnbk+pi=*ZAHN}8q@g$$g<6_4?ej&Rw)I%w(%jgGlS5dTHN`9(^<}Hg zD$PbZX+X>;$v4NjGJxMDvVBiIam$cP-;h0YqQ{YgxYn-g&!}lHgaG3^B=>Z!D*7tp zu19e;r`u*+@4h41Da&NZv$qy-i6#DdI)EVvmKO*PvIKz-9E5R*k#|`$zJza8QJ)Q{ zf~Vl+I=8oaq)K!lL7Et5ycH;m&LKIvC|z4FH5bo|>#Kg5z+Jy*8Ifai}5A#%@)TgPRaC4f>Qk&} z4WciN&V(T~u^xBgH=iP(#nd;_@L&`7FUF>Qm-;hOljv(!74f&if;fz2Mg=b%^8$^C zna!2I&iCz&9I5ckX-5mVoAwz~)_&b#&k$e+pp=U2q-OjkS@yZ8ly1$2Vh?}yF0={P zPd3O@g{0L=eT-Dm9?imeUP(!As&DJ_D=5lwQ=3)XWXg)12CoB=-g-HX9RSXgL;yo0 z?$7z8Sy9w?DvA^u`Fnl7r_J&_jJ7claq*2l9E~#iJIWAPXuAHfmF3-4YjFYhOXkNJ zVz8BS_4KCUe68n{cPOTTuD<#H&?*|ayPR2-eJ2U0j$#P!>fhd(LXM>b_0^Gm27$;s ze#JTrkdpb*ws{iJ1jprw#ta&Lz6OjSJhJgmwIaVo!K}znCdX>y!=@@V_=VLZlF&@t z!{_emFt$Xar#gSZi_S5Sn#7tBp`eSwPf73&Dsh52J3bXLqWA`QLoVjU35Q3S4%|Zl zR2x4wGu^K--%q2y=+yDfT*Ktnh#24Sm86n`1p@vJRT|!$B3zs6OWxGN9<}T-XX>1; zxAt4#T(-D3XwskNhJZ6Gvd?3raBu$`W+c(+$2E{_E_;yghgs~U1&XO6$%47BLJF4O zXKZLVTr6kc$Ee0WUBU0cw+uAe!djN=dvD*scic%t)0Jp*1& zhjKqEK+U~w93c<~m_Oh;HX{|zgz=>@(45=Ynh{k#3xlfg!k z>hsq90wPe(!NljYbnuL6s`Z!wQSL8|(A*@M8K>`nPJ<9Hb^ zB6o?#^9zP>3hp0>JAite*3N?Rm>nJ1Lpq4)eqSe8KM_f(0DB?k8DNN6(3 zU#>-{0}3~vYJ7iIwC?Zbh@aJ8kfIvY%RveZltThMN73#Ew}jOwVw+|vU5u-wMoo9C zO(tv#&5`DOhlzunPV?M~qlM|K74x4cBC_AC?2GNw_-Uv&QtPOj(7L4NtVh$`J%xci zioGVvj5s|GY886)(}g`4WS3_%%PrF(O|s-n&-SdfbssL`!Gi7Hrz_r$IO@*$1fYbQ zgdp6?(IUaNPaH7}0%U|9X8HFonsJRrVwfmf*o1;k0+PwV^i%f7U{LAayu`!x*FmhN za(#a^@Idw9)jN)K!=sFC(G)ZNaYY169*IJ_ouY9>W8tC>S&MEp$+7 zy)NFumpuE>=7T@`j}8pa)MGpJaZoG(Ex3AzzH>gUU^eyWp*N2Fx+9*4k~BU;lQ1PG zj4)_JlelzJ==t*7=n2(}B4^^bqqcKFcJ7yVzbH_CWK?{eXdpKm);4|o{aM=M&`E$=_~PVi2>>L zKTN_x&qA)@ak=v=0Hl5H6~?LOfO@1+fu5(sB|VWID)w?%{m+n#7bLaszEJ#;$HMdt z9qP0gk)hIYvE1!jseA^FGTyK=i4eTPjTL$R;6FywMBZBPlh2ar9!8wlj1sinLF-1g zR5}hLq>pb1|AC-WcF!38e*kFv|9n<$etuB=xE%B=PUs}iVFl>m;BiWUqRIxYh7}L&2w@{SS-t(zUp`wLWAyO=PEE=Ekvn@YS*K@($=i zBkTMaH<&cAk${idNy0KZ8xh}u;eAl*tstdM8DYnM5N;bDa`AB+(8>DqX+mj17R2xBp45UES|H*#GHb_%Nc{xWs7l{0pqmiBIPe@r=X%Y-h<-Ceo;4I>isrw1Hd zZd*VjT`H9gxbf{b3krEKNAaV$k>SzK(gzv}>;byq##WEhzTN^@B4+VJvW>y|U}}AQ z4^Bdz9%QKBWCy+h$I?L@ffl{fLLL41Tx|M+NjjRf(`KjHG4^y=x3l z!!-{*v7_^6MiJOC@C$WV=hz9J^Y^lK9#tzs6}-

Gn4F+B~IivciU9^t0j-Mgao3 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 DDw4oP diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e0fd02028..6514f919f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index f3b75f3b0..23d15a936 100755 --- a/gradlew +++ b/gradlew @@ -114,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -205,7 +205,7 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. @@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9d21a2183..db3a6ac20 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,11 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/settings.gradle b/settings.gradle index f8139930e..6f039dc93 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,5 @@ +plugins { + // Apply the foojay-resolver plugin to allow automatic download of JDKs + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.10.0' +} rootProject.name = 'Stirling-PDF' diff --git a/testing/test_webpages.sh b/testing/test_webpages.sh index 2091995af..fdc32c6eb 100644 --- a/testing/test_webpages.sh +++ b/testing/test_webpages.sh @@ -26,7 +26,7 @@ check_webpage() { fi # Check if response contains HTML - if ! printf '%s' "$BODY" | grep -q "\|\|> "$result_file" return 1 fi @@ -75,13 +75,13 @@ test_all_urls() { ((total_count++)) ((url_index++)) - + # Run the check in background test_url "$url" "$base_url" "$tmp_dir" "$url_index" & - + # Track the job ((active_jobs++)) - + # If we've reached max_parallel, wait for a job to finish if [ $active_jobs -ge $max_parallel ]; then wait -n # Wait for any child process to exit @@ -97,7 +97,7 @@ test_all_urls() { if [ -f "${tmp_dir}/result_${i}.txt" ]; then cat "${tmp_dir}/result_${i}.txt" fi - + if [ -f "${tmp_dir}/failed_${i}" ]; then failed_count=$((failed_count + $(cat "${tmp_dir}/failed_${i}"))) fi @@ -171,4 +171,4 @@ main() { # Run main if script is executed directly if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then main "$@" -fi \ No newline at end of file +fi