Skip to content
Snippets Groups Projects
Commit 8a3e2739 authored by Victor Piryns (pivi)'s avatar Victor Piryns (pivi)
Browse files

[FIX] web: truncate filename when importing custom module via studio


Issue:
When uploading a large custom module via studio for importing, Chrome
crashes with an internal SIGKILL and Firefox manages to load, but is
really sluggish.

Steps to reproduce:
- Install Studio
- In the Apps Dashboard > Customizations > Import
- Upload a large custom module (50 MiB)
- Chrome crashes, while on Firefox the page is sluggish

Cause:
In the module `base_import_module`, the `module_file` doesn't have a
corresponding `filename`, therefor the name used to be displayed in
the wizard is the content of the binary file in base64 encoding...
For a module that is of a large size, this is a *gigantic* string
that crashes Chrome and slows down the DOM on Firefox.

Fix:
Truncate the maximum filename that is displayed in the template to
the max length necessary to encode in base64 (0xFF) 255 bytes, as
255 bytes is the maximum filename size on Linux/Windows/MacOS.

Affected versions:
16.0 up to master

Reference:
opw-3491998

closes odoo/odoo#134165

Signed-off-by: default avatarAaron Bohy (aab) <aab@odoo.com>
parent 0b0fd85c
Branches
Tags
No related merge requests found
......@@ -3,3 +3,12 @@
export function isBinarySize(value) {
return /^\d+(\.\d*)? [^0-9]+$/.test(value);
}
/**
* Get the length necessary for a base64 str to encode maxBytes
* @param {number} maxBytes number of bytes we want to encode in base64
* @returns {number} number of char
*/
export function toBase64Length(maxBytes) {
return Math.ceil(maxBytes * 4 / 3);
}
......@@ -2,13 +2,16 @@
import { registry } from "@web/core/registry";
import { useService } from "@web/core/utils/hooks";
import { isBinarySize } from "@web/core/utils/binary";
import { isBinarySize, toBase64Length } from "@web/core/utils/binary";
import { download } from "@web/core/network/download";
import { standardFieldProps } from "../standard_field_props";
import { FileUploader } from "../file_handler";
import { _lt } from "@web/core/l10n/translation";
import { Component, onWillUpdateProps, useState } from "@odoo/owl";
export const MAX_FILENAME_SIZE_BYTES = 0xFF; // filenames do not exceed 255 bytes on Linux/Windows/MacOS
export class BinaryField extends Component {
setup() {
this.notification = useService("notification");
......@@ -21,7 +24,7 @@ export class BinaryField extends Component {
}
get fileName() {
return this.state.fileName || this.props.value || "";
return (this.state.fileName || this.props.value || "").slice(0, toBase64Length(MAX_FILENAME_SIZE_BYTES));
}
update({ data, name }) {
......
......@@ -13,6 +13,8 @@ import {
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
import { browser } from "@web/core/browser/browser";
import { RPCError } from "@web/core/network/rpc_service";
import { MAX_FILENAME_SIZE_BYTES } from "@web/views/fields/binary/binary_field";
import { toBase64Length } from "@web/core/utils/binary";
const BINARY_FILE =
"R0lGODlhDAAMAKIFAF5LAP/zxAAAANyuAP/gaP///wAAAAAAACH5BAEAAAUALAAAAAAMAAwAAAMlWLPcGjDKFYi9lxKBOaGcF35DhWHamZUW0K4mAbiwWtuf0uxFAgA7";
......@@ -432,6 +434,28 @@ QUnit.module("Fields", (hooks) => {
assert.containsNone(target, "button.fa-download");
});
QUnit.test("Binary filename doesn't exceed 255 bytes", async function (assert) {
const LARGE_BINARY_FILE = BINARY_FILE.repeat(5);
assert.ok((LARGE_BINARY_FILE.length / 4 * 3) > MAX_FILENAME_SIZE_BYTES,
"The initial binary file should be larger than max bytes that can represent the filename");
serverData.models.partner.fields.document.default = LARGE_BINARY_FILE;
await makeView({
serverData,
type: "form",
resModel: "partner",
arch: `
<form>
<field name="document"/>
</form>
`,
});
assert.strictEqual(
target.querySelector(".o_field_binary input[type=text]").value.length,
toBase64Length(MAX_FILENAME_SIZE_BYTES),
"The filename shouldn't exceed the maximum size in bytes in base64"
);
});
QUnit.test("BinaryField filename is updated when using the pager", async function (assert) {
serverData.models.partner.records.push(
{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment