7878 type =" email"
7979 @update:model-value =" updateEmailValue" />
8080
81+ <NcTextField
82+ v-else-if =" propName === 'url'"
83+ v-model:model-value =" localValue"
84+ :inputmode =" inputmode"
85+ :aria-label =" propName"
86+ :class =" { 'property__value--with-ext': haveExtHandler }"
87+ :error =" !isUrlValid"
88+ :helper-text =" !urlHelpText || isReadonly ? '' : urlHelpText"
89+ type =" url"
90+ :placeholder =" placeholder"
91+ @update:model-value =" updateUrlValue" />
92+
8193 <!-- OR default to input -->
8294 <p v-else-if =" isReadOnly" >
8395 {{ localValue }}
@@ -179,6 +191,8 @@ export default {
179191 return {
180192 emailHelpText: null ,
181193 isEmailValid: true ,
194+ urlHelpText: null ,
195+ isUrlValid: true ,
182196 }
183197 },
184198
@@ -199,7 +213,10 @@ export default {
199213 },
200214
201215 URLScheme () {
202- if (this .propName === ' tel' ) {
216+ // block javascript URIs
217+ if (this .localValue ? .trim ().toLowerCase ()? .startsWith (' javascript:' )) {
218+ return false
219+ } else if (this .propName === ' tel' ) {
203220 return ' tel:'
204221 } else if (this .propName === ' email' ) {
205222 return ' mailto:'
@@ -258,6 +275,19 @@ export default {
258275 this .emailHelpText = this .$refs .email .$refs .inputField .$refs .input .validationMessage || null
259276 },
260277
278+ updateUrlValue () {
279+ // Block javascript: URLs as a security measure, accept everything else
280+ this .isUrlValid = ! / ^ \s * javascript\s * :/ i .test (this .localValue )
281+ if (this .isUrlValid ) {
282+ this .urlHelpText = null
283+ this .updateValue (this .localValue )
284+ this .sharedState .validUrl = true
285+ return
286+ }
287+ this .sharedState .validUrl = false
288+ this .urlHelpText = t (' contacts' , ' JavaScript URIs are not allowed' )
289+ },
290+
261291 /**
262292 * Watch textarea resize and update the gridSize accordingly
263293 */
0 commit comments