Merge branch 'main' into 2728-bug-signed-rotated-document-different-than-preview

This commit is contained in:
ConnorYoh 2025-04-15 17:41:05 +01:00 committed by GitHub
commit 8748eaaa76
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 109 additions and 111 deletions

View File

@ -141,7 +141,7 @@ Stirling-PDF currently supports 39 languages!
| Persian (فارسی) (fa_IR) | ![88%](https://geps.dev/progress/88) | | Persian (فارسی) (fa_IR) | ![88%](https://geps.dev/progress/88) |
| Polish (Polski) (pl_PL) | ![96%](https://geps.dev/progress/96) | | Polish (Polski) (pl_PL) | ![96%](https://geps.dev/progress/96) |
| Portuguese (Português) (pt_PT) | ![91%](https://geps.dev/progress/91) | | Portuguese (Português) (pt_PT) | ![91%](https://geps.dev/progress/91) |
| Portuguese Brazilian (Português) (pt_BR) | ![94%](https://geps.dev/progress/94) | | Portuguese Brazilian (Português) (pt_BR) | ![98%](https://geps.dev/progress/98) |
| Romanian (Română) (ro_RO) | ![75%](https://geps.dev/progress/75) | | Romanian (Română) (ro_RO) | ![75%](https://geps.dev/progress/75) |
| Russian (Русский) (ru_RU) | ![94%](https://geps.dev/progress/94) | | Russian (Русский) (ru_RU) | ![94%](https://geps.dev/progress/94) |
| Serbian Latin alphabet (Srpski) (sr_LATN_RS) | ![60%](https://geps.dev/progress/60) | | Serbian Latin alphabet (Srpski) (sr_LATN_RS) | ![60%](https://geps.dev/progress/60) |

View File

@ -29,7 +29,7 @@ ext {
} }
group = "stirling.software" group = "stirling.software"
version = "0.45.5" version = "0.45.6"
java { java {
// 17 is lowest but we support and recommend 21 // 17 is lowest but we support and recommend 21

View File

@ -109,33 +109,6 @@ public class AppConfig {
return (rateLimit != null) ? Boolean.valueOf(rateLimit) : false; return (rateLimit != null) ? Boolean.valueOf(rateLimit) : false;
} }
@Bean(name = "uploadLimit")
public long uploadLimit() {
String maxUploadSize =
applicationProperties.getSystem().getFileUploadLimit() != null
? applicationProperties.getSystem().getFileUploadLimit()
: "";
if (maxUploadSize.isEmpty()) {
return 0;
} else if (!new Regex("^[1-9][0-9]{0,2}[KMGkmg][Bb]$").matches(maxUploadSize)) {
log.error(
"Invalid maxUploadSize format. Expected format: [1-9][0-9]{0,2}[KMGkmg][Bb], but got: {}",
maxUploadSize);
return 0;
} else {
String unit = maxUploadSize.replaceAll("[1-9][0-9]{0,2}", "").toUpperCase();
String number = maxUploadSize.replaceAll("[KMGkmg][Bb]", "");
long size = Long.parseLong(number);
return switch (unit) {
case "KB" -> size * 1024;
case "MB" -> size * 1024 * 1024;
case "GB" -> size * 1024 * 1024 * 1024;
default -> 0;
};
}
}
@Bean(name = "RunningInDocker") @Bean(name = "RunningInDocker")
public boolean runningInDocker() { public boolean runningInDocker() {
return Files.exists(Paths.get("/.dockerenv")); return Files.exists(Paths.get("/.dockerenv"));

View File

@ -1,30 +0,0 @@
package stirling.software.SPDF.controller.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;
@Component
@ControllerAdvice
public class GlobalUploadLimitWebController {
@Autowired() private long uploadLimit;
@ModelAttribute("uploadLimit")
public long populateUploadLimit() {
return uploadLimit;
}
@ModelAttribute("uploadLimitReadable")
public String populateReadableLimit() {
return humanReadableByteCount(uploadLimit);
}
private String humanReadableByteCount(long bytes) {
if (bytes < 1024) return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(1024));
String pre = "KMGTPE".charAt(exp - 1) + "B";
return String.format("%.1f %s", bytes / Math.pow(1024, exp), pre);
}
}

View File

@ -0,0 +1,55 @@
package stirling.software.SPDF.controller.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.ApplicationProperties;
import java.util.regex.Pattern;
@Service
@Slf4j
public class UploadLimitService {
@Autowired
private ApplicationProperties applicationProperties;
public long getUploadLimit() {
String maxUploadSize =
applicationProperties.getSystem().getFileUploadLimit() != null
? applicationProperties.getSystem().getFileUploadLimit()
: "";
if (maxUploadSize.isEmpty()) {
return 0;
} else if (!Pattern.compile("^[1-9][0-9]{0,2}[KMGkmg][Bb]$").matcher(maxUploadSize).matches()) {
log.error(
"Invalid maxUploadSize format. Expected format: [1-9][0-9]{0,2}[KMGkmg][Bb], but got: {}",
maxUploadSize);
return 0;
} else {
String unit = maxUploadSize.replaceAll("[1-9][0-9]{0,2}", "").toUpperCase();
String number = maxUploadSize.replaceAll("[KMGkmg][Bb]", "");
long size = Long.parseLong(number);
return switch (unit) {
case "KB" -> size * 1024;
case "MB" -> size * 1024 * 1024;
case "GB" -> size * 1024 * 1024 * 1024;
default -> 0;
};
}
}
//TODO: why do this server side not client?
public String getReadableUploadLimit() {
return humanReadableByteCount(getUploadLimit());
}
private String humanReadableByteCount(long bytes) {
if (bytes < 1024) return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(1024));
String pre = "KMGTPE".charAt(exp - 1) + "B";
return String.format("%.1f %s", bytes / Math.pow(1024, exp), pre);
}
}

View File

@ -10,9 +10,9 @@ multiPdfPrompt=Selecione os PDFs (2+)
multiPdfDropPrompt=Selecione (ou arraste e solte) todos os PDFs desejados: multiPdfDropPrompt=Selecione (ou arraste e solte) todos os PDFs desejados:
imgPrompt=Selecione a(s) Imagem(ns) imgPrompt=Selecione a(s) Imagem(ns)
genericSubmit=Enviar genericSubmit=Enviar
uploadLimit=Maximum file size: uploadLimit=Tamanho máximo do arquivo:
uploadLimitExceededSingular=is too large. Maximum allowed size is uploadLimitExceededSingular=está acima do limite. Tamanho máximo permitido é
uploadLimitExceededPlural=are too large. Maximum allowed size is uploadLimitExceededPlural=estão acima do limite. Tamanho máximo permitido é
processTimeWarning=Aviso: Este processo pode levar até um minuto, dependendo do tamanho do arquivo processTimeWarning=Aviso: Este processo pode levar até um minuto, dependendo do tamanho do arquivo
pageOrderPrompt=Ordem de Página Personalizada (Digite uma lista de números de páginas, separadas por vírgula ou funções como 2n+1): pageOrderPrompt=Ordem de Página Personalizada (Digite uma lista de números de páginas, separadas por vírgula ou funções como 2n+1):
pageSelectionPrompt=Seleção de Página Personalizada (Digite uma lista de números de páginas, separadas por vírgula como 1,5,6 ou funções como 2n+1): pageSelectionPrompt=Seleção de Página Personalizada (Digite uma lista de números de páginas, separadas por vírgula como 1,5,6 ou funções como 2n+1):
@ -86,14 +86,14 @@ loading=Carregando...
addToDoc=Adicionar ao Documento addToDoc=Adicionar ao Documento
reset=Reiniciar reset=Reiniciar
apply=Aplicar apply=Aplicar
noFileSelected=No file selected. Please upload one. noFileSelected=Nenhum arquivo selecionado. Por favo, envie um arquivo.
legal.privacy=Política de Privacidade legal.privacy=Política de Privacidade
legal.terms=Termos e Condições legal.terms=Termos e Condições
legal.accessibility=Acessibilidade legal.accessibility=Acessibilidade
legal.cookie=Política de Cookies legal.cookie=Política de Cookies
legal.impressum=Informações legais legal.impressum=Informações legais
legal.showCookieBanner=Cookie Preferences legal.showCookieBanner=Preferências de Cookies
############### ###############
# Pipeline # # Pipeline #
@ -237,31 +237,31 @@ adminUserSettings.activeUsers=Usuários Ativos:
adminUserSettings.disabledUsers=Usuários Desabilitados: adminUserSettings.disabledUsers=Usuários Desabilitados:
adminUserSettings.totalUsers=Total de Usuários: adminUserSettings.totalUsers=Total de Usuários:
adminUserSettings.lastRequest=Última solicitação adminUserSettings.lastRequest=Última solicitação
adminUserSettings.usage=View Usage adminUserSettings.usage=Ver Utilização
endpointStatistics.title=Endpoint Statistics endpointStatistics.title=Estatísticas de Endpoints
endpointStatistics.header=Endpoint Statistics endpointStatistics.header=Estatísticas de Endpoints
endpointStatistics.top10=Top 10 endpointStatistics.top10=Top 10
endpointStatistics.top20=Top 20 endpointStatistics.top20=Top 20
endpointStatistics.all=All endpointStatistics.all=Todos
endpointStatistics.refresh=Refresh endpointStatistics.refresh=Atualizar
endpointStatistics.includeHomepage=Include Homepage ('/') endpointStatistics.includeHomepage=Incluir Página Inicial ('/')
endpointStatistics.includeLoginPage=Include Login Page ('/login') endpointStatistics.includeLoginPage=Incluir Página de Login ('/login')
endpointStatistics.totalEndpoints=Total Endpoints endpointStatistics.totalEndpoints=Total de Endpoints
endpointStatistics.totalVisits=Total Visits endpointStatistics.totalVisits=Total de Visitas
endpointStatistics.showing=Showing endpointStatistics.showing=Mostrando
endpointStatistics.selectedVisits=Selected Visits endpointStatistics.selectedVisits=Visitas Selecionadas
endpointStatistics.endpoint=Endpoint endpointStatistics.endpoint=Endpoint
endpointStatistics.visits=Visits endpointStatistics.visits=Visitas
endpointStatistics.percentage=Percentage endpointStatistics.percentage=Percentagem
endpointStatistics.loading=Loading... endpointStatistics.loading=Carregando...
endpointStatistics.failedToLoad=Failed to load endpoint data. Please try refreshing. endpointStatistics.failedToLoad=Falha ao carregar dados do Endpoint. Por favor, tente atualizar.
endpointStatistics.home=Home endpointStatistics.home=Home
endpointStatistics.login=Login endpointStatistics.login=Login
endpointStatistics.top=Top endpointStatistics.top=Top
endpointStatistics.numberOfVisits=Number of Visits endpointStatistics.numberOfVisits=Número de Visitas
endpointStatistics.visitsTooltip=Visits: {0} ({1}% of total) endpointStatistics.visitsTooltip=Visitas: {0} ({1}% do total)
endpointStatistics.retry=Retry endpointStatistics.retry=Tentar novamente
database.title=Importar/Exportar banco de dados database.title=Importar/Exportar banco de dados
database.header=Importar/Exportar banco de dados database.header=Importar/Exportar banco de dados
@ -739,10 +739,10 @@ sanitizePDF.title=Higienizar
sanitizePDF.header=Higienizar sanitizePDF.header=Higienizar
sanitizePDF.selectText.1=Remover scripts de JavaScript. sanitizePDF.selectText.1=Remover scripts de JavaScript.
sanitizePDF.selectText.2=Remover arquivos embutidos. sanitizePDF.selectText.2=Remover arquivos embutidos.
sanitizePDF.selectText.3=Remove XMP metadata sanitizePDF.selectText.3=Remover metadados XMP.
sanitizePDF.selectText.4=Remover links. sanitizePDF.selectText.4=Remover links.
sanitizePDF.selectText.5=Remover fontes. sanitizePDF.selectText.5=Remover fontes.
sanitizePDF.selectText.6=Remove Document Info Metadata sanitizePDF.selectText.6=Remover metadados de informações do documento.
sanitizePDF.submit=Higienizar PDF sanitizePDF.submit=Higienizar PDF
@ -1408,25 +1408,25 @@ validateSignature.cert.bits=bits
#################### ####################
# Cookie banner # # Cookie banner #
#################### ####################
cookieBanner.popUp.title=How we use Cookies cookieBanner.popUp.title=Como nós utilizamos 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.1=Nós utilizamos cookies e outras tecnologias para melhorar o Stirling PDF, ajude-nos para que possamos desenvolver novas funcionalidades que você irá amar.
cookieBanner.popUp.description.2=If youd rather not, clicking 'No Thanks' will only enable the essential cookies needed to keep things running smoothly. cookieBanner.popUp.description.2=Se você não tiver interesse, clicando em "Não, Obrigado" será habilitado apenas cookies essenciais, para o site funcionar sem problemas.
cookieBanner.popUp.acceptAllBtn=Okay cookieBanner.popUp.acceptAllBtn=Aceito
cookieBanner.popUp.acceptNecessaryBtn=No Thanks cookieBanner.popUp.acceptNecessaryBtn=Não, Obrigado
cookieBanner.popUp.showPreferencesBtn=Manage preferences cookieBanner.popUp.showPreferencesBtn=Gerenciar Preferências
cookieBanner.preferencesModal.title=Consent Preferences Center cookieBanner.preferencesModal.title=Central de Preferências de Consentimento
cookieBanner.preferencesModal.acceptAllBtn=Accept all cookieBanner.preferencesModal.acceptAllBtn=Aceitar tudo
cookieBanner.preferencesModal.acceptNecessaryBtn=Reject all cookieBanner.preferencesModal.acceptNecessaryBtn=Rejeitar tudo
cookieBanner.preferencesModal.savePreferencesBtn=Save preferences cookieBanner.preferencesModal.savePreferencesBtn=Salvar preferências
cookieBanner.preferencesModal.closeIconLabel=Close modal cookieBanner.preferencesModal.closeIconLabel=Fechar janela
cookieBanner.preferencesModal.serviceCounterLabel=Service|Services cookieBanner.preferencesModal.serviceCounterLabel=Serviço|Serviços
cookieBanner.preferencesModal.subtitle=Cookie Usage cookieBanner.preferencesModal.subtitle=Uso de Cookies
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.1=Stirling PDF utiliza cookies e tecnologias semelhantes para aprimorar sua experiência e entender como nossas ferramentas são utilizadas. Isso nos ajuda a melhorar o desempenho, desenvolver os recursos de seu interesse e fornecer suporte contínuo aos nossos usuários.
cookieBanner.preferencesModal.description.2=Stirling PDF cannot—and will never—track or access the content of the documents you use. cookieBanner.preferencesModal.description.2=O Stirling PDF não pode e nunca irá rastrear ou acessar o conteúdo dos documentos que você manipula.
cookieBanner.preferencesModal.description.3=Your privacy and trust are at the core of what we do. cookieBanner.preferencesModal.description.3=Sua privacidade e confiança são prioridades para nós.
cookieBanner.preferencesModal.necessary.title.1=Strictly Necessary Cookies cookieBanner.preferencesModal.necessary.title.1=Cookies Estritamente Necessários
cookieBanner.preferencesModal.necessary.title.2=Always Enabled cookieBanner.preferencesModal.necessary.title.2=Sempre Ativado
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 cant be turned off. cookieBanner.preferencesModal.necessary.description=Estes cookies são essenciais para o bom funcionamento do site. Eles habilitam recursos básicos como definir suas preferências de privacidade, realizar login e preencher formulários e é por isso que não podem ser desativados.
cookieBanner.preferencesModal.analytics.title=Analytics cookieBanner.preferencesModal.analytics.title=Cookies Analíticos
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.preferencesModal.analytics.description=Estes cookies nos ajudam a entender como nossas ferramentas estão sendo utilizadas, para que possamos nos concentrar na construção dos recursos que nossa comunidade mais valoriza. Fique tranquilo: o Stirling PDF não pode e nunca rastreará o conteúdo dos documentos com os quais você manipula.

View File

@ -240,8 +240,8 @@
window.stirlingPDF.sessionExpired = /*[[#{session.expired}]]*/ ''; window.stirlingPDF.sessionExpired = /*[[#{session.expired}]]*/ '';
window.stirlingPDF.refreshPage = /*[[#{session.refreshPage}]]*/ 'Refresh Page'; window.stirlingPDF.refreshPage = /*[[#{session.refreshPage}]]*/ 'Refresh Page';
window.stirlingPDF.error = /*[[#{error}]]*/ "Error"; window.stirlingPDF.error = /*[[#{error}]]*/ "Error";
window.stirlingPDF.uploadLimit = /*[[${uploadLimit}]]*/ 0; window.stirlingPDF.uploadLimitReadable = /*[[${@uploadLimitService.getReadableUploadLimit()}]]*/ 'Unlimited';
window.stirlingPDF.uploadLimitReadable = /*[[${uploadLimitReadable}]]*/ 'Unlimited'; window.stirlingPDF.uploadLimit = /*[[${@uploadLimitService.getUploadLimit()}]]*/ 0;
window.stirlingPDF.uploadLimitExceededSingular = /*[[#{uploadLimitExceededSingular}]]*/ 'is too large. Maximum allowed size is'; window.stirlingPDF.uploadLimitExceededSingular = /*[[#{uploadLimitExceededSingular}]]*/ 'is too large. Maximum allowed size is';
window.stirlingPDF.uploadLimitExceededPlural = /*[[#{uploadLimitExceededPlural}]]*/ 'are too large. Maximum allowed size is'; window.stirlingPDF.uploadLimitExceededPlural = /*[[#{uploadLimitExceededPlural}]]*/ 'are too large. Maximum allowed size is';
})(); })();
@ -292,9 +292,9 @@
</div> </div>
</div> </div>
<div class="selected-files flex-wrap"></div> <div class="selected-files flex-wrap"></div>
<div class="text-muted small mt-0 text-end w-100" th:if="${uploadLimit != 0}"> <div class="text-muted small mt-0 text-end w-100" th:if="${@uploadLimitService.getUploadLimit() != 0}">
<span th:text="#{uploadLimit}">Maximum file size: </span> <span th:text="#{uploadLimit}">Maximum file size: </span>
<span th:text="${uploadLimitReadable}"></span> <span th:text="${@uploadLimitService.getReadableUploadLimit()}"></span>
</div> </div>
</div> </div>
<div class="progressBarContainer" style="display: none; position: relative;"> <div class="progressBarContainer" style="display: none; position: relative;">