Index: openacs-4/packages/xowiki/tcl/form-field-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/form-field-procs.tcl,v diff -u -r1.17 -r1.18 --- openacs-4/packages/xowiki/tcl/form-field-procs.tcl 15 Jul 2007 16:14:08 -0000 1.17 +++ openacs-4/packages/xowiki/tcl/form-field-procs.tcl 15 Jul 2007 23:45:33 -0000 1.18 @@ -54,18 +54,26 @@ FormField instproc validate {obj} { my instvar name required value + if {$required && $value eq ""} { my instvar label return [_ acs-templating.Element_is_required] } # todo: value type checker (through subtypes, check only if necessary) if {[my validator] ne ""} { - set r [$obj [my validator] $value] - #my msg "validator [my validator] /[$obj procsearch [my validator]]/ returned $r" + set errorMsg "" + # + # The validator might set the variable errorMsg in this scope. + # + #my msg "call [my validator] '$value'" + set r [$obj validate=[my validator] $value] if {$r != 1} { - set cl [namespace tail [lindex [$obj procsearch [my validator]] 0]] - # my msg xowiki.$cl-[my validator] - return [_ xowiki.$cl-[my validator]] + # + # We have an error message. Get the class name from procsearch and construct + # a message key based on the class and the name of the validator. + # + set cl [namespace tail [lindex [$obj procsearch validate=[my validator]] 0]] + return [_ xowiki.$cl-validate_[my validator] [list value $value errorMsg $errorMsg]] } } return "" @@ -87,32 +95,47 @@ help_text=* {my help_text [lindex [split $s =] 1]} *=* { set l [split $s =] - set value [lindex $l 1] + foreach {attribute value} $l break + set definition_class [lindex [my procsearch $attribute] 0] + if {[string match "::xotcl::*" $definition_class] || $definition_class eq ""} { + error [_ xowiki.error-form_constraint-unknown_attribute [list name [my name] entry $attribute]] + } if {[catch { # - # we want to allow e.g. options=[xowiki::locales] + # We want to allow a programmer to use e.g. options=[xowiki::locales] # - # TODO: Make sure, that validaton of form fields does not allow - # square brackets. + # Note: do not allow users to use [] via forms, since they might + # execute arbitrary commands. The validator for the form fields + # makes sure, that the input specs are free from square brackets. + # if {[string match {\[*\]} $value]} { set value [subst $value] } my [lindex $l 0] $value } errMsg]} { - my msg "Error during setting attribute [lindex $l 0] to value [lindex $l 1]: $errMsg" + error "Error during setting attribute '[lindex $l 0]' to value '[lindex $l 1]': $errMsg" } } default { if {[my isclass [self class]::$s]} { my class [self class]::$s } else { - my msg "Ignoring unknown spec for entry [my name]: '$s'" + #my msg "Ignoring unknown spec for entry [my name]: '$s'" + error [_ xowiki.error-form_constraint-unknown_spec_entry [list name [my name] entry $s x "Unknown spec entry for entry '$s'"]] } } } } ::xotcl::Class::Parameter searchDefaults [self]; # TODO: will be different in xotcl 1.6.* - #my msg "[my name]: '$spec' calling initialize class=[my info class]\n" + # + # It is possible, that a default value of a form field is changed through a spec. + # Since only the configuration might set values, checking value for "" seems safe here. + # + if {[my value] eq "" && [my exists default] && [my default] ne ""} { + # my msg "reset value to [my default]" + my value [my default] + } + if {[lang::util::translator_mode_p]} { my mixin "::xo::TRN-Mode" } @@ -257,7 +280,6 @@ if {$value eq $v} {return [my localize $label]} } } - # todo: if we can do locale substituion per langauge of the item return [string map [list & "&" < "<" > ">" \" """ ' "'"] $v] } @@ -618,6 +640,10 @@ {format "DD MONTH YYYY"} {display_format "%Y-%m-%d %T"} } + # The default of a date might be all relative dates + # supported by clock scan. These include "now", "tomorrow", + # "yesterday", "next week", .... use _ for blanks + FormField::date instproc initialize {} { my set widget_type date my set format [string map [list _ " "] [my format]] @@ -654,12 +680,11 @@ FormField::date instproc set_compound_value {} { set value [my value] - # my msg "date: value set to '$value'" + #my msg "date: value set to '$value'" if {$value ne ""} { - set ticks [clock scan $value] + set ticks [clock scan [string map [list _ " "] $value]] } else { - # TODO: just for now, should be empty as well, when we have no value - set ticks [clock seconds] + set ticks "" } # set the value parts for each components foreach {class code trim_zeros} [my components] { Index: openacs-4/packages/xowiki/tcl/xowiki-form-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/xowiki-form-procs.tcl,v diff -u -r1.75 -r1.76 --- openacs-4/packages/xowiki/tcl/xowiki-form-procs.tcl 13 Jul 2007 14:14:06 -0000 1.75 +++ openacs-4/packages/xowiki/tcl/xowiki-form-procs.tcl 15 Jul 2007 23:45:33 -0000 1.76 @@ -50,6 +50,7 @@ set show_page_order [[$data package_id] show_page_order] if {!$show_page_order} { my f.page_order "= hidden" } if {$autoname} { my f.name "= hidden"} + set form_fields [list] foreach __field $field_list { @@ -78,6 +79,7 @@ set __spec ${__field}:[$f asWidgetSpec] set __wspec [lindex $__spec 0] + lappend form_fields $f } if {[string first "richtext" $__wspec] > -1} { @@ -88,7 +90,13 @@ #my log "--F field <$__field> = $__spec" append __fields [list $__spec] \n } + + # setting form fields for later use in validator + # $data show_fields $form_fields + my set form_fields $form_fields + my set fields $__fields + } proc ::xowiki::locales {} { @@ -190,6 +198,25 @@ return 1 } + + proc ::xowiki::validate_form_constraints {} { + upvar form_constraints form_constraints + my instvar data + set f [$data lookup_form_field -name form_constraints [my set form_fields]] + $f value $form_constraints + set validation_error [$f validate $data] + if {$validation_error ne ""} { + util_user_message -message "Error in form constraints: $validation_error" + set success 0 + } else { + set success 1 + } + return $success + } + + + + WikiForm instproc data_from_form {{-new 0}} { my instvar data if {[$data exists_form_parameter text.format]} { @@ -588,8 +615,7 @@ set dont_edit [concat [[$data info class] edit_atts] [list title] \ [::Generic::CrClass set common_query_atts]] - - set category_spec [$data get_short_spec @categories] + set category_spec [$data get_short_spec _categories] foreach f [split $category_spec ,] { if {$f eq "off"} {my set with_categories false} } @@ -672,6 +698,7 @@ already in this folder}} {text {\[::xowiki::validate_form_text\]} {From must contain a valid template}} {form {\[::xowiki::validate_form_form\]} {From must contain an HTML form}} + {form_constraints {\[::xowiki::validate_form_constraints\]} {Invalid form constraints}} }} } Index: openacs-4/packages/xowiki/tcl/xowiki-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/xowiki-procs.tcl,v diff -u -r1.140 -r1.141 --- openacs-4/packages/xowiki/tcl/xowiki-procs.tcl 14 Jul 2007 18:14:26 -0000 1.140 +++ openacs-4/packages/xowiki/tcl/xowiki-procs.tcl 15 Jul 2007 23:45:33 -0000 1.141 @@ -56,7 +56,7 @@ ::xowiki::Page::slot::name set required true ::xowiki::Page::slot::name set help_text #xowiki.Page-name-help_text# ::xowiki::Page::slot::name set datatype text - ::xowiki::Page::slot::name set validator validate_name + ::xowiki::Page::slot::name set validator name ::xowiki::Page::slot::title set pretty_name #xowiki.Page-title# ::xowiki::Page::slot::title set required true @@ -135,7 +135,8 @@ ::Generic::Attribute new -attribute_name form \ -datatype text -sqltype long_text -default "" ::Generic::Attribute new -attribute_name form_constraints \ - -datatype text -sqltype long_text -default "" + -datatype text -sqltype long_text -default "" \ + -validator form_constraints } \ -form ::xowiki::FormForm @@ -795,7 +796,7 @@ return $field_name:$spec } - Page instproc validate_name {name} { + Page instproc validate=name {name} { upvar nls_language nls_language my set data [self] ;# for the time being; change clobbering when validate_name becomes a method set success [::xowiki::validate_name] @@ -866,6 +867,37 @@ } # + # Some utility functions, called on different kind of pages + # + + Page instproc lookup_form_field { + -name + form_fields + } { + set found 0 + foreach f $form_fields { + if {[$f name] eq $name} {set found 1; break} + } + if {!$found && [regexp {^([^.]+)[.](.*)$} $name _ container component]} { + # components of a field + set f [my lookup_form_field -name $container $form_fields]::$component + set found 1 + } + if {!$found} { + error "No form field with name $name found" + } + return $f + } + + Page instproc show_fields {form_fields} { + # this method is for debugging only + set msg "" + foreach f $form_fields { append msg "[$f name] [$f info class], " } + my msg $msg + } + + + # # Methods of ::xowiki::PlainPage # @@ -1147,39 +1179,39 @@ return [my include_portlet [list form-menu -form_item_id [my item_id]]] } - Page instproc new_name {name} { - if {$name ne ""} { - my instvar package_id - set name [my complete_name $name] - set name [::$package_id normalize_name $name] - set suffix ""; set i 0 - set folder_id [my parent_id] - while {[CrItem lookup -name $name$suffix -parent_id $folder_id] != 0} { - set suffix -[incr i] - } - set name $name$suffix - } - return $name - } +# Page instproc new_name {name} { +# if {$name ne ""} { +# my instvar package_id +# set name [my complete_name $name] +# set name [::$package_id normalize_name $name] +# set suffix ""; set i 0 +# set folder_id [my parent_id] +# while {[CrItem lookup -name $name$suffix -parent_id $folder_id] != 0} { +# set suffix -[incr i] +# } +# set name $name$suffix +# } +# return $name +# } - Page instproc create-new {} { - my instvar package_id - set name [my new_name [::xo::cc form_parameter name ""]] - set class [::xo::cc form_parameter class ::xowiki::Page] - if {[::xotcl::Object isclass $class] && [$class info heritage ::xowiki::Page] ne ""} { - set class [::xo::cc form_parameter class ::xowiki::Page] - set f [$class new -destroy_on_cleanup \ - -name $name \ - -package_id $package_id \ - -parent_id [my parent_id] \ - -publish_status "production" \ - -title [my title] \ - -text [list [::xo::cc form_parameter content ""] text/html]] - $f save_new - $package_id returnredirect \ - [my query_parameter "return_url" [$package_id pretty_link $name]?m=edit] - } - } +# Page instproc create-new {} { +# my instvar package_id +# set name [my new_name [::xo::cc form_parameter name ""]] +# set class [::xo::cc form_parameter class ::xowiki::Page] +# if {[::xotcl::Object isclass $class] && [$class info heritage ::xowiki::Page] ne ""} { +# set class [::xo::cc form_parameter class ::xowiki::Page] +# set f [$class new -destroy_on_cleanup \ +# -name $name \ +# -package_id $package_id \ +# -parent_id [my parent_id] \ +# -publish_status "production" \ +# -title [my title] \ +# -text [list [::xo::cc form_parameter content ""] text/html]] +# $f save_new +# $package_id returnredirect \ +# [my query_parameter "return_url" [$package_id pretty_link $name]?m=edit] +# } +# } Form instproc create-new {} { my instvar package_id @@ -1220,6 +1252,37 @@ my view [my include_portlet [list form-instances -form_item_id [my item_id]]] } + + Form instproc validate=form_constraints {form_constraints} { + # + # + # + if {[regexp {[\[\]]} $form_constraints]} { + my uplevel [list set errorMsg [_ xowiki.error-form_constraint-invalid_characters]] + return 0 + } + # + # Create from fields from all specs and report, if there are any errors + # + foreach name_and_spec $form_constraints { + foreach {spec_name short_spec} [split $name_and_spec :] break + #my msg "checking spec '$short_spec' for form field '$spec_name'" + if {[catch { + set f [my create_form_field \ + -name $spec_name \ + -slot [my find_slot $spec_name] \ + -spec $short_spec] + $f destroy + } errorMsg]} { + my uplevel [list set errorMsg $errorMsg] + #my msg "ERROR: invalid spec '$short_spec' for form field '$spec_name' -- $errorMsg" + return 0 + } + } + return 1 + } + + # # Methods of ::xowiki::FormInstance # Index: openacs-4/packages/xowiki/tcl/xowiki-www-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/xowiki-www-procs.tcl,v diff -u -r1.75 -r1.76 --- openacs-4/packages/xowiki/tcl/xowiki-www-procs.tcl 15 Jul 2007 16:14:08 -0000 1.75 +++ openacs-4/packages/xowiki/tcl/xowiki-www-procs.tcl 15 Jul 2007 23:45:33 -0000 1.76 @@ -389,24 +389,6 @@ return $f } - PageInstance instproc lookup_form_field { - -name - form_fields - } { - set found 0 - foreach f $form_fields { - if {[$f name] eq $name} {set found 1; break} - } - if {!$found && [regexp {^([^.]+)[.](.*)$} $name _ container component]} { - # components of a field - set f [my lookup_form_field -name $container $form_fields]::$component - set found 1 - } - if {!$found} { - error "No form field with name $name found" - } - return $f - } } namespace eval ::xowiki { @@ -616,13 +598,6 @@ return $form_fields } - FormInstance instproc show_fields {form_fields} { - # this method is for debugging only - set msg "" - foreach f $form_fields { append msg "[$f name] [$f info class], " } - my msg $msg - } - FormInstance instproc edit { {-validation_errors ""} } {