From ac3c50adefa479bd24b5d8296b3e44c213e5615b 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 | 3 +- api/lang/egw_en.lang | 3 +- api/src/Etemplate/Widget/Vfs.php | 12 +++- 7 files changed, 95 insertions(+), 88 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 2c4cd2cb71..55058c0951 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 @@ -1317,12 +1318,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 diff --git a/api/lang/egw_en.lang b/api/lang/egw_en.lang index 72abca7288..1145bf059a 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; }