mirror of
https://github.com/frappe/erpnext.git
synced 2026-10-29 22:57:42 +00:00
fix(edi): clean file name and escape values in code list import
(cherry picked from commit 32bbf5a6c9)
This commit is contained in:
@@ -88,9 +88,14 @@ function show_column_selection_dialog(context) {
|
||||
for (let column in context.filterable_columns) {
|
||||
fields.push({
|
||||
fieldname: `filter_${column}`,
|
||||
label: __("by {}", [column]),
|
||||
label: __("by {}", [frappe.utils.escape_html(column)]),
|
||||
fieldtype: "Select",
|
||||
options: [null].concat(context.filterable_columns[column]),
|
||||
options: [null].concat(
|
||||
context.filterable_columns[column].map((value) => ({
|
||||
label: frappe.utils.escape_html(value),
|
||||
value: value,
|
||||
}))
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -176,7 +181,7 @@ function update_preview(dialog, context) {
|
||||
// Add headers for filterable columns
|
||||
for (let column in context.filterable_columns) {
|
||||
if (dialog.get_value(`filter_${column}`)) {
|
||||
html += `<th>${__(column)}</th>`;
|
||||
html += `<th>${frappe.utils.escape_html(column)}</th>`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,23 +190,19 @@ function update_preview(dialog, context) {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
html += "<tr>";
|
||||
if (title_column) {
|
||||
let title = context.example_values[title_column][i] || "";
|
||||
html += `<td title="${title}">${truncate(title)}</td>`;
|
||||
html += preview_cell(context.example_values[title_column][i]);
|
||||
}
|
||||
if (code_column) {
|
||||
let code = context.example_values[code_column][i] || "";
|
||||
html += `<td title="${code}">${truncate(code)}</td>`;
|
||||
html += preview_cell(context.example_values[code_column][i]);
|
||||
}
|
||||
if (description_column) {
|
||||
let description = context.example_values[description_column][i] || "";
|
||||
html += `<td title="${description}">${truncate(description)}</td>`;
|
||||
html += preview_cell(context.example_values[description_column][i]);
|
||||
}
|
||||
|
||||
// Add values for filterable columns
|
||||
for (let column in context.filterable_columns) {
|
||||
if (dialog.get_value(`filter_${column}`)) {
|
||||
let value = context.example_values[column][i] || "";
|
||||
html += `<td title="${value}">${truncate(value)}</td>`;
|
||||
html += preview_cell(context.example_values[column][i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,3 +218,8 @@ function truncate(value, maxLength = 40) {
|
||||
if (typeof value !== "string") return "";
|
||||
return value.length > maxLength ? value.substring(0, maxLength - 3) + "..." : value;
|
||||
}
|
||||
|
||||
function preview_cell(value) {
|
||||
value = value || "";
|
||||
return `<td title="${frappe.utils.escape_html(value)}">${frappe.utils.escape_html(truncate(value))}</td>`;
|
||||
}
|
||||
|
||||
@@ -4,12 +4,14 @@ from urllib.parse import urlsplit
|
||||
import frappe
|
||||
import requests
|
||||
from frappe import _
|
||||
from frappe.core.doctype.file.utils import get_safe_file_name
|
||||
from frappe.utils import escape_html
|
||||
from frappe.utils.file_manager import save_file
|
||||
from lxml import etree
|
||||
|
||||
GENERICODE_FETCH_TIMEOUT = 15
|
||||
LOCAL_FILE_PREFIXES = ("/files/", "/private/files/")
|
||||
DEFAULT_FILE_NAME = "genericode.xml"
|
||||
|
||||
|
||||
class RemoteGenericodeUrlNotAllowedError(Exception):
|
||||
@@ -55,7 +57,7 @@ def import_genericode_from_url(
|
||||
):
|
||||
"""Import a Code List from a trusted backend URL."""
|
||||
content = fetch_genericode_from_url(url)
|
||||
file_name = urlsplit(url).path.rsplit("/", 1)[-1] or "genericode.xml"
|
||||
file_name = urlsplit(url).path.rsplit("/", 1)[-1] or DEFAULT_FILE_NAME
|
||||
|
||||
return import_genericode_content(
|
||||
doctype=doctype,
|
||||
@@ -134,7 +136,7 @@ def import_genericode_content(
|
||||
code_list.save()
|
||||
|
||||
file_doc = save_file(
|
||||
fname=file_name,
|
||||
fname=get_safe_file_name(file_name or "").lstrip(".") or DEFAULT_FILE_NAME,
|
||||
content=content,
|
||||
dt=doctype,
|
||||
dn=code_list.name,
|
||||
|
||||
@@ -119,6 +119,18 @@ class TestCodeListImport(FrappeTestCase):
|
||||
file_doc = frappe.get_doc("File", import_result["file"])
|
||||
self.assertEqual(code_list_import.read_file_bytes(file_doc), SAMPLE_GENERICODE)
|
||||
|
||||
def test_uploaded_file_is_saved_under_a_plain_name(self):
|
||||
cases = (("../../sub/list.xml", "_.._sub_list.xml"), ("..", "genericode.xml"))
|
||||
for index, (file_name, expected) in enumerate(cases):
|
||||
frappe.db.delete("Code List", "test-code-list-v1")
|
||||
content = SAMPLE_GENERICODE + f"<!-- {index} {frappe.generate_hash()} -->".encode()
|
||||
with self.upload_context(content=content, file_name=file_name):
|
||||
import_result = code_list_import.import_genericode()
|
||||
|
||||
file_doc = frappe.get_doc("File", import_result["file"])
|
||||
self.assertEqual(file_doc.file_name, expected)
|
||||
self.assertEqual(file_doc.file_url, f"/private/files/{expected}")
|
||||
|
||||
def test_process_genericode_import_reads_file_doc_content(self):
|
||||
self.set_upload_context(content=SAMPLE_GENERICODE, file_name="uploaded_genericode.xml")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user