From aadaa28f86be0c8c9d27fe8be991c56e105e911c Mon Sep 17 00:00:00 2001 From: ralf Date: Wed, 31 Jul 2024 11:27:23 +0200 Subject: [PATCH] new et2-vfs-name widget which does NOT allow to put (back)slashes in filenames @nathangray client-side validation somehow does NOT work --- api/etemplate.php | 2 +- api/js/etemplate/Et2Vfs/Et2VfsName.ts | 71 +++++++++++++++++++++ api/js/etemplate/et2_widget_vfs.ts | 91 +++------------------------ api/js/etemplate/etemplate2.ts | 1 + api/lang/egw_de.lang | 5 +- api/lang/egw_en.lang | 3 +- api/src/Etemplate/Widget/Vfs.php | 12 +++- 7 files changed, 96 insertions(+), 89 deletions(-) create mode 100644 api/js/etemplate/Et2Vfs/Et2VfsName.ts diff --git a/api/etemplate.php b/api/etemplate.php index 31ac42ff3b..f664214625 100644 --- a/api/etemplate.php +++ b/api/etemplate.php @@ -17,7 +17,7 @@ const ADD_ET2_PREFIX_REGEXP = '#<((/?)([vh]?box)|vfs-select)(/?|\s[^>]*)>#m'; const ADD_ET2_PREFIX_LAST_GROUP = 4; // unconditional of legacy add et2- prefix to this widgets -const ADD_ET2_PREFIX_LEGACY_REGEXP = '#<((/?)(tabbox|description|searchbox|textbox|label|avatar|lavatar|image|appicon|colorpicker|checkbox|url(-email|-phone|-fax)?|vfs-mime|vfs-uid|vfs-gid|vfs-select|link|link-[a-z]+|favorites))(/?|\s[^>]*)>#m'; +const ADD_ET2_PREFIX_LEGACY_REGEXP = '#<((/?)(tabbox|description|searchbox|textbox|label|avatar|lavatar|image|appicon|colorpicker|checkbox|url(-email|-phone|-fax)?|vfs-mime|vfs-uid|vfs-gid|vfs-select|vfs-name|link|link-[a-z]+|favorites))(/?|\s[^>]*)>#m'; const ADD_ET2_PREFIX_LEGACY_LAST_GROUP = 5; // switch evtl. set output-compression off, as we can't calculate a Content-Length header with transparent compression diff --git a/api/js/etemplate/Et2Vfs/Et2VfsName.ts b/api/js/etemplate/Et2Vfs/Et2VfsName.ts new file mode 100644 index 0000000000..fb9edd0f52 --- /dev/null +++ b/api/js/etemplate/Et2Vfs/Et2VfsName.ts @@ -0,0 +1,71 @@ +/** + * EGroupware eTemplate2 - Readonly select WebComponent + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package api + * @link https://www.egroupware.org + * @author Ralf Becker + */ + +import {Et2Textbox} from "../Et2Textbox/Et2Textbox"; +import {Et2Description} from "../Et2Description/Et2Description"; +import {egw} from "../../jsapi/egw_global"; + +export class Et2VfsName extends Et2Textbox +{ + constructor() + { + super(); + + this.validator = /^[^\/\\]+$/; + } + + set value(_value) + { + if(_value.path) + { + _value = _value.path; + } + try + { + _value = egw.decodePath(_value); + } catch (e) + { + _value = 'Error! ' + _value; + } + super.value = _value; + } + + get value() + { + return egw.encodePath(super.value || ''); + } +} +// @ts-ignore TypeScript is not recognizing that this widget is a LitElement +customElements.define("et2-vfs-name", Et2VfsName); + +export class Et2VfsNameReadonly extends Et2Description +{ + set value(_value) + { + if(_value.path) + { + _value = _value.path; + } + try + { + _value = egw.decodePath(_value); + } catch (e) + { + _value = 'Error! ' + _value; + } + super.value = _value; + } + + get value() + { + return egw.encodePath(super.value || ''); + } +} +// @ts-ignore TypeScript is not recognizing that this widget is a LitElement +customElements.define("et2-vfs-name_ro", Et2VfsNameReadonly); \ No newline at end of file diff --git a/api/js/etemplate/et2_widget_vfs.ts b/api/js/etemplate/et2_widget_vfs.ts index 4b7a3e16a1..56a7ea6937 100644 --- a/api/js/etemplate/et2_widget_vfs.ts +++ b/api/js/etemplate/et2_widget_vfs.ts @@ -21,7 +21,6 @@ import {et2_valueWidget} from "./et2_core_valueWidget"; import {et2_createWidget, et2_register_widget, WidgetConfig} from "./et2_core_widget"; import {ClassWithAttributes} from "./et2_core_inheritance"; -import {et2_textbox, et2_textbox_ro} from "./et2_widget_textbox"; import {et2_description} from "./et2_widget_description"; import {et2_file} from "./et2_widget_file"; import {et2_IDetachedDOM} from "./et2_core_interfaces"; @@ -32,6 +31,7 @@ import {EGW_KEY_ENTER} from '../egw_action/egw_action_constants'; import {Et2Dialog} from "./Et2Dialog/Et2Dialog"; import type {Et2VfsMime} from "./Vfs/Et2VfsMime"; import type {Et2VfsGid, Et2VfsUid} from "./Et2Vfs/Et2VfsUid"; +import {Et2VfsName, Et2VfsNameReadonly} from "./Et2Vfs/Et2VfsName"; /** * Class which implements the "vfs" XET-Tag @@ -240,91 +240,14 @@ export class et2_vfs extends et2_valueWidget implements et2_IDetachedDOM et2_register_widget(et2_vfs, ["vfs"]); /** -* vfs-name -* filename automatically urlencoded on return (urldecoded on display to user) -* -* @augments et2_textbox +* @deprecated use Et2VfsName */ -export class et2_vfsName extends et2_textbox -{ - /** - * Constructor - * - * @memberOf et2_vfsName - */ - constructor(_parent, _attrs? : WidgetConfig, _child? : object) - { - // Call the inherited constructor - super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_vfsName._attributes, _child || {})); - this.input.addClass("et2_vfs"); - } - set_value(_value) - { - if(_value.path) - { - _value = _value.path; - } - try - { - _value = egw.decodePath(_value); - } catch (e) - { - _value = 'Error! ' + _value; - } - super.set_value(_value); - } - - getValue() - { - return egw.encodePath(super.getValue() || ''); - } -} -et2_register_widget(et2_vfsName, ["vfs-name"]); +export type et2_vfsName = Et2VfsName; /** -* vfs-name -* filename automatically urlencoded on return (urldecoded on display to user) -* -* @augments et2_textbox_ro -*/ -export class et2_vfsName_ro extends et2_textbox_ro -{ - /** - * Constructor - * - * @memberOf et2_vfsName_ro - */ - /** - * Constructor - */ - constructor(_parent, _attrs? : WidgetConfig, _child? : object) - { - // Call the inherited constructor - super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_vfsName_ro._attributes, _child || {})); - } - - set_value(_value) - { - if(_value.path) - { - _value = _value.path; - } - try - { - _value = egw.decodePath(_value); - } catch (e) - { - _value = 'Error! ' + _value; - } - super.set_value(_value); - } - - getValue() - { - return egw.encodePath(super.getValue() || ''); - } -} -et2_register_widget(et2_vfsName_ro, ["vfs-name_ro"]); + * @deprecated use Et2VfsName_ro + */ +export type et2_vfsName_ro = Et2VfsNameReadonly; /** * vfs-mime: icon for mimetype of file, or thumbnail @@ -818,4 +741,4 @@ export class et2_vfsUpload extends et2_file } } } -et2_register_widget(et2_vfsUpload, ["vfs-upload"]); +et2_register_widget(et2_vfsUpload, ["vfs-upload"]); \ No newline at end of file diff --git a/api/js/etemplate/etemplate2.ts b/api/js/etemplate/etemplate2.ts index 4106bdac7d..359133b278 100644 --- a/api/js/etemplate/etemplate2.ts +++ b/api/js/etemplate/etemplate2.ts @@ -105,6 +105,7 @@ import "./Et2Vfs/Et2VfsSelectButton"; import "./Et2Vfs/Et2VfsSelectDialog"; import "./Et2Vfs/Et2VfsSelectRow"; import "./Et2Vfs/Et2VfsUid"; +import "./Et2Vfs/Et2VfsName"; import "./Validators/EgwValidationFeedback"; import "./Et2Textbox/Et2Password"; import './Et2Textbox/Et2Searchbox'; diff --git a/api/lang/egw_de.lang b/api/lang/egw_de.lang index 933fa53fc7..2e7ab5d1b1 100644 --- a/api/lang/egw_de.lang +++ b/api/lang/egw_de.lang @@ -36,6 +36,7 @@ '%1' is not a valid timezone! common de '%1' ist keine gültige Zeitzone! '%1' is not allowed ('%2')! common de '%1' ist NICHT erlaubt ('%2')! '%1' is not allowed%2)! common de '%1' ist NICHT erlaubt '%2'! +'%1' must not contain (back)slashes! common de '%1' darf keine Schrägstriche enthalten! (session restored in %1 seconds) common de Sitzung in %1 Sekunden wiederhergestellt. 00 (disable) admin de 00 (deaktiviert) 1 day common de 1 Tag @@ -1304,12 +1305,12 @@ show page generation time? common de Erstellungszeit der Seite anzeigen show password common de Zeige Passwort show values common de Werte anzeigen show/hide common de Anzeigen/ausblenden Seitenleiste -show_more_apps common de Mehr Applikationen anzeigen showing common de zeigt showing %1 common de %1 Einträge showing %1 - %2 of %3 common de %1 - %2 von %3 Einträgen shows / allows you to enter values into the etemplate for testing common de Zeigt den Inhalt / Werte an und erlaubt welche zum Testen des eTemplates einzugeben shows/displays etemplate for testing, does not save it before common de Zeigt eTemplate zum Testen an, speichert es NICHT davor +show_more_apps common de Mehr Applikationen anzeigen sierra leone common de SIERRA LEONE sign up common de Registrieren simple common de Einfach @@ -1581,4 +1582,4 @@ your session timed out, please log in again login de Ihre Sitzung ist abgelaufen your settings have been updated common de Ihre Einstellungen wurden aktualisiert. zambia common de ZAMBIA zimbabwe common de ZIMBABWE -zoom common de Zoomen +zoom common de Zoomen \ No newline at end of file diff --git a/api/lang/egw_en.lang b/api/lang/egw_en.lang index 863df3f992..3ebd51f272 100644 --- a/api/lang/egw_en.lang +++ b/api/lang/egw_en.lang @@ -36,6 +36,7 @@ '%1' is not a valid timezone! common en '%1' is not a valid timezone! '%1' is not allowed ('%2')! common en '%1' is NOT allowed ('%2')! '%1' is not allowed%2)! common en '%1' is NOT allowed (%2)! +'%1' must not contain (back)slashes! common en '%1' must not contain (back)slashes! (session restored in %1 seconds) common en Session restored in %1 seconds. 00 (disable) admin en 00 (disable) 1 day common en 1 day @@ -1305,12 +1306,12 @@ show page generation time? common en Show page generation time show password common en Show password show values common en Show values show/hide common en Show/hide sidebar -show_more_apps common en Show_more_apps showing common en Showing showing %1 common en showing %1 showing %1 - %2 of %3 common en showing %1 - %2 of %3 shows / allows you to enter values into the etemplate for testing common en Shows / allows to enter values into the eTemplate for testing shows/displays etemplate for testing, does not save it before common en Shows / displays eTemplate for testing, does NOT save it +show_more_apps common en Show more apps sierra leone common en SIERRA LEONE sign up common en Sign up simple common en Simple diff --git a/api/src/Etemplate/Widget/Vfs.php b/api/src/Etemplate/Widget/Vfs.php index 9bbb9502f1..e5b5b40cba 100644 --- a/api/src/Etemplate/Widget/Vfs.php +++ b/api/src/Etemplate/Widget/Vfs.php @@ -337,6 +337,8 @@ class Vfs extends File return $path; } + const VFS_NAME_REGEXP = '#^[^/\\\\]+$#'; + /** * Validate input * Merge any already uploaded files into the content array @@ -361,7 +363,7 @@ class Vfs extends File { case 'vfs-upload': if(!is_array($value)) $value = array(); - /* Check & skip files that made it asyncronously + /* Check & skip files that made it asynchronously list($app,$id,$relpath) = explode(':',$this->id,3); //... foreach($value as $tmp => $file) @@ -370,6 +372,14 @@ class Vfs extends File }*/ parent::validate($cname, $expand, $content, $validated); break; + case 'vfs-name': + case 'et2-vfs-name': + if (!preg_match(self::VFS_NAME_REGEXP, $value)) + { + self::set_validation_error($form_name, lang("'%1' must not contain (back)slashes!", $value)); + return; + } + break; } if (!empty($this->id)) $valid = $value; }