return false;
}
-function validateFile(element: WoltlabCoreFileUploadElement, file: File): boolean {
+function validateFileSize(element: WoltlabCoreFileUploadElement, file: File): boolean {
+ let isImage = false;
+ switch (file.type) {
+ case "image/gif":
+ case "image/jpeg":
+ case "image/png":
+ case "image/webp":
+ isImage = true;
+ break;
+ }
+
+ // Skip the file size validation for images, they can potentially be resized.
+ if (isImage) {
+ return true;
+ }
+
+ const maximumSize = element.maximumSize;
+ if (maximumSize === -1) {
+ return true;
+ }
+
+ if (file.size <= maximumSize) {
+ return true;
+ }
+
+ innerError(element, getPhrase("wcf.upload.error.fileSizeTooLarge", { filename: file.name }));
+
+ return false;
+}
+
+function validateFileExtension(element: WoltlabCoreFileUploadElement, file: File): boolean {
const fileExtensions = (element.dataset.fileExtensions || "*").split(",");
for (const fileExtension of fileExtensions) {
if (fileExtension === "*") {
if (!validateFileLimit(element)) {
return;
- } else if (!validateFile(element, file)) {
+ } else if (!validateFileExtension(element, file)) {
+ return;
+ } else if (!validateFileSize(element, file)) {
return;
}
clearPreviousErrors(element);
- if (!validateFile(element, file)) {
+ if (!validateFileExtension(element, file)) {
promiseReject!();
return;
return parseInt(this.dataset.maximumCount || "1");
}
+ get maximumSize(): number {
+ return parseInt(this.dataset.maximumSize || "-1");
+ }
+
get disabled(): boolean {
return this.#element.disabled;
}
get disabled(): boolean;
set disabled(disabled: boolean);
get maximumCount(): number;
+ get maximumSize(): number;
}
interface WoltlabCoreLoadingIndicatorElement extends HTMLElement {
(0, Util_1.innerError)(element, (0, Language_1.getPhrase)("wcf.upload.error.maximumCountReached", { maximumCount }));
return false;
}
- function validateFile(element, file) {
+ function validateFileSize(element, file) {
+ let isImage = false;
+ switch (file.type) {
+ case "image/gif":
+ case "image/jpeg":
+ case "image/png":
+ case "image/webp":
+ isImage = true;
+ break;
+ }
+ // Skip the file size validation for images, they can potentially be resized.
+ if (isImage) {
+ return true;
+ }
+ const maximumSize = element.maximumSize;
+ if (maximumSize === -1) {
+ return true;
+ }
+ if (file.size <= maximumSize) {
+ return true;
+ }
+ (0, Util_1.innerError)(element, (0, Language_1.getPhrase)("wcf.upload.error.fileSizeTooLarge", { filename: file.name }));
+ return false;
+ }
+ function validateFileExtension(element, file) {
const fileExtensions = (element.dataset.fileExtensions || "*").split(",");
for (const fileExtension of fileExtensions) {
if (fileExtension === "*") {
if (!validateFileLimit(element)) {
return;
}
- else if (!validateFile(element, file)) {
+ else if (!validateFileExtension(element, file)) {
+ return;
+ }
+ else if (!validateFileSize(element, file)) {
return;
}
void resizeImage(element, file).then((resizedFile) => {
promiseReject = reject;
});
clearPreviousErrors(element);
- if (!validateFile(element, file)) {
+ if (!validateFileExtension(element, file)) {
promiseReject();
return;
}
position: absolute;
visibility: hidden;
}
- `}get maximumCount(){return parseInt(this.dataset.maximumCount||"1")}get disabled(){return this.#e.disabled}set disabled(i){this.#e.disabled=!!i}}window.customElements.define("woltlab-core-file-upload",e)}{let r=[24,48,96];class i extends HTMLElement{#e;#a;connectedCallback(){this.#e===void 0&&this.#t()}attributeChangedCallback(t,a,l){if(t==="size"){let d=parseInt(l||"");if(!r.includes(d)){let g=parseInt(a||"");r.includes(g)||(g=24),this.setAttribute(t,g.toString())}}}#t(){this.classList.add("loading-indicator"),this.hasAttribute("size")||this.setAttribute("size",24 .toString()),this.#e=document.createElement("fa-icon"),this.#e.size=this.size,this.#e.setIcon("spinner"),this.#a=document.createElement("span"),this.#a.classList.add("loading-indicator__text"),this.#a.textContent=window.WoltLabLanguage.getPhrase("wcf.global.loading"),this.#a.hidden=this.hideText;let t=document.createElement("div");t.classList.add("loading-indicator__wrapper"),t.append(this.#e,this.#a),this.append(t)}get size(){return parseInt(this.getAttribute("size"))}set size(t){if(!r.includes(t))throw new TypeError(`The size ${t} is unrecognized, permitted values are ${r.join(", ")}.`);this.setAttribute("size",t.toString()),this.#e&&(this.#e.size=t)}get hideText(){return this.hasAttribute("hide-text")}set hideText(t){t?this.setAttribute("hide-text",""):this.removeAttribute("hide-text"),this.#a&&(this.#a.hidden=t)}static get observedAttributes(){return["size"]}}window.customElements.define("woltlab-core-loading-indicator",i)}{let e;(l=>(l.Info="info",l.Success="success",l.Warning="warning",l.Error="error"))(e||={});class r extends HTMLElement{#e;#a;connectedCallback(){let c=this.attachShadow({mode:"open"});this.#e=document.createElement("fa-icon"),this.#e.size=24,this.#e.setIcon(this.icon,!0),this.#e.slot="icon",this.append(this.#e);let t=document.createElement("style");t.textContent=`
+ `}get maximumCount(){return parseInt(this.dataset.maximumCount||"1")}get maximumSize(){return parseInt(this.dataset.maximumSize||"-1")}get disabled(){return this.#e.disabled}set disabled(i){this.#e.disabled=!!i}}window.customElements.define("woltlab-core-file-upload",e)}{let r=[24,48,96];class i extends HTMLElement{#e;#a;connectedCallback(){this.#e===void 0&&this.#t()}attributeChangedCallback(t,a,l){if(t==="size"){let d=parseInt(l||"");if(!r.includes(d)){let g=parseInt(a||"");r.includes(g)||(g=24),this.setAttribute(t,g.toString())}}}#t(){this.classList.add("loading-indicator"),this.hasAttribute("size")||this.setAttribute("size",24 .toString()),this.#e=document.createElement("fa-icon"),this.#e.size=this.size,this.#e.setIcon("spinner"),this.#a=document.createElement("span"),this.#a.classList.add("loading-indicator__text"),this.#a.textContent=window.WoltLabLanguage.getPhrase("wcf.global.loading"),this.#a.hidden=this.hideText;let t=document.createElement("div");t.classList.add("loading-indicator__wrapper"),t.append(this.#e,this.#a),this.append(t)}get size(){return parseInt(this.getAttribute("size"))}set size(t){if(!r.includes(t))throw new TypeError(`The size ${t} is unrecognized, permitted values are ${r.join(", ")}.`);this.setAttribute("size",t.toString()),this.#e&&(this.#e.size=t)}get hideText(){return this.hasAttribute("hide-text")}set hideText(t){t?this.setAttribute("hide-text",""):this.removeAttribute("hide-text"),this.#a&&(this.#a.hidden=t)}static get observedAttributes(){return["size"]}}window.customElements.define("woltlab-core-loading-indicator",i)}{let e;(l=>(l.Info="info",l.Success="success",l.Warning="warning",l.Error="error"))(e||={});class r extends HTMLElement{#e;#a;connectedCallback(){let c=this.attachShadow({mode:"open"});this.#e=document.createElement("fa-icon"),this.#e.size=24,this.#e.setIcon(this.icon,!0),this.#e.slot="icon",this.append(this.#e);let t=document.createElement("style");t.textContent=`
:host {
align-items: center;
display: grid;
return 1;
}
+ #[\Override]
+ public function getMaximumSize(array $context): ?int
+ {
+ // Do not limit the maximum size of an uploaded file.
+ return null;
+ }
+
#[\Override]
public function getResizeConfiguration(): ResizeConfiguration
{
return $attachmentHandler?->count();
}
+ #[\Override]
+ public function getMaximumSize(array $context): ?int
+ {
+ $attachmentHandler = $this->getAttachmentHandlerFromContext($context);
+ return $attachmentHandler?->getMaxSize();
+ }
+
private function getAttachmentHandlerFromContext(array $context): ?AttachmentHandler
{
try {
$maximumCount = -1;
}
+ $maximumSize = $fileProcessor->getMaximumSize($context);
+ if ($maximumSize === null) {
+ $maximumSize = -1;
+ }
+
return \sprintf(
<<<'HTML'
<woltlab-core-file-upload
data-file-extensions="%s"
data-resize-configuration="%s"
data-maximum-count="%d"
+ data-maximum-size="%d"
></woltlab-core-file-upload>
HTML,
StringUtil::encodeHTML($fileProcessor->getObjectTypeName()),
StringUtil::encodeHTML($allowedFileExtensions),
StringUtil::encodeHTML(JSON::encode($fileProcessor->getResizeConfiguration())),
$maximumCount,
+ $maximumSize,
);
}
* it does not track this for whatever reason.
*
* @param array<string,string> $context
- * @return null|int number of existing files or `null` if this should not be enforced
+ * @return null|int Number of existing files or `null` if this should not be enforced
*/
public function countExistingFiles(array $context): ?int;
*/
public function getMaximumCount(array $context): ?int;
+ /**
+ * Limits the maximum size of an uploade file.
+ *
+ * @param array<string,string> $context
+ * @return null|int Maximum size in bytes or null to disable the limit.
+ */
+ public function getMaximumSize(array $context): ?int;
+
/**
* Controls the client-side resizing of some types of images before they are
* being uploaded to the server.