Skip to content

Commit

Permalink
Merge pull request #360 from Frooodle/itextRemoval
Browse files Browse the repository at this point in the history
Itext removal password enhancement and others
  • Loading branch information
Frooodle authored Sep 14, 2023
2 parents fefa834 + 315cba0 commit e5a7a06
Show file tree
Hide file tree
Showing 156 changed files with 1,920 additions and 1,064 deletions.
4 changes: 2 additions & 2 deletions HowToAddNewLanguage.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Fork Stirling-PDF and make a new branch out of Main

Then add reference to the language in the navbar by adding a new language entry to the dropdown

https://github.com/Frooodle/Stirling-PDF/blob/main/src/main/resources/templates/fragments/navbar.html#L306
https://github.com/Frooodle/Stirling-PDF/blob/main/src/main/resources/templates/fragments/languages.html
and add a flag svg file to
https://github.com/Frooodle/Stirling-PDF/tree/main/src/main/resources/static/images/flags
Any SVG flags are fine, i got most of mine from [here](https://flagicons.lipis.dev/)
Expand All @@ -25,7 +25,7 @@ The data-language-code is the code used to reference the file in the next step.

Start by copying the existing english property file

[https://github.com/Frooodle/Stirling-PDF/tree/langSetup/src/main/resources/messages_en_GB.properties](https://github.com/Frooodle/Stirling-PDF/blob/main/src/main/resources/messages_en_US.properties)
[https://github.com/Frooodle/Stirling-PDF/blob/main/src/main/resources/messages_en_GB.properties](https://github.com/Frooodle/Stirling-PDF/blob/main/src/main/resources/messages_en_GB.properties)

Copy and rename it to messages_{your data-language-code here}.properties, in the polish example you would set the name to messages_pl_PL.properties

Expand Down
104 changes: 63 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,42 +23,63 @@ Feel free to request any features or bug fixes either in github issues or our [D
![stirling-home](images/stirling-home.png)

## Features
- Full interactive GUI for merging/splitting/rotating/moving PDFs and their pages.
- Split PDFs into multiple files at specified page numbers or extract all pages as individual files.
- Merge multiple PDFs together into a single resultant file
- Convert PDFs to and from images
- Reorganize PDF pages into different orders.
- Add/Generate signatures
- Format PDFs into a multi-paged page
- Scale page contents size by set %
- Adjust Contrast
- Crop PDF
- Auto Split PDF (With physically scanned page dividers)
- Flatten PDFs
- Repair PDFs
- Detect and remove blank pages
- Compare 2 PDFs and show differences in text
- Add images to PDFs
- Rotating PDFs in 90 degree increments.
- Compressing PDFs to decrease their filesize. (Using OCRMyPDF)
- Add and remove passwords
- Set PDF Permissions
- Add watermark(s)
- Convert Any common file to PDF (using LibreOffice)
- Convert PDF to Word/Powerpoint/Others (using LibreOffice)
- Convert HTML to PDF
- URL to PDF
- Extract images from PDF
- Extract images from Scans
- Add page numbers
- Auto rename file by detecting PDF header text
- OCR on PDF (Using OCRMyPDF)
- PDF/A conversion (Using OCRMyPDF)
- Edit metadata
- Dark mode support.
- Custom download options (see [here](https://github.com/Frooodle/Stirling-PDF/blob/main/images/settings.png) for example)
- Parallel file processing and downloads
- API for integration with external scripts
- Optional Login and Authentication support (see [here](https://github.com/Frooodle/Stirling-PDF/tree/main#login-authentication) for documentation)


## **PDF Features**

### **Page Operations**
- Full interactive GUI for merging/splitting/rotating/moving PDFs and their pages.
- Merge multiple PDFs together into a single resultant file.
- Split PDFs into multiple files at specified page numbers or extract all pages as individual files.
- Reorganize PDF pages into different orders.
- Rotate PDFs in 90-degree increments.
- Remove pages.
- Multi-page layout (Format PDFs into a multi-paged page).
- Scale page contents size by set %.
- Adjust Contrast.
- Crop PDF.
- Auto Split PDF (With physically scanned page dividers).
- Extract page(s).
- Convert PDF to a single page.

### **Conversion Operations**
- Convert PDFs to and from images.
- Convert any common file to PDF (using LibreOffice).
- Convert PDF to Word/Powerpoint/Others (using LibreOffice).
- Convert HTML to PDF.
- URL to PDF.
- Markdown to PDF.

### **Security & Permissions**
- Add and remove passwords.
- Change/set PDF Permissions.
- Add watermark(s).
- Certify/sign PDFs.
- Sanitize PDFs.
- Auto-redact text.

### **Other Operations**
- Add/Generate/Write signatures.
- Repair PDFs.
- Detect and remove blank pages.
- Compare 2 PDFs and show differences in text.
- Add images to PDFs.
- Compress PDFs to decrease their filesize (Using OCRMyPDF).
- Extract images from PDF.
- Extract images from Scans.
- Add page numbers.
- Auto rename file by detecting PDF header text.
- OCR on PDF (Using OCRMyPDF).
- PDF/A conversion (Using OCRMyPDF).
- Edit metadata.
- Flatten PDFs.
- Get all information on a PDF to view or export as JSON.


For a overview of the tasks and the technology each uses please view [groups.md](https://github.com/Frooodle/Stirling-PDF/blob/main/Groups.md)
Hosted instance/demo of the app can be seen [here](https://pdf.adminforge.de/) hosted by the team at adminforge.de
Expand Down Expand Up @@ -94,6 +115,7 @@ docker run -d \
-p 8080:8080 \
-v /location/of/trainingData:/usr/share/tesseract-ocr/4.00/tessdata \
-v /location/of/extraConfigs:/configs \
-e DOCKER_ENABLE_SECURITY=false \
--name stirling-pdf \
frooodle/s-pdf:latest
Expand All @@ -114,16 +136,18 @@ services:
- /location/of/trainingData:/usr/share/tesseract-ocr/4.00/tessdata #Required for extra OCR languages
- /location/of/extraConfigs:/configs
# - /location/of/customFiles:/customFiles/
environment:
- DOCKER_ENABLE_SECURITY=false
```


## Enable OCR/Compression feature
Please view https://github.com/Frooodle/Stirling-PDF/blob/main/HowToUseOCR.md

## Want to add your own language?
Stirling PDF currently supports 16!
Stirling PDF currently supports 18!
- English (English) (en_GB)
- English (US) (en_US)
- Arabic (العربية) (ar_AR)
- German (Deutsch) (de_DE)
- French (Français) (fr_FR)
Expand All @@ -139,6 +163,7 @@ Stirling PDF currently supports 16!
- Russian (Русский) (ru_RU)
- Basque (Euskara) (eu_ES)
- Japanese (日本語) (ja_JP)
- Dutch (Nederlands) (nl_NL)

If you want to add your own language to Stirling-PDF please refer
https://github.com/Frooodle/Stirling-PDF/blob/main/HowToAddNewLanguage.md
Expand Down Expand Up @@ -173,9 +198,6 @@ The Current list of settings is
```
security:
enableLogin: false # set to 'true' to enable login
initialLogin:
username: 'username' # Specify the initial username for first boot (e.g. 'admin')
password: 'password' # Specify the initial password for first boot (e.g. 'password123')
csrfDisabled: true
system:
Expand All @@ -193,7 +215,7 @@ endpoints:
groupsToRemove: [] # List groups to disable (e.g. ['LibreOffice'])
metrics:
enabled: true # 'true' to enable Info APIs (`/api/*`) endpoints, 'false' to disable
enabled: true # 'true' to enable Info APIs endpoints (view http://localhost:8080/swagger-ui/index.html#/API to learn more), 'false' to disable
```
### Extra notes
- Endpoints. Currently, the endpoints ENDPOINTS_TO_REMOVE and GROUPS_TO_REMOVE can include comma separate lists of endpoints and groups to disable as example ENDPOINTS_TO_REMOVE=img-to-pdf,remove-pages would disable both image-to-pdf and remove pages, GROUPS_TO_REMOVE=LibreOffice Would disable all things that use LibreOffice. You can see a list of all endpoints and groups [here](https://github.com/Frooodle/Stirling-PDF/blob/main/groups.md)
Expand All @@ -213,11 +235,11 @@ For those wanting to use Stirling-PDFs backend API to link with their own custom
### Prerequisites:
- User must have the folder ./configs volumed within docker so that it is retained during updates.
- Docker uses must download the security jar version by setting ``DOCKER_ENABLE_SECURITY`` to ``true`` in environment variables.
- Now the initial user must be generated. Navigate to your settings.yaml and configure your security settings along with the username and password (only required on the first boot to create the initial user, ignored after.). Alternatively, you can set these via the environment variables ``SECURITY_ENABLELOGIN : true`` ``SECURITY_INITIALLOGIN_USERNAME: username`` ``SECURITY_INITIALLOGIN_PASSWORD: password``
- Now the initial user will be generated with username ``admin`` and password ``stirling``. On login you will be forced to change the password to a new one.

Once the above has been done, on restart, a new stirling-pdf-DB.mv.db will show if everything worked.

When you login to Stirling PDF you will be redirected to /login page to login with those credentials. After login everything should function as normal
When you login to Stirling PDF you will be redirected to /login page to login with those default credentials. After login everything should function as normal

To access your account settings go to Account settings in the settings cog menu (top right in navbar) This Account settings menu is also where you find your API key.

Expand All @@ -232,7 +254,7 @@ For API usage you must provide a header with 'X-API-Key' and the associated API
- Progress bar/Tracking
- Full custom logic pipelines to combine multiple operations together.
- Folder support with auto scanning to perform operations on
- Redact text (Via UI)
- Redact text (Via UI not just automated way)
- Add Forms
- Annotations
- Multi page layout (Stich PDF pages together) support x rows y columns and custom page sizing
Expand Down
4 changes: 3 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ plugins {
}

group = 'stirling.software'
version = '0.13.1'
version = '0.14.0'
sourceCompatibility = '17'

repositories {
Expand Down Expand Up @@ -98,6 +98,8 @@ dependencies {
implementation 'com.github.vladimir-bukhtoyarov:bucket4j-core:7.6.0'

developmentOnly("org.springframework.boot:spring-boot-devtools")
compileOnly 'org.projectlombok:lombok:1.18.28'
annotationProcessor 'org.projectlombok:lombok:1.18.28'

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons
String queryString = request.getQueryString();
if (queryString != null && !queryString.isEmpty()) {
String requestURI = request.getRequestURI();

Map<String, String> parameters = new HashMap<>();

// Keep only the allowed parameters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,32 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.general.CropPdfForm;
import stirling.software.SPDF.utils.WebResponseUtils;

@RestController
@RequestMapping("/api/v1/general")
@Tag(name = "General", description = "General APIs")
public class CropController {

private static final Logger logger = LoggerFactory.getLogger(CropController.class);

@PostMapping(value = "/crop", consumes = "multipart/form-data")
@Operation(summary = "Crops a PDF document", description = "This operation takes an input PDF file and crops it according to the given coordinates. Input:PDF Output:PDF Type:SISO")
public ResponseEntity<byte[]> cropPdf(
@Parameter(description = "The input PDF file", required = true) @RequestParam("fileInput") MultipartFile file,
@Parameter(description = "The x-coordinate of the top-left corner of the crop area", required = true, schema = @Schema(type = "number")) @RequestParam("x") float x,
@Parameter(description = "The y-coordinate of the top-left corner of the crop area", required = true, schema = @Schema(type = "number")) @RequestParam("y") float y,
@Parameter(description = "The width of the crop area", required = true, schema = @Schema(type = "number")) @RequestParam("width") float width,
@Parameter(description = "The height of the crop area", required = true, schema = @Schema(type = "number")) @RequestParam("height") float height)
public ResponseEntity<byte[]> cropPdf(@ModelAttribute CropPdfForm form)
throws IOException {





PDDocument sourceDocument = PDDocument.load(new ByteArrayInputStream(file.getBytes()));
PDDocument sourceDocument = PDDocument.load(new ByteArrayInputStream(form.getFileInput().getBytes()));

PDDocument newDocument = new PDDocument();

Expand All @@ -65,7 +60,7 @@ public ResponseEntity<byte[]> cropPdf(
contentStream.saveGraphicsState();

// Define the crop area
contentStream.addRect(x, y, width, height);
contentStream.addRect(form.getX(), form.getY(), form.getWidth(), form.getHeight());
contentStream.clip();

// Draw the entire formXObject
Expand All @@ -76,7 +71,7 @@ public ResponseEntity<byte[]> cropPdf(
contentStream.close();

// Now, set the new page's media box to the cropped size
newPage.setMediaBox(new PDRectangle(x, y, width, height));
newPage.setMediaBox(new PDRectangle(form.getX(), form.getY(), form.getWidth(), form.getHeight()));
}

ByteArrayOutputStream baos = new ByteArrayOutputStream();
Expand All @@ -85,7 +80,7 @@ public ResponseEntity<byte[]> cropPdf(
sourceDocument.close();

byte[] pdfContent = baos.toByteArray();
return WebResponseUtils.bytesToWebResponse(pdfContent, file.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_cropped.pdf");
return WebResponseUtils.bytesToWebResponse(pdfContent, form.getFileInput().getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_cropped.pdf");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.general.MergePdfsRequest;
import stirling.software.SPDF.utils.WebResponseUtils;

@RestController
@RequestMapping("/api/v1/general")
@Tag(name = "General", description = "General APIs")
public class MergeController {

Expand Down Expand Up @@ -88,20 +88,10 @@ private Comparator<MultipartFile> getSortComparator(String sortType) {
@PostMapping(consumes = "multipart/form-data", value = "/merge-pdfs")
@Operation(summary = "Merge multiple PDF files into one",
description = "This endpoint merges multiple PDF files into a single PDF file. The merged file will contain all pages from the input files in the order they were provided. Input:PDF Output:PDF Type:MISO")
public ResponseEntity<byte[]> mergePdfs(
@RequestPart(required = true, value = "fileInput") MultipartFile[] files,
@RequestParam(value = "sortType", defaultValue = "orderProvided")
@Parameter(schema = @Schema(description = "The type of sorting to be applied on the input files before merging.",
allowableValues = {
"orderProvided",
"byFileName",
"byDateModified",
"byDateCreated",
"byPDFTitle"
}))
String sortType) throws IOException {
public ResponseEntity<byte[]> mergePdfs(@ModelAttribute MergePdfsRequest form) throws IOException {

Arrays.sort(files, getSortComparator(sortType));
MultipartFile[] files = form.getFileInput();
Arrays.sort(files, getSortComparator(form.getSortType()));

List<PDDocument> documents = new ArrayList<>();
for (MultipartFile file : files) {
Expand Down
Loading

0 comments on commit e5a7a06

Please sign in to comment.