Index: openacs-4/packages/acs-tcl/tcl/00-database-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/00-database-procs.tcl,v diff -u -N -r1.92 -r1.93 --- openacs-4/packages/acs-tcl/tcl/00-database-procs.tcl 22 Dec 2017 13:26:15 -0000 1.92 +++ openacs-4/packages/acs-tcl/tcl/00-database-procs.tcl 19 Jan 2018 20:56:00 -0000 1.93 @@ -263,25 +263,8 @@ return [expr { $db_type eq "" || [db_type] eq $db_type }] } -ad_proc -deprecated db_package_supports_rdbms_p { db_type_list } { - @return 1 if db_type_list contains the current RDMBS type. A package intended to run with a given RDBMS must note this in it's package info file regardless of whether or not it actually uses the database. - @see apm_package_supports_rdbms_p -} { - if { [lsearch $db_type_list [db_type]] != -1 } { - return 1 - } - # DRB: Legacy package check - we allow installation of old aD Oracle 4.2 packages, - # though we don't guarantee that they work. - - if { [db_type] eq "oracle" && [lsearch $db_type_list "oracle-8.1.6"] != -1 } { - return 1 - } - - return 0 -} - ad_proc -private db_legacy_package_p { db_type_list } { @return 1 if the package is a legacy package. We can only tell for certain if it explicitly supports Oracle 8.1.6 rather than the OpenACS more general oracle. } { Index: openacs-4/packages/acs-tcl/tcl/apm-file-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/apm-file-procs.tcl,v diff -u -N -r1.37 -r1.38 --- openacs-4/packages/acs-tcl/tcl/apm-file-procs.tcl 7 Aug 2017 23:47:59 -0000 1.37 +++ openacs-4/packages/acs-tcl/tcl/apm-file-procs.tcl 19 Jan 2018 20:56:00 -0000 1.38 @@ -403,15 +403,7 @@ return $watchable_files } -ad_proc -public -deprecated pkg_home {package_key} { - @return A server-root relative path to the directory for a package. Usually /packages/package-key - @see acs_package_root_dir - -} { - return "/packages/$package_key" -} - ad_proc -private apm_system_paths {} { @return a list of acceptable system paths to search for executables in. Index: openacs-4/packages/acs-tcl/tcl/apm-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/apm-procs.tcl,v diff -u -N -r1.97 -r1.98 --- openacs-4/packages/acs-tcl/tcl/apm-procs.tcl 1 Oct 2017 12:16:05 -0000 1.97 +++ openacs-4/packages/acs-tcl/tcl/apm-procs.tcl 19 Jan 2018 20:56:00 -0000 1.98 @@ -129,12 +129,6 @@ } -ad_proc -public -deprecated apm_doc_body_callback { string } { - This callback uses the document api to append more text to the stream. -} { - doc_body_append $string -} - ad_proc apm_callback_and_log { { -severity Notice } callback message } { Executes the $callback callback routine with $message as an argument, Index: openacs-4/packages/acs-tcl/tcl/community-core-2-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/community-core-2-procs.tcl,v diff -u -N -r1.4 -r1.5 --- openacs-4/packages/acs-tcl/tcl/community-core-2-procs.tcl 7 Aug 2017 23:47:59 -0000 1.4 +++ openacs-4/packages/acs-tcl/tcl/community-core-2-procs.tcl 19 Jan 2018 20:56:00 -0000 1.5 @@ -9,23 +9,6 @@ } -# The User Namespace -namespace eval oacs::user { - - ad_proc -deprecated -public get { - {-user_id:required} - {-array:required} - } { - Load up user information - @see acs_user::get - } { - # Upvar the Tcl Array - upvar $array row - db_1row select_user {} -column_array row - } - -} - # Local variables: # mode: tcl # tcl-indent-level: 4 Index: openacs-4/packages/acs-tcl/tcl/community-core-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/community-core-procs.tcl,v diff -u -N -r1.64 -r1.65 --- openacs-4/packages/acs-tcl/tcl/community-core-procs.tcl 16 Aug 2017 09:18:20 -0000 1.64 +++ openacs-4/packages/acs-tcl/tcl/community-core-procs.tcl 19 Jan 2018 20:56:00 -0000 1.65 @@ -12,100 +12,6 @@ namespace eval person {} namespace eval acs_user {} -ad_proc -deprecated -private cc_lookup_screen_name_user { screen_name } { - @see acs_user::get_user_id_by_screen_name -} { - return [db_string user_select {} -default {}] -} - -ad_proc -deprecated cc_screen_name_user { screen_name } { - - @return Returns the user ID for a particular screen name, or an empty string - if none exists. - - @see acs_user::get_user_id_by_screen_name - -} { - return [util_memoize [list cc_lookup_screen_name_user $screen_name]] -} - -ad_proc -deprecated -private cc_lookup_email_user { email } { - Return the user_id of a user given the email. Returns the empty string if no such user exists. - @see party::get_by_email -} { - return [db_string user_select {} -default {}] -} - -ad_proc -public -deprecated cc_email_from_party { party_id } { - @return The email address of the indicated party. - @see party::email -} { - return [db_string email_from_party {} -default {}] -} - -ad_proc -deprecated cc_email_user { email } { - - @return Returns the user ID for a particular email address, or an empty string - if none exists. - - @see party::get_by_email -} { - return [util_memoize [list cc_lookup_email_user $email]] -} - -ad_proc -deprecated -private cc_lookup_name_group { name } { - @see group::get_id -} { - return [db_string group_select {} -default {}] -} - -ad_proc -deprecated cc_name_to_group { name } { - - Returns the group ID for a particular name, or an empty string - if none exists. - - @see group::get_id -} { - return [util_memoize [list cc_lookup_name_group $name]] -} - -ad_proc -deprecated ad_user_new { - email - first_names - last_name - password - password_question - password_answer - {url ""} - {email_verified_p "t"} - {member_state "approved"} - {user_id ""} - {username ""} - {authority_id ""} - {screen_name ""} -} { - Creates a new user in the system. The user_id can be specified as an argument to enable double click protection. - If this procedure succeeds, returns the new user_id. Otherwise, returns 0. - - @see auth::create_user - @see auth::create_local_account -} { - return [auth::create_local_account_helper \ - $email \ - $first_names \ - $last_name \ - $password \ - $password_question \ - $password_answer \ - $url \ - $email_verified_p \ - $member_state \ - $user_id \ - $username \ - $authority_id \ - $screen_name] -} - ad_proc -public person::person_p { {-party_id:required} } { Index: openacs-4/packages/acs-tcl/tcl/deprecated-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/deprecated-procs.tcl,v diff -u -N -r1.4 -r1.5 --- openacs-4/packages/acs-tcl/tcl/deprecated-procs.tcl 19 Jan 2018 20:39:16 -0000 1.4 +++ openacs-4/packages/acs-tcl/tcl/deprecated-procs.tcl 19 Jan 2018 20:56:00 -0000 1.5 @@ -1106,6 +1106,2061 @@ return "" } +#################### +# +# Legacy stuff +# +#################### + + +ad_proc -deprecated util_striphtml {html} { + Deprecated. Use ad_html_to_text instead. + + @see ad_html_to_text +} { + return [ad_html_to_text -- $html] +} + + +ad_proc -deprecated util_convert_plaintext_to_html { raw_string } { + + Almost everything this proc does can be accomplished with the ad_text_to_html. + Use that proc instead. + +

+ + Only difference is that ad_text_to_html doesn't check + to see if the plaintext might in fact be HTML already by + mistake. But we usually don't want that anyway, + because maybe the user wanted a <p> tag in his + plaintext. We'd rather let the user change our + opinion about the text, e.g. html_p = 't'. + + @see ad_text_to_html +} { + if { [regexp -nocase {

} $raw_string] || [regexp -nocase {
} $raw_string] } { + # user was already trying to do this as HTML + return $raw_string + } else { + return [ad_text_to_html -no_links -- $raw_string] + } +} + +ad_proc -deprecated util_maybe_convert_to_html {raw_string html_p} { + + This proc is deprecated. Use ad_convert_to_html + instead. + + @see ad_convert_to_html + +} { + if { $html_p == "t" } { + return $raw_string + } else { + return [ad_text_to_html -- $raw_string] + } +} + +ad_proc -deprecated -warn util_quotehtml { arg } { + This proc does exactly the same as ad_quotehtml. + Use that instead. This one will be deleted eventually. + + @see ad_quotehtml +} { + return [ns_quotehtml $arg] +} + +ad_proc -deprecated util_quote_double_quotes {arg} { + This proc does exactly the same as ad_quotehtml. + Use that instead. This one will be deleted eventually. + + @see ad_quotehtml +} { + return [ns_quotehtml $arg] +} + +ad_proc -deprecated philg_quote_double_quotes {arg} { + This proc does exactly the same as ad_quotehtml. + Use that instead. This one will be deleted eventually. + + @see ad_quotehtml +} { + return [ns_quotehtml $arg] +} + + + + +ad_proc -deprecated ad_dimensional_set_variables {option_list {options_set ""}} { + set the variables defined in option_list from the form provided + (form defaults to ad_conn form) or to default value from option_list if + not in the form data. +

+ You only really need to call this if you need the variables + (for example to pick which select statement and table to actually use) +} { + set out {} + + if {$option_list eq ""} { + return + } + + if {$options_set eq ""} { + set options_set [ns_getform] + } + + foreach option $option_list { + # find out what the current option value is. + # check if a default is set otherwise the first value is used + set option_key [lindex $option 0] + set option_val {} + # get the option from the form + if { $options_set ne "" && [ns_set find $options_set $option_key] != -1} { + uplevel [list set $option_key [ns_set get $options_set $option_key]] + } else { + uplevel [list set $option_key [lindex $option 2]] + } + } +} + +ad_proc -deprecated ad_table { + {-Torder_target_url {}} + {-Torderby {}} + {-Tasc_order_img {^}} + {-Tdesc_order_img {v}} + {-Tmissing_text "No data found."} + {-Tsuffix {}} + {-Tcolumns {}} + {-Taudit {}} + {-Trows_per_band 1} + {-Tband_colors {{} "#ececec"}} + {-Tband_classes {{even} {odd}}} + {-Trows_per_page 0} + {-Tmax_rows 0} + {-Ttable_extra_html {cellpadding=3 cellspacing=0 class="table-display"}} + {-Theader_row_extra {style="background-color:#f8f8f8" class="table-header"}} + {-Ttable_break_html "

"} + {-Tpre_row_code {}} + {-Trow_code {[subst $Trow_default]}} + {-Tpost_data_ns_sets {}} + {-Textra_vars {}} + {-Textra_rows {}} + {-bind {}} + {-dbn {}} + statement_name sql_qry Tdatadef +} { + + DRB: New code should use the listbuilder. + + Note: all the variables in this function are named Tblah since we could potentially + have namespace collisions +

+ build and return an html fragment given an active query and a data definition. +

+ + Datadef structure : +
 
+    { 
+        {column_id "Column_Heading" order_clause display_info}
+        ...
+    }
+    
+ + + @param dbn The database name to use. If empty_string, uses the default database. +} { + + set full_statement_name [db_qd_get_fullname $statement_name] + + # This procedure needs a full rewrite! + db_with_handle -dbn $dbn Tdb { + # Execute the query + set selection [db_exec select $Tdb $full_statement_name $sql_qry] + set Tcount 0 + set Tband_count 0 + set Tpage_count 0 + set Tband_color 0 + set Tband_class 0 + set Tn_bands [llength $Tband_colors] + set Tn_band_classes [llength $Tband_classes] + set Tform [ad_conn form] + + # export variables from calling environment + if {$Textra_vars ne ""} { + foreach Tvar $Textra_vars { + upvar $Tvar $Tvar + } + } + + # get the current ordering information + set Torderbykey {::not_sorted::} + set Treverse {} + regexp {^([^*,]+)([*])?} $Torderby match Torderbykey Treverse + if {$Treverse eq "*"} { + set Torder desc + } else { + set Torder asc + } + + # set up the target url for new sorts + if {$Torder_target_url eq ""} { + set Torder_target_url [ad_conn url] + } + set Texport "[uplevel [list export_ns_set_vars url [list orderby$Tsuffix]]]&" + if {$Texport == "&"} { + set Texport {} + } + set Tsort_url "$Torder_target_url?${Texport}orderby$Tsuffix=" + + set Thtml {} + set Theader {} + + # build the list of columns to display... + set Tcolumn_list [ad_table_column_list $Tdatadef $Tcolumns] + + # generate the header code + # + append Theader "\n" + if {$Theader_row_extra eq ""} { + append Theader "\n" + } else { + append Theader "\n" + } + foreach Ti $Tcolumn_list { + set Tcol [lindex $Tdatadef $Ti] + if { ( [ns_set find $selection [lindex $Tcol 0]] < 0 + && ([lindex $Tcol 2] eq "" || [lindex $Tcol 2] ne "sort_by_pos") + ) + || [lindex $Tcol 2] eq "no_sort" + } { + + # not either a column in the select or has sort code + # then just a plain text header so do not do sorty things + append Theader " \n" + } else { + if {[lindex $Tcol 0] eq $Torderbykey } { + if {$Torder eq "desc"} { + set Tasord $Tasc_order_img + } else { + set Tasord $Tdesc_order_img + } + } else { + set Tasord {} + } + set href $Tsort_url[ns_urlencode [ad_new_sort_by [lindex $Tcol 0] $Torderby]] + append Theader \ + [subst { \n" + } + } + append Theader "\n" + + # + # This has gotten kind of ugly. Here we are looping over the + # rows returned and then potentially a list of ns_sets which can + # be passed in (grrr. Richard Li needs for general protections stuff + # for "fake" public record which does not exist in DB). + # + + set Tpost_data 0 + + while { 1 } { + if {!$Tpost_data && [ns_db getrow $Tdb $selection]} { + # in all its evil majesty + set_variables_after_query + } else { + # move on to fake rows... + incr Tpost_data + } + + if { $Tpost_data && $Tpost_data <= [llength $Tpost_data_ns_sets] } { + # bind the Tpost_data_ns_sets row of the passed in data + set_variables_after_query_not_selection [lindex $Tpost_data_ns_sets $Tpost_data-1] + } elseif { $Tpost_data } { + # past the end of the fake data drop out. + break + } + + if { $Tmax_rows && $Tcount >= $Tmax_rows } { + if { ! $Tpost_data } { + # we hit max count and had rows left to read... + ns_db flush $Tdb + } + break + } + + # deal with putting in the header if need + if { $Tcount == 0 } { + append Thtml "$Theader" + } elseif { $Tpage_count == 0 } { + append Thtml "
[lindex $Tcol 1]}] \ + "\n[lindex $Tcol 1] $Tasord
\n$Ttable_break_html\n$Theader" + } + + # first check if we are in audit mode and if the audit columns have changed + set Tdisplay_changes_only 0 + if {$Taudit ne "" && $Tcount > 0} { + # check if the audit key columns changed + foreach Taudit_key $Taudit { + if {[set $Taudit_key] eq [set P$Taudit_key] } { + set Tdisplay_changes_only 1 + } + } + } + + # this is for breaking on sorted field etc. + append Thtml [subst $Tpre_row_code] + + if { ! $Tdisplay_changes_only } { + # in audit mode a record spans multiple rows. + incr Tcount + incr Tband_count + } + incr Tpage_count + + if { $Trows_per_page && $Tpage_count >= $Trows_per_page } { + set Tband_color 0 + set Tband_class 0 + set Tband_count 0 + set Tpage_count 0 + + } + + set Trow_default {} + # generate the row band color + if { $Tband_count >= $Trows_per_band } { + set Tband_count 0 + set Tband_color [expr {($Tband_color + 1) % $Tn_bands} ] + set Tband_class [expr {($Tband_class + 1) % $Tn_band_classes} ] + } + # do this check since we would like the ability to band with + # page background as well + if {$Tn_bands && [lindex $Tband_colors $Tband_color] ne ""} { + append Trow_default " style=\"background-color:[lindex $Tband_colors $Tband_color]\"" + } + if {$Tn_band_classes && [lindex $Tband_classes $Tband_class] ne ""} { + append Trow_default " class=\"[lindex $Tband_classes $Tband_class]\"" + } + + + set Trow_default "" + + append Thtml [subst $Trow_code] + + foreach Ti $Tcolumn_list { + set Tcol [lindex $Tdatadef $Ti] + # If we got some special formatting code we handle it + # single characters r l c are special for alignment + set Tformat [lindex $Tcol 3] + set Tcolumn [lindex $Tcol 0] + switch -- $Tformat { + "" {set Tdisplay_field " [set $Tcolumn]\n"} + r {set Tdisplay_field " [set $Tcolumn]\n"} + l {set Tdisplay_field " [set $Tcolumn]\n"} + c {set Tdisplay_field " [set $Tcolumn]\n"} + tf {set Tdisplay_field " [util_PrettyBoolean [set $Tcolumn]]\n"} + 01 {set Tdisplay_field " [util_PrettyTclBoolean [set $Tcolumn]]\n"} + bz {set Tdisplay_field "  [blank_zero [set $Tcolumn]]\n"} + default {set Tdisplay_field " [subst $Tformat]\n"} + } + + if { $Tdisplay_changes_only + && $Tdisplay_field eq $Tlast_display($Ti) } { + set Tdisplay_field { } + } else { + set Tlast_display($Ti) $Tdisplay_field + } + append Thtml $Tdisplay_field + } + + append Thtml "\n" + + # keep the last row around so we can do fancy things. + # so on next row we can say things like if $Pvar != $var not blank + if { $Tpost_data && $Tpost_data <= [llength $Tpost_data_ns_sets] } { + # bind the Tpost_data_ns_sets row of the passed in data + set_variables_after_query_not_selection [lindex $Tpost_data_ns_sets $Tpost_data-1] P + } else { + set_variables_after_query_not_selection $selection P + } + } + + if { $Tcount > 0} { + append Thtml "$Textra_rows +\n" + } else { + append Thtml $Tmissing_text + } + } + return $Thtml +} + +ad_proc -deprecated ad_table_column_list { + { -sortable all } + datadef columns +} { + build a list of pointers into the list of column definitions +

+ returns a list of indexes into the columns one per column it found +

+ -sortable from t/f/all +} { + set column_list {} + if {$columns eq ""} { + for {set i 0} {$i < [llength $datadef]} {incr i} { + if {$sortable eq "all" + || ($sortable == "t" && [lindex $datadef $i 2] ne "no_sort") + || ($sortable == "f" && [lindex $datadef $i 2] eq "no_sort") + } { + lappend column_list $i + } + } + } else { + set colnames {} + foreach col $datadef { + if {$sortable eq "all" + || ($sortable == "t" && [lindex $col 2] ne "no_sort") + || ($sortable == "f" && [lindex $col 2] eq "no_sort") + } { + lappend colnames [lindex $col 0] + } else { + # placeholder for invalid column + lappend colnames "X+X" + } + } + foreach col $columns { + set i [lsearch $colnames $col] + if {$i > -1} { + lappend column_list $i + } + } + } + + return $column_list +} + +ad_proc -deprecated ad_sort_primary_key {orderby} { + return the primary (first) key of an order spec + used by +} { + if {[regexp {^([^*,]+)} $orderby match]} { + return $match + } + return $orderby +} + +ad_proc -deprecated ad_table_same varname { + Called from inside ad_table. + + returns true if the variable has same value as + on the previous row. Always false for 1st row. + +} { + if { [uplevel set Tcount] + && [uplevel string compare \$$varname \$P$varname] == 0} { + return 1 + } else { + return 0 + } +} + +ad_proc -deprecated ad_table_span {str {td_html "align=\"left\""}} { + given string the function generates a row which spans the + whole table. +} { + return "$str" +} + +ad_proc -deprecated ad_table_form { + datadef + {type select} + {return_url {}} + {item_group {}} + {item {}} + {columns {}} + {allowed {}} +} { + builds a form for chosing the columns to display +

+ columns is a list of the currently selected columns. +

+ allowed is the list of all the displayable columns, if empty + all columns are allowed. +} { + # first build a map of all available columns + set sel_list [ad_table_column_list $datadef $allowed] + + # build the map of currently selected columns + set sel_columns [ad_table_column_list $datadef $columns] + + set max_columns [llength $sel_list] + set n_sel_columns [llength $sel_columns] + + set html {} + if {$item eq "CreateNewCustom" } { + set item {} + } + # now spit out the form fragment. + if {$item ne ""} { + append html "

Editing $item

" + append html "
" + append html "" + append html "" + append html "[export_vars -form {item_group item}]" + if {$return_url ne ""} { + append html "[export_vars -form {return_url}]" + } + append html "
" + } + + append html "
" + if {$return_url ne ""} { + append html "[export_vars -form {return_url}]" + } + if {$item_group eq ""} { + set item_group [ad_conn url] + } + + append html "[export_vars -form {item_group}]" + if {$item ne ""} { + set item_original $item + append html "[export_vars -form {item_original}]" + append html "" + } else { + append html "" + } + + append html "" + append html "" + if {$item ne ""} { + set item_original item + append html "[export_vars -form {item_original}]" + append html "" + } + + if {$type eq "select" } { + # select table + set options "" + foreach opt $sel_list { + append options " " + } + + for {set i 0} { $i < $max_columns} {incr i} { + if {$i < $n_sel_columns} { + set match [lindex $datadef [lindex $sel_columns $i] 0] + regsub "(\n" + } + } else { + # radio button table + append html "" + foreach opt $sel_list { + append html "" + } + append html "" + + foreach opt $sel_list { + append options "" + } + for {set i 0} { $i < $max_columns} {incr i} { + if {$i < $n_sel_columns} { + set match [lindex $datadef [lindex $sel_columns $i] 0] + regsub "( type=\"radio\" )(value=\"$match\">)" $options "\\1 checked=\"checked\" \\2" out + } else { + set out $options + } + regsub -all {@@} $out $i out + append html "$out\n" + } + } + append html "
Name:
 Editing the name will rename the view
[expr {$i + 1}]
Col \#[lindex $datadef $opt 1]
[expr {$i + 1}]
" + + return $html +} + +ad_proc -deprecated ad_table_sort_form { + datadef + {type select} + {return_url {}} + {item_group {}} + {item {}} + {sort_spec {}} + {allowed {}} +} { + builds a form for setting up custom sorts. +

+

+

+ An example from the ticket system: +

+      ad_table_sort_form $tabledef select $return_url ticket_tracker_main_sort $ticket_sort $orderby
+    
+} { + # first build a map of all available columns + set sel_list [ad_table_column_list -sortable t $datadef $allowed] + + # build the map of currently selected columns + set full_column [split $sort_spec ","] + set sel_columns [list] + set direction [list] + foreach col $full_column { + regexp {([^*,]+)([*])?} $col match coln dirn + if {$dirn eq "*"} { + set dirn desc + } else { + set dirn asc + } + lappend sel_columns $coln + lappend direction $dirn + } + + set max_columns 4 + set n_sel_columns [llength $sel_columns] + + set html {} + if {$item eq "CreateNewCustom" } { + set item {} + } + # now spit out the form fragment. + if {$item ne ""} { + append html "

Editing $item

" + append html "
" + append html "" + append html "" + append html "[export_vars -form {item_group item}]" + if {$return_url ne ""} { + append html "[export_vars -form {return_url}]" + } + append html "
" + } + + append html "
" + if {$return_url ne ""} { + append html "[export_vars -form {return_url}]" + } + if {$item_group eq ""} { + set item_group [ad_conn url] + } + + append html "[export_vars -form {item_group}]" + if {$item ne ""} { + set item_original $item + append html "[export_vars -form {item_original}]" + append html "" + } else { + append html "" + } + + append html "" + append html "" + if {$item ne ""} { + set item_original item + append html "[export_vars -form {item_original}]" + append html "" + } + + set options "" + foreach opt $sel_list { + append options " " + } + + for {set i 0} { $i < $max_columns} {incr i} { + if {$i < $n_sel_columns} { + set match [lindex $sel_columns $i] + regsub "(\n" + } + append html "
Name:
 Editing the name will rename the sort
[expr {$i + 1}]" + switch [lindex $direction $i] { + asc { + append html "" + } + default { + append html "" + + } + } + append html "\n
" + + return $html +} + +ad_proc -deprecated ad_order_by_from_sort_spec {sort_by tabledef} { + Takes a sort_by spec, and translates it into into an "order by" clause + with each sort_by key dictated by the sort info in tabledef +} { + set order_by_clause {} + + foreach sort_key_spec [split $sort_by ","] { + if { [regexp {^([A-Za-z_0-9]+)(\*?)$} $sort_key_spec match sort_key reverse] } { + # if there's a "*" after the key, we want to reverse the usual order + foreach order_spec $tabledef { + if { $sort_key == [lindex $order_spec 0] } { + if { $reverse eq "*" } { + set order "desc" + } else { + set order "asc" + } + + if { $order_by_clause eq "" } { + append order_by_clause "\norder by " + } else { + append order_by_clause ", " + } + + # tack on the order by clause + if {[lindex $order_spec 2] ne "" && [lindex $order_spec 2] ne "sort_by_pos"} { + append order_by_clause "[subst [lindex $order_spec 2]]" + } else { + append order_by_clause "$sort_key $order" + } + break + } + } + } + } + return $order_by_clause +} + +ad_proc -deprecated ad_new_sort_by {key keys} { + Makes a new sort_by string, sorting by "key". + + If the key is followed by "*", that indicates the ordering should + be reversed from the default ordering for that key. + + Old sort keys are retained, so the sort appears to be a little more stable. + That is, suppose two things are sorted into an order, and their values for a + different column are the same. If that different column is used as the primary + sort key to reorder, the things which have the same value for the newly-sorted + column will remain in the same relative order. +} { + if { $keys eq "" } { + return $key + + } elseif { [regexp "^${key}(\\*?)," "$keys," match reverse] } { + # if this was already the first key, then reverse order + if { $reverse eq "*" } { + regsub "\\*," "$keys," "," keys + } else { + regsub "," "$keys," "*," keys + } + regsub ",$" $keys "" keys + return $keys + } else { + regsub ",$key\\*?," "$keys," "," keys + regsub ",$" $keys "" keys + return "$key,$keys" + } +} + +ad_proc -deprecated ad_same_page_link {variable value text {form ""}} { + Makes a link to this page, with a new value for "variable". +} { + if { $form eq "" } { + set form [ns_getform] + } + set url_vars [export_ns_set_vars url $variable $form] + set href "[ad_conn url]?$variable=[ns_urlencode $value]$url_vars" + return [subst {[ns_quotehtml $text]}] +} + +ad_proc -deprecated ad_reverse order { + returns the opposite sort order from the + one it is given. Mostly for columns whose natural + sort order is not the default. +} { + switch [string tolower $order] { + desc {return asc} + asc {return desc} + } + return $order +} + +ad_proc -deprecated ad_custom_load {user_id item_group item item_type} { + load a persisted user customization as saved by + for example table-custom.tcl. +} { + + if { + ![db_0or1row load_user_customization { + select value_type, value + from user_custom + where user_id = :user_id + and item_type = :item_type + and item_group = :item_group + and item = :item + }] + } { + set value {} + } + return $value +} + +ad_proc -deprecated ad_custom_list {user_id item_group item_set item_type target_url custom_url {new_string "new view"}} { + Generates the html fragment for choosing, editing and creating + user customized data +} { + + set items [db_list custom_list { + select item from user_custom + where user_id = :user_id + and item_type = :item_type + and item_group = :item_group + }] + + set break {} + foreach item $items { + if {$item_set eq $item } { + append html "$break$item (edit)" + } else { + append html "$break$item" + } + set break " | " + } + append html "$break ($new_string)\n" + + return $html +} + + +ad_proc -deprecated ad_custom_page_defaults {defaults} { + set the page defaults. If the form is + empty do a returnredirect with the defaults set +} { + set form [ns_getform] + if {$form eq "" + && $defaults ne ""} { + # we did not get a form so set all the variables + # and redirect to set them + set redirect "[ad_conn url]?" + set pre {} + foreach kvp $defaults { + append redirect "$pre[lindex $kvp 0]=[ns_urlencode [lindex $kvp 1]]" + set pre {&} + } + ad_returnredirect $redirect + ad_script_abort + } + + # we have a form so stuff in the ones we dont find. + # should think about how to support lists and ns_set persist too. + foreach kvp $defaults { + if {[ns_set find $form [lindex $kvp 0]] < 0} { + ns_set put $form [lindex $kvp 0] [lindex $kvp 1] + } + } +} + +ad_proc -deprecated ad_custom_form {return_url item_group item} { + sets up the head of a form to feed to /tools/form-custom.tcl +} { + append html "
\n" + if {$return_url ne ""} { + append html "[export_vars -form {return_url}]\n" + } + if {$item_group eq ""} { + set item_group [ad_conn url] + } + set item_original $item + append html "[export_vars -form {item_group item item_original}]\n" + append html "" +} + +ad_proc -deprecated ad_dimensional_settings {define current} { + given a dimensional slider definition this routine returns a form to set the + defaults for the given slider. + + NB...this does not close either the table or the form... +} { + foreach opt $define { + append html "[lindex $opt 1]" + append html "\n" + } + return $html +} + +ad_proc -deprecated ad_table_orderby_sql {datadef orderby order} { + create the order by clause consistent with the orderby and order variables + and the datadef which built the table +} { + set orderclause "order by $orderby $order" + foreach col $datadef { + if {$orderby eq [lindex $col 0] } { + if {[lindex $col 2] ne ""} { + set orderclause [subst [lindex $col 2]] + } + } + } + return $orderclause +} + + + +# +# was in set-operation-procs.tcl +# + +ad_proc -deprecated set_member? { s v } { +

Tests whether or not $v is a member of set $s.

+} { + if {$v ni $s} { + return 0 + } else { + return 1 + } +} + + + +ad_proc -deprecated set_append! { s-name v } { +

Adds the element v to the set named s-name in the calling + environment, if it isn't already there.

+} { + upvar $s-name s + + if { ![set_member? $s $v] } { + lappend s $v + } +} + + + +ad_proc -deprecated set_union { u v } { +

Returns the union of sets $u and $v.

+} { + set result $u + + foreach ve $v { + if { ![set_member? $result $ve] } { + lappend result $ve + } + } + + return $result +} + +ad_proc -deprecated set_union! { u-name v } { +

Computes the union of the set stored in the variable + named $u-name in the calling environment and the set v, + sets the variable named $u-name in the calling environment + to that union, and also returns that union.

+} { + upvar $u-name u + + foreach ve $v { + if { ![set_member? $u $ve] } { + lappend u $ve + } + } + + return $u +} + + + + +ad_proc -deprecated set_intersection { u v } { +

Returns the intersection of sets $u and $v.

+} { + set result [list] + + foreach ue $u { + if { [set_member? $v $ue] } { + lappend result $ue + } + } + + return $result +} + +ad_proc -deprecated set_intersection! { u-name v } { +

Computes the intersection of the set stored in the variable + named $u-name in the calling environment and the set v, + sets the variable named $u-name in the calling environment + to that intersection, and also returns that intersection.

+} { + upvar $u-name u + set result [list] + + foreach ue $u { + if { [set_member? $v $ue] } { + lappend result $ue + } + } + + set u $result + return $result +} + +ad_proc -deprecated set_difference { u v } { +

Returns the difference of sets $u and $v. (i.e. The set of all + members of u that aren't also members of $v.)

+} { + set result [list] + + foreach ue $u { + if { ![set_member? $v $ue] } { + lappend result $ue + } + } + + return $result +} + +ad_proc -deprecated set_difference! { u-name v } { +

Computes the difference of the set stored in the variable + named $u-name in the calling environment and the set v, + sets the variable named $u-name in the calling environment + to that difference, and also returns that difference.

+} { + upvar $u-name u + set result [list] + + foreach ue $u { + if { ![set_member? $v $ue] } { + lappend result $ue + } + } + + set u $result + return $result +} + +# +# from tcl/navigation-procs.tcl +# +ad_proc -deprecated -public ad_context_bar_ws args { + Returns a Yahoo-style hierarchical navbar. Use ad_context_bar instead. + + @param list of url desc ([list [list url desc] [list url desc] ... "terminal"]) + @return an html fragment generated by ad_context_bar_html + + @see ad_context_bar +} { + return [ad_context_bar $args] +} + + +# a context bar, rooted at the workspace or index, depending on whether +# user is logged in + +ad_proc -deprecated -public ad_context_bar_ws_or_index args { + Returns a Yahoo-style hierarchical navbar. Use ad_context_bar instead. + + @param args list of url desc ([list [list url desc] [list url desc] ... "terminal"]) + @return an html fragment generated by ad_context_bar + + @see ad_context_bar +} { + return [ad_context_bar $args] +} + +ad_proc -public -deprecated ad_admin_context_bar args { + Returns a Yahoo-style hierarchical navbar. Use ad_context_bar instead. + + @param args list of url desc ([list [list url desc] [list url desc] ... "terminal"]) + @return an html fragment generated by ad_context_bar + + @see ad_context_bar +} { + return [ad_context_bar $args] +} + + +# +# From tcl/http-client-procs.tcl +# + +######################### +## Deprecated HTTP api ## +######################### + +ad_proc -deprecated -public util_link_responding_p { + url + {list_of_bad_codes "404"} +} { + Returns 1 if the URL is responding (generally we think that anything other than 404 (not found) is okay). + + @see util::link_responding_p +} { + util::link_responding_p -url $url -list_of_bad_codes $list_of_bad_codes +} + +ad_proc -public -deprecated util_get_http_status { + url + {use_get_p 1} + {timeout 30} +} { + Returns the HTTP status code, e.g., 200 for a normal response + or 500 for an error, of a URL. By default this uses the GET method + instead of HEAD since not all servers will respond properly to a + HEAD request even when the URL is perfectly valid. Note that + this means AOLserver may be sucking down a lot of bits that it + doesn't need. + + @see util::get_http_status +} { + return [util::get_http_status -url $url -use_get_p $use_get_p -timeout $timeout] +} + +ad_proc -deprecated -public ad_httpget { + -url + {-headers ""} + {-timeout 30} + {-depth 0} +} { + Just like ns_httpget, but first headers is an ns_set of + headers to send during the fetch. + + ad_httpget also makes use of Conditional GETs (if called with a + Last-Modified header). + + Returns the data in array get form with array elements page status modified. + + @see util::http::get +} { + ns_log debug "Getting {$url} {$headers} {$timeout} {$depth}" + + if {[incr depth] > 10} { + return -code error "ad_httpget: Recursive redirection: $url" + } + + lassign [ns_httpopen GET $url $headers $timeout] rfd wfd headers + close $wfd + + set response [ns_set name $headers] + set status [lindex $response 1] + set last_modified [ns_set iget $headers last-modified] + + if {$status == 302 || $status == 301} { + set location [ns_set iget $headers location] + if {$location ne ""} { + ns_set free $headers + close $rfd + return [ad_httpget -url $location -timeout $timeout -depth $depth] + } + } elseif { $status == 304 } { + # The requested variant has not been modified since the time specified + # A conditional get didn't return anything. return an empty page and + set page {} + + ns_set free $headers + close $rfd + } else { + set length [ns_set iget $headers content-length] + if { $length eq "" } {set length -1} + + set type [ns_set iget $headers content-type] + set_encoding $type $rfd + + set err [catch { + while 1 { + set buf [_ns_http_read $timeout $rfd $length] + append page $buf + if { "" eq $buf } break + if {$length > 0} { + incr length -[string length $buf] + if {$length <= 0} break + } + } + } errMsg] + ns_set free $headers + close $rfd + + if {$err} { + return -code error -errorinfo $::errorInfo $errMsg + } + } + + # order matters here since we depend on page content + # being element 1 in this list in util_httpget + return [list page $page \ + status $status \ + modified $last_modified] +} + +ad_proc -deprecated -public util_httpget { + url {headers ""} {timeout 30} {depth 0} +} { + util_httpget simply calls util::http::get which also returns + status and last_modfied + + @see util::http::get +} { + return [dict get [util::http::get -url $url -headers $headers -timeout $timeout -depth $depth] page] +} + +# httppost; give it a URL and a string with formvars, and it +# returns the page as a Tcl string +# formvars are the posted variables in the following form: +# arg1=value1&arg2=value2 + +# in the event of an error or timeout, -1 is returned + +ad_proc -deprecated -public util_httppost {url formvars {timeout 30} {depth 0} {http_referer ""}} { + Returns the result of POSTing to another Web server or -1 if there is an error or timeout. + formvars should be in the form \"arg1=value1&arg2=value2\". +

+ post is encoded as application/x-www-form-urlencoded. See util_http_file_upload + for file uploads via post (encoded multipart/form-data). +

+ @see util_http_file_upload +} { + if { [catch { + if {[incr depth] > 10} { + return -code error "util_httppost: Recursive redirection: $url" + } + set http [util_httpopen POST $url "" $timeout $http_referer] + set rfd [lindex $http 0] + set wfd [lindex $http 1] + + #headers necessary for a post and the form variables + + _ns_http_puts $timeout $wfd "Content-type: application/x-www-form-urlencoded \r" + _ns_http_puts $timeout $wfd "Content-length: [string length $formvars]\r" + _ns_http_puts $timeout $wfd \r + _ns_http_puts $timeout $wfd "$formvars\r" + flush $wfd + close $wfd + + set rpset [ns_set new [_ns_http_gets $timeout $rfd]] + while 1 { + set line [_ns_http_gets $timeout $rfd] + if { $line eq "" } break + ns_parseheader $rpset $line + } + + set headers $rpset + set response [ns_set name $headers] + set status [lindex $response 1] + if {$status == 302} { + set location [ns_set iget $headers location] + if {$location ne ""} { + ns_set free $headers + close $rfd + return [util_httpget $location {} $timeout $depth] + } + } + set length [ns_set iget $headers content-length] + if { "" eq $length } {set length -1} + set type [ns_set iget $headers content-type] + set_encoding $type $rfd + set err [catch { + while 1 { + set buf [_ns_http_read $timeout $rfd $length] + append page $buf + if { "" eq $buf } break + if {$length > 0} { + incr length -[string length $buf] + if {$length <= 0} break + } + } + } errMsg] + ns_set free $headers + close $rfd + if {$err} { + return -code error -errorinfo $::errorInfo $errMsg + } + } errmgs ] } {return -1} + return $page +} + +# system by Tracy Adams (teadams@arsdigita.com) to permit AOLserver to POST +# to another Web server; sort of like ns_httpget + +ad_proc -deprecated -public util_httpopen { + method + url + {rqset ""} + {timeout 30} + {http_referer ""} +} { + Like ns_httpopen but works for POST as well; called by util_httppost +} { + + if { ![string match "http://*" $url] } { + return -code error "Invalid url \"$url\": _httpopen only supports HTTP" + } + set url [split $url /] + set hp [split [lindex $url 2] :] + set host [lindex $hp 0] + set port [lindex $hp 1] + if { [string match $port ""] } {set port 80} + set uri /[join [lrange $url 3 end] /] + set fds [ns_sockopen -nonblock $host $port] + set rfd [lindex $fds 0] + set wfd [lindex $fds 1] + if { [catch { + _ns_http_puts $timeout $wfd "$method $uri HTTP/1.0\r" + _ns_http_puts $timeout $wfd "Host: $host\r" + if {$rqset ne ""} { + for {set i 0} {$i < [ns_set size $rqset]} {incr i} { + _ns_http_puts $timeout $wfd \ + "[ns_set key $rqset $i]: [ns_set value $rqset $i]\r" + } + } else { + _ns_http_puts $timeout $wfd \ + "Accept: */*\r" + + _ns_http_puts $timeout $wfd "User-Agent: Mozilla/1.01 \[en\] (Win95; I)\r" + _ns_http_puts $timeout $wfd "Referer: $http_referer \r" + } + + } errMsg] } { + #close $wfd + #close $rfd + if { [info exists rpset] } {ns_set free $rpset} + return -1 + } + return [list $rfd $wfd ""] + +} + +ad_proc -deprecated -public util_http_file_upload { -file -data -binary:boolean -filename + -name {-mime_type */*} {-mode formvars} + {-rqset ""} url {formvars {}} {timeout 30} + {depth 10} {http_referer ""} +} { + Implement client-side HTTP file uploads as multipart/form-data as per + RFC 1867. +

+ + Similar to util_httppost, + but enhanced to be able to upload a file as multipart/form-data. + Also useful for posting to forms that require their input to be encoded + as multipart/form-data instead of as + application/x-www-form-urlencoded. + +

+ + The switches -file /path/to/file and -data + $raw_data are mutually exclusive. You can specify one or the + other, but not both. NOTE: it is perfectly valid to not specify + either, in which case no file is uploaded, but form variables are + encoded using multipart/form-data instead of the usual + encoding (as noted aboved). + +

+ + If you specify either -file or -data you + must supply a value for -name, which is + the name of the <INPUT TYPE="file" NAME="..."> form + tag. + +

+ + Specify the -binary switch if the file (or data) needs + to be base-64 encoded. Not all servers seem to be able to handle + this. (For example, http://mol-stage.usps.com/mml.adp, which + expects to receive an XML file doesn't seem to grok any kind of + Content-Transfer-Encoding.) + +

+ + If you specify -file then -filename is optional + (it can be inferred from the name of the file). However, if you + specify -data then it is mandatory. + +

+ + If -mime_type is not specified then ns_guesstype + is used to try and find a mime type based on the filename. + If ns_guesstype returns */* the generic value + of application/octet-stream will be used. + +

+ + Any form variables may be specified in one of four formats: +

+ +

+ + -rqset specifies an ns_set of extra headers to send to + the server when doing the POST. + +

+ + timeout, depth, and http_referer are optional, and are included + as optional positional variables in the same order they are used + in util_httppost. NOTE: util_http_file_upload does + not (currently) follow any redirects, so depth is superfluous. + + @author Michael A. Cleverly (michael@cleverly.com) + @creation-date 3 September 2002 + + @see util::http::post +} { + + # sanity checks on switches given + if {$mode ni {formvars array ns_set vars}} { + error "Invalid mode \"$mode\"; should be one of: formvars,\ + array, ns_set, vars" + } + + if {[info exists file] && [info exists data]} { + error "Both -file and -data are mutually exclusive; can't use both" + } + + if {[info exists file]} { + if {![file exists $file]} { + error "Error reading file: $file not found" + } + + if {![file readable $file]} { + error "Error reading file: $file permission denied" + } + + set fp [open $file] + fconfigure $fp -translation binary + set data [read $fp] + close $fp + + if {![info exists filename]} { + set filename [file tail $file] + } + + if {$mime_type eq "*/*" || $mime_type eq ""} { + set mime_type [ns_guesstype $file] + } + } + + set boundary [ns_sha1 [list [clock clicks -milliseconds] [clock seconds]]] + set payload {} + + if {[info exists data] && [string length $data]} { + if {![info exists name]} { + error "Cannot upload file without specifying form variable -name" + } + + if {![info exists filename]} { + error "Cannot upload file without specifying -filename" + } + + if {$mime_type eq "*/*" || $mime_type eq ""} { + set mime_type [ns_guesstype $filename] + + if {$mime_type eq "*/*" || $mime_type eq ""} { + set mime_type application/octet-stream + } + } + + if {$binary_p} { + set data [base64::encode base64] + set transfer_encoding base64 + } else { + set transfer_encoding binary + } + + append payload --$boundary \ + \r\n \ + "Content-Disposition: form-data; " \ + "name=\"$name\"; filename=\"$filename\"" \ + \r\n \ + "Content-Type: $mime_type" \ + \r\n \ + "Content-transfer-encoding: $transfer_encoding" \ + \r\n \ + \r\n \ + $data \ + \r\n + } + + + set variables [list] + switch -- $mode { + array { + set variables $formvars + } + + formvars { + foreach formvar [split $formvars &] { + set formvar [split $formvar =] + set key [lindex $formvar 0] + set val [join [lrange $formvar 1 end] =] + lappend variables $key $val + } + } + + ns_set { + for {set i 0} {$i < [ns_set size $formvars]} {incr i} { + set key [ns_set key $formvars $i] + set val [ns_set value $formvars $i] + lappend variables $key $val + } + } + + vars { + foreach key $formvars { + upvar 1 $key val + lappend variables $key $val + } + } + } + + foreach {key val} $variables { + append payload --$boundary \ + \r\n \ + "Content-Disposition: form-data; name=\"$key\"" \ + \r\n \ + \r\n \ + $val \ + \r\n + } + + append payload --$boundary-- \r\n + + if { [catch { + if {[incr depth -1] <= 0} { + return -code error "util_http_file_upload:\ + Recursive redirection: $url" + } + + lassign [util_httpopen POST $url $rqset $timeout $http_referer] rfd wfd + + _ns_http_puts $timeout $wfd \ + "Content-type: multipart/form-data; boundary=$boundary\r" + _ns_http_puts $timeout $wfd "Content-length: [string length $payload]\r" + _ns_http_puts $timeout $wfd \r + _ns_http_puts $timeout $wfd "$payload\r" + flush $wfd + close $wfd + + set rpset [ns_set new [_ns_http_gets $timeout $rfd]] + while 1 { + set line [_ns_http_gets $timeout $rfd] + if { $line eq "" } break + ns_parseheader $rpset $line + } + + set headers $rpset + set response [ns_set name $headers] + set status [lindex $response 1] + set length [ns_set iget $headers content-length] + if { "" eq $length } { set length -1 } + set type [ns_set iget $headers content-type] + set_encoding $type $rfd + set err [catch { + while 1 { + set buf [_ns_http_read $timeout $rfd $length] + append page $buf + if { "" eq $buf } break + if {$length > 0} { + incr length -[string length $buf] + if {$length <= 0} break + } + } + } errMsg] + + ns_set free $headers + close $rfd + + if {$err} { + return -code error -errorinfo $::errorInfo $errMsg + } + } errmsg] } { + if {[info exists wfd] && $wfd in [file channels]} { + close $wfd + } + + if {[info exists rfd] && $rfd in [file channels]} { + close $rfd + } + + set page -1 + } + + return $page +} + +# +# from tcl/community-core-procs.tcl +# + + +ad_proc -deprecated -private cc_lookup_screen_name_user { screen_name } { + @see acs_user::get_user_id_by_screen_name +} { + return [db_string user_select {} -default {}] +} + +ad_proc -deprecated cc_screen_name_user { screen_name } { + + @return Returns the user ID for a particular screen name, or an empty string + if none exists. + + @see acs_user::get_user_id_by_screen_name + +} { + return [util_memoize [list cc_lookup_screen_name_user $screen_name]] +} + +ad_proc -deprecated -private cc_lookup_email_user { email } { + Return the user_id of a user given the email. Returns the empty string if no such user exists. + @see party::get_by_email +} { + return [db_string user_select {} -default {}] +} + +ad_proc -public -deprecated cc_email_from_party { party_id } { + @return The email address of the indicated party. + @see party::email +} { + return [db_string email_from_party {} -default {}] +} + +ad_proc -deprecated cc_email_user { email } { + + @return Returns the user ID for a particular email address, or an empty string + if none exists. + + @see party::get_by_email +} { + return [util_memoize [list cc_lookup_email_user $email]] +} + +ad_proc -deprecated -private cc_lookup_name_group { name } { + @see group::get_id +} { + return [db_string group_select {} -default {}] +} + +ad_proc -deprecated cc_name_to_group { name } { + + Returns the group ID for a particular name, or an empty string + if none exists. + + @see group::get_id +} { + return [util_memoize [list cc_lookup_name_group $name]] +} + +ad_proc -deprecated ad_user_new { + email + first_names + last_name + password + password_question + password_answer + {url ""} + {email_verified_p "t"} + {member_state "approved"} + {user_id ""} + {username ""} + {authority_id ""} + {screen_name ""} +} { + Creates a new user in the system. The user_id can be specified as an argument to enable double click protection. + If this procedure succeeds, returns the new user_id. Otherwise, returns 0. + + @see auth::create_user + @see auth::create_local_account +} { + return [auth::create_local_account_helper \ + $email \ + $first_names \ + $last_name \ + $password \ + $password_question \ + $password_answer \ + $url \ + $email_verified_p \ + $member_state \ + $user_id \ + $username \ + $authority_id \ + $screen_name] +} + +# +# from tcl/community-core-2-procs.tc +# + + +# The User Namespace +namespace eval oacs::user { + + ad_proc -deprecated -public get { + {-user_id:required} + {-array:required} + } { + Load up user information + @see acs_user::get + } { + # Upvar the Tcl Array + upvar $array row + db_1row select_user {} -column_array row + } + +} + +# +# from tcl/00-database-procs.tcl +# +ad_proc -deprecated db_package_supports_rdbms_p { db_type_list } { + @return 1 if db_type_list contains the current RDMBS type. A package intended to run with a given RDBMS must note this in it's package info file regardless of whether or not it actually uses the database. + + @see apm_package_supports_rdbms_p +} { + if { [lsearch $db_type_list [db_type]] != -1 } { + return 1 + } + + # DRB: Legacy package check - we allow installation of old aD Oracle 4.2 packages, + # though we don't guarantee that they work. + + if { [db_type] eq "oracle" && [lsearch $db_type_list "oracle-8.1.6"] != -1 } { + return 1 + } + + return 0 +} + +# +# from tcl/apm-procs.tcl +# + +ad_proc -public -deprecated apm_doc_body_callback { string } { + This callback uses the document api to append more text to the stream. +} { + doc_body_append $string +} + +# +# from tcl/apm-file-procs.tcl +# + +ad_proc -public -deprecated pkg_home {package_key} { + + @return A server-root relative path to the directory for a package. Usually /packages/package-key + @see acs_package_root_dir + +} { + return "/packages/$package_key" +} + +# +# deprecated-utilities-procs.tcl +# + +# ad_library { +# +# Provides a variety of non-ACS-specific utilities that have been +# deprecated +# +# Note the 5.2 deprecated procs have been moved to deprecated/5.2/acs-tcl +# +# @author yon [yon@arsdigita.com] +# @creation-date 9 Jul 2000 +# @cvs-id $Id$ +# } + +# if you do a +# set selection [ns_db 1row $db "select foo,bar from my_table where key=37"] +# set_variables_after_query +# then you will find that the Tcl vars $foo and $bar are set to whatever +# the database returned. If you don't like these var names, you can say +# set selection [ns_db 1row $db "select count(*) as n_rows from my_table"] +# set_variables_after_query +# and you will find the Tcl var $n_rows set + +# You can also use this in a multi-row loop +# set selection [ns_db select $db "select *,email from mailing_list order by email"] +# while { [ns_db getrow $db $selection] } { +# set_variables_after_query +# ... your code here ... +# } +# then the appropriate vars will be set during your loop + +# +# CAVEAT NERDOR: you MUST use the variable name "selection" +# + +# +# we pick long names for the counter and limit vars +# because we don't want them to conflict with names of +# database columns or in parent programs +# + +ad_proc -deprecated -warn set_variables_after_query {} { + to be removed. + + + @see packages/acs-tcl/tcl/00-database-procs.tcl +} { + uplevel { + set set_variables_after_query_i 0 + set set_variables_after_query_limit [ns_set size $selection] + while {$set_variables_after_query_i<$set_variables_after_query_limit} { + set [ns_set key $selection $set_variables_after_query_i] [ns_set value $selection $set_variables_after_query_i] + incr set_variables_after_query_i + } + } +} + +# as above, but you must use sub_selection + +ad_proc -deprecated -warn set_variables_after_subquery {} { + to be removed. + + + @see packages/acs-tcl/tcl/00-database-procs.tcl +} { + uplevel { + set set_variables_after_query_i 0 + set set_variables_after_query_limit [ns_set size $sub_selection] + while {$set_variables_after_query_i<$set_variables_after_query_limit} { + set [ns_set key $sub_selection $set_variables_after_query_i] [ns_set value $sub_selection $set_variables_after_query_i] + incr set_variables_after_query_i + } + } +} + +#same as philg's but you can: +#1. specify the name of the "selection" variable +#2. append a prefix to all the named variables + +ad_proc -deprecated -warn set_variables_after_query_not_selection {selection_variable {name_prefix ""}} { + to be removed. + + + @see packages/acs-tcl/tcl/00-database-procs.tcl +} { + set set_variables_after_query_i 0 + set set_variables_after_query_limit [ns_set size $selection_variable] + while {$set_variables_after_query_i<$set_variables_after_query_limit} { + # NB backslash squarebracket needed since mismatched {} would otherwise mess up value stmt. + uplevel " + set ${name_prefix}[ns_set key $selection_variable $set_variables_after_query_i] \[ns_set value $selection_variable $set_variables_after_query_i] + " + incr set_variables_after_query_i + } +} + + +ad_proc -public -deprecated -warn ad_secure_conn_p {} { + Use security::secure_conn_p instead. + + @see security::secure_conn_p +} { + return [security::secure_conn_p] +} + +ad_proc -public -deprecated ad_get_user_id {} { + Gets the user ID. 0 indicates the user is not logged in. + + Deprecated since user_id now provided via ad_conn user_id + + @see ad_conn +} { + return [ad_conn user_id] +} + +ad_proc -public -deprecated -warn ad_verify_and_get_user_id { + {-secure f} +} { + Returns the current user's ID. 0 indicates user is not logged in + + Deprecated since user_id now provided via ad_conn user_id + + @see ad_conn +} { + return [ad_conn user_id] +} + +# handling privacy + +ad_proc -public -deprecated ad_privacy_threshold {} { + Pages that are consider whether to display a user's name or email + address should test to make sure that a user's priv_ from the + database is less than or equal to what ad_privacy_threshold returns. + + Now deprecated. + + @see ad_conn +} { + set session_user_id [ad_conn user_id] + if {$session_user_id == 0} { + # viewer of this page isn't logged in, only show stuff + # that is extremely unprivate + set privacy_threshold 0 + } else { + set privacy_threshold 5 + } + return $privacy_threshold +} + +ad_proc -deprecated ad_maybe_redirect_for_registration {} { + + Checks to see if a user is logged in. If not, redirects to + [subsite]/register/index to require the user to register. + When registration is complete, the user will return to the current + location. All variables in ns_getform (both posts and gets) will + be maintained. Note that this will return out of its caller so that + the caller need not explicitly call "return". Returns the user id + if login was successful. + + @see auth::require_login +} { + auth::require_login +} + +ad_proc -public -deprecated proc_doc { args } { + + A synonym for ad_proc (to support legacy code). + + @see ad_proc +} { + ad_proc {*}$args +} + +# +# GN: maybe this function was useful for ancient versions of Tcl, but +# unless i oversee something, it does not make any sense. The comment +# argues, that "return -code ..." ignores the error code, but then the +# function uses "return -code ..." to fix this... +# +ad_proc -deprecated ad_return { args } { + + Works like the "return" Tcl command, with one difference. Where + "return" will always return TCL_RETURN, regardless of the -code + switch this way, by burying it inside a proc, the proc will return + the code you specify. + +

+ + Why? Because "return" only sets the "returnCode" attribute of the + interpreter object, which the function actually interpreting the + procedure then reads and uses as the return code of the procedure. + This proc adds just that level of processing to the statement. + +

+ + When is that useful or necessary? Here: + +

+    set errno [catch {
+        return -code error "Boo!"
+    } error]
+    
+ + In this case, errno will always contain 2 (TCL_RETURN). + If you use ad_return instead, it'll contain what you wanted, namely + 1 (TCL_ERROR). + +} { + return {*}$args +} + +ad_proc -private -deprecated rp_handle_adp_request {} { + + Handles a request for an .adp file. + + @see adp_parse_ad_conn_file + +} { + doc_init + + set adp [ns_adp_parse -file [ad_conn file]] + + if { [doc_exists_p] } { + doc_set_property body $adp + doc_serve_document + } else { + set content_type [ns_set iget [ad_conn outputheaders] "content-type"] + if { $content_type eq "" } { + set content_type "text/html" + } + doc_return 200 $content_type $adp + } +} + + # Local variables: # mode: tcl # tcl-indent-level: 4 Index: openacs-4/packages/acs-tcl/tcl/http-client-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/http-client-procs.tcl,v diff -u -N -r1.8 -r1.9 --- openacs-4/packages/acs-tcl/tcl/http-client-procs.tcl 22 Dec 2017 14:14:20 -0000 1.8 +++ openacs-4/packages/acs-tcl/tcl/http-client-procs.tcl 19 Jan 2018 20:56:00 -0000 1.9 @@ -1868,512 +1868,8 @@ } -######################### -## Deprecated HTTP api ## -######################### -ad_proc -deprecated -public util_link_responding_p { - url - {list_of_bad_codes "404"} -} { - Returns 1 if the URL is responding (generally we think that anything other than 404 (not found) is okay). - @see util::link_responding_p -} { - util::link_responding_p -url $url -list_of_bad_codes $list_of_bad_codes -} - -ad_proc -public -deprecated util_get_http_status { - url - {use_get_p 1} - {timeout 30} -} { - Returns the HTTP status code, e.g., 200 for a normal response - or 500 for an error, of a URL. By default this uses the GET method - instead of HEAD since not all servers will respond properly to a - HEAD request even when the URL is perfectly valid. Note that - this means AOLserver may be sucking down a lot of bits that it - doesn't need. - - @see util::get_http_status -} { - return [util::get_http_status -url $url -use_get_p $use_get_p -timeout $timeout] -} - -ad_proc -deprecated -public ad_httpget { - -url - {-headers ""} - {-timeout 30} - {-depth 0} -} { - Just like ns_httpget, but first headers is an ns_set of - headers to send during the fetch. - - ad_httpget also makes use of Conditional GETs (if called with a - Last-Modified header). - - Returns the data in array get form with array elements page status modified. - - @see util::http::get -} { - ns_log debug "Getting {$url} {$headers} {$timeout} {$depth}" - - if {[incr depth] > 10} { - return -code error "ad_httpget: Recursive redirection: $url" - } - - lassign [ns_httpopen GET $url $headers $timeout] rfd wfd headers - close $wfd - - set response [ns_set name $headers] - set status [lindex $response 1] - set last_modified [ns_set iget $headers last-modified] - - if {$status == 302 || $status == 301} { - set location [ns_set iget $headers location] - if {$location ne ""} { - ns_set free $headers - close $rfd - return [ad_httpget -url $location -timeout $timeout -depth $depth] - } - } elseif { $status == 304 } { - # The requested variant has not been modified since the time specified - # A conditional get didn't return anything. return an empty page and - set page {} - - ns_set free $headers - close $rfd - } else { - set length [ns_set iget $headers content-length] - if { $length eq "" } {set length -1} - - set type [ns_set iget $headers content-type] - set_encoding $type $rfd - - set err [catch { - while 1 { - set buf [_ns_http_read $timeout $rfd $length] - append page $buf - if { "" eq $buf } break - if {$length > 0} { - incr length -[string length $buf] - if {$length <= 0} break - } - } - } errMsg] - ns_set free $headers - close $rfd - - if {$err} { - return -code error -errorinfo $::errorInfo $errMsg - } - } - - # order matters here since we depend on page content - # being element 1 in this list in util_httpget - return [list page $page \ - status $status \ - modified $last_modified] -} - -ad_proc -deprecated -public util_httpget { - url {headers ""} {timeout 30} {depth 0} -} { - util_httpget simply calls util::http::get which also returns - status and last_modfied - - @see util::http::get -} { - return [dict get [util::http::get -url $url -headers $headers -timeout $timeout -depth $depth] page] -} - -# httppost; give it a URL and a string with formvars, and it -# returns the page as a Tcl string -# formvars are the posted variables in the following form: -# arg1=value1&arg2=value2 - -# in the event of an error or timeout, -1 is returned - -ad_proc -deprecated -public util_httppost {url formvars {timeout 30} {depth 0} {http_referer ""}} { - Returns the result of POSTing to another Web server or -1 if there is an error or timeout. - formvars should be in the form \"arg1=value1&arg2=value2\". -

- post is encoded as application/x-www-form-urlencoded. See util_http_file_upload - for file uploads via post (encoded multipart/form-data). -

- @see util_http_file_upload -} { - if { [catch { - if {[incr depth] > 10} { - return -code error "util_httppost: Recursive redirection: $url" - } - set http [util_httpopen POST $url "" $timeout $http_referer] - set rfd [lindex $http 0] - set wfd [lindex $http 1] - - #headers necessary for a post and the form variables - - _ns_http_puts $timeout $wfd "Content-type: application/x-www-form-urlencoded \r" - _ns_http_puts $timeout $wfd "Content-length: [string length $formvars]\r" - _ns_http_puts $timeout $wfd \r - _ns_http_puts $timeout $wfd "$formvars\r" - flush $wfd - close $wfd - - set rpset [ns_set new [_ns_http_gets $timeout $rfd]] - while 1 { - set line [_ns_http_gets $timeout $rfd] - if { $line eq "" } break - ns_parseheader $rpset $line - } - - set headers $rpset - set response [ns_set name $headers] - set status [lindex $response 1] - if {$status == 302} { - set location [ns_set iget $headers location] - if {$location ne ""} { - ns_set free $headers - close $rfd - return [util_httpget $location {} $timeout $depth] - } - } - set length [ns_set iget $headers content-length] - if { "" eq $length } {set length -1} - set type [ns_set iget $headers content-type] - set_encoding $type $rfd - set err [catch { - while 1 { - set buf [_ns_http_read $timeout $rfd $length] - append page $buf - if { "" eq $buf } break - if {$length > 0} { - incr length -[string length $buf] - if {$length <= 0} break - } - } - } errMsg] - ns_set free $headers - close $rfd - if {$err} { - return -code error -errorinfo $::errorInfo $errMsg - } - } errmgs ] } {return -1} - return $page -} - -# system by Tracy Adams (teadams@arsdigita.com) to permit AOLserver to POST -# to another Web server; sort of like ns_httpget - -ad_proc -deprecated -public util_httpopen { - method - url - {rqset ""} - {timeout 30} - {http_referer ""} -} { - Like ns_httpopen but works for POST as well; called by util_httppost -} { - - if { ![string match "http://*" $url] } { - return -code error "Invalid url \"$url\": _httpopen only supports HTTP" - } - set url [split $url /] - set hp [split [lindex $url 2] :] - set host [lindex $hp 0] - set port [lindex $hp 1] - if { [string match $port ""] } {set port 80} - set uri /[join [lrange $url 3 end] /] - set fds [ns_sockopen -nonblock $host $port] - set rfd [lindex $fds 0] - set wfd [lindex $fds 1] - if { [catch { - _ns_http_puts $timeout $wfd "$method $uri HTTP/1.0\r" - _ns_http_puts $timeout $wfd "Host: $host\r" - if {$rqset ne ""} { - for {set i 0} {$i < [ns_set size $rqset]} {incr i} { - _ns_http_puts $timeout $wfd \ - "[ns_set key $rqset $i]: [ns_set value $rqset $i]\r" - } - } else { - _ns_http_puts $timeout $wfd \ - "Accept: */*\r" - - _ns_http_puts $timeout $wfd "User-Agent: Mozilla/1.01 \[en\] (Win95; I)\r" - _ns_http_puts $timeout $wfd "Referer: $http_referer \r" - } - - } errMsg] } { - #close $wfd - #close $rfd - if { [info exists rpset] } {ns_set free $rpset} - return -1 - } - return [list $rfd $wfd ""] - -} - -ad_proc -deprecated -public util_http_file_upload { -file -data -binary:boolean -filename - -name {-mime_type */*} {-mode formvars} - {-rqset ""} url {formvars {}} {timeout 30} - {depth 10} {http_referer ""} -} { - Implement client-side HTTP file uploads as multipart/form-data as per - RFC 1867. -

- - Similar to util_httppost, - but enhanced to be able to upload a file as multipart/form-data. - Also useful for posting to forms that require their input to be encoded - as multipart/form-data instead of as - application/x-www-form-urlencoded. - -

- - The switches -file /path/to/file and -data - $raw_data are mutually exclusive. You can specify one or the - other, but not both. NOTE: it is perfectly valid to not specify - either, in which case no file is uploaded, but form variables are - encoded using multipart/form-data instead of the usual - encoding (as noted aboved). - -

- - If you specify either -file or -data you - must supply a value for -name, which is - the name of the <INPUT TYPE="file" NAME="..."> form - tag. - -

- - Specify the -binary switch if the file (or data) needs - to be base-64 encoded. Not all servers seem to be able to handle - this. (For example, http://mol-stage.usps.com/mml.adp, which - expects to receive an XML file doesn't seem to grok any kind of - Content-Transfer-Encoding.) - -

- - If you specify -file then -filename is optional - (it can be inferred from the name of the file). However, if you - specify -data then it is mandatory. - -

- - If -mime_type is not specified then ns_guesstype - is used to try and find a mime type based on the filename. - If ns_guesstype returns */* the generic value - of application/octet-stream will be used. - -

- - Any form variables may be specified in one of four formats: -

- -

- - -rqset specifies an ns_set of extra headers to send to - the server when doing the POST. - -

- - timeout, depth, and http_referer are optional, and are included - as optional positional variables in the same order they are used - in util_httppost. NOTE: util_http_file_upload does - not (currently) follow any redirects, so depth is superfluous. - - @author Michael A. Cleverly (michael@cleverly.com) - @creation-date 3 September 2002 - - @see util::http::post -} { - - # sanity checks on switches given - if {$mode ni {formvars array ns_set vars}} { - error "Invalid mode \"$mode\"; should be one of: formvars,\ - array, ns_set, vars" - } - - if {[info exists file] && [info exists data]} { - error "Both -file and -data are mutually exclusive; can't use both" - } - - if {[info exists file]} { - if {![file exists $file]} { - error "Error reading file: $file not found" - } - - if {![file readable $file]} { - error "Error reading file: $file permission denied" - } - - set fp [open $file] - fconfigure $fp -translation binary - set data [read $fp] - close $fp - - if {![info exists filename]} { - set filename [file tail $file] - } - - if {$mime_type eq "*/*" || $mime_type eq ""} { - set mime_type [ns_guesstype $file] - } - } - - set boundary [ns_sha1 [list [clock clicks -milliseconds] [clock seconds]]] - set payload {} - - if {[info exists data] && [string length $data]} { - if {![info exists name]} { - error "Cannot upload file without specifying form variable -name" - } - - if {![info exists filename]} { - error "Cannot upload file without specifying -filename" - } - - if {$mime_type eq "*/*" || $mime_type eq ""} { - set mime_type [ns_guesstype $filename] - - if {$mime_type eq "*/*" || $mime_type eq ""} { - set mime_type application/octet-stream - } - } - - if {$binary_p} { - set data [base64::encode base64] - set transfer_encoding base64 - } else { - set transfer_encoding binary - } - - append payload --$boundary \ - \r\n \ - "Content-Disposition: form-data; " \ - "name=\"$name\"; filename=\"$filename\"" \ - \r\n \ - "Content-Type: $mime_type" \ - \r\n \ - "Content-transfer-encoding: $transfer_encoding" \ - \r\n \ - \r\n \ - $data \ - \r\n - } - - - set variables [list] - switch -- $mode { - array { - set variables $formvars - } - - formvars { - foreach formvar [split $formvars &] { - set formvar [split $formvar =] - set key [lindex $formvar 0] - set val [join [lrange $formvar 1 end] =] - lappend variables $key $val - } - } - - ns_set { - for {set i 0} {$i < [ns_set size $formvars]} {incr i} { - set key [ns_set key $formvars $i] - set val [ns_set value $formvars $i] - lappend variables $key $val - } - } - - vars { - foreach key $formvars { - upvar 1 $key val - lappend variables $key $val - } - } - } - - foreach {key val} $variables { - append payload --$boundary \ - \r\n \ - "Content-Disposition: form-data; name=\"$key\"" \ - \r\n \ - \r\n \ - $val \ - \r\n - } - - append payload --$boundary-- \r\n - - if { [catch { - if {[incr depth -1] <= 0} { - return -code error "util_http_file_upload:\ - Recursive redirection: $url" - } - - lassign [util_httpopen POST $url $rqset $timeout $http_referer] rfd wfd - - _ns_http_puts $timeout $wfd \ - "Content-type: multipart/form-data; boundary=$boundary\r" - _ns_http_puts $timeout $wfd "Content-length: [string length $payload]\r" - _ns_http_puts $timeout $wfd \r - _ns_http_puts $timeout $wfd "$payload\r" - flush $wfd - close $wfd - - set rpset [ns_set new [_ns_http_gets $timeout $rfd]] - while 1 { - set line [_ns_http_gets $timeout $rfd] - if { $line eq "" } break - ns_parseheader $rpset $line - } - - set headers $rpset - set response [ns_set name $headers] - set status [lindex $response 1] - set length [ns_set iget $headers content-length] - if { "" eq $length } { set length -1 } - set type [ns_set iget $headers content-type] - set_encoding $type $rfd - set err [catch { - while 1 { - set buf [_ns_http_read $timeout $rfd $length] - append page $buf - if { "" eq $buf } break - if {$length > 0} { - incr length -[string length $buf] - if {$length <= 0} break - } - } - } errMsg] - - ns_set free $headers - close $rfd - - if {$err} { - return -code error -errorinfo $::errorInfo $errMsg - } - } errmsg] } { - if {[info exists wfd] && $wfd in [file channels]} { - close $wfd - } - - if {[info exists rfd] && $rfd in [file channels]} { - close $rfd - } - - set page -1 - } - - return $page -} - # # Local variables: # mode: tcl Index: openacs-4/packages/acs-tcl/tcl/navigation-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/navigation-procs.tcl,v diff -u -N -r1.34 -r1.35 --- openacs-4/packages/acs-tcl/tcl/navigation-procs.tcl 22 Dec 2017 14:14:20 -0000 1.34 +++ openacs-4/packages/acs-tcl/tcl/navigation-procs.tcl 19 Jan 2018 20:56:00 -0000 1.35 @@ -202,42 +202,8 @@ -ad_proc -deprecated -public ad_context_bar_ws args { - Returns a Yahoo-style hierarchical navbar. Use ad_context_bar instead. - @param list of url desc ([list [list url desc] [list url desc] ... "terminal"]) - @return an html fragment generated by ad_context_bar_html - @see ad_context_bar -} { - return [ad_context_bar $args] -} - -# a context bar, rooted at the workspace or index, depending on whether -# user is logged in - -ad_proc -deprecated -public ad_context_bar_ws_or_index args { - Returns a Yahoo-style hierarchical navbar. Use ad_context_bar instead. - - @param args list of url desc ([list [list url desc] [list url desc] ... "terminal"]) - @return an html fragment generated by ad_context_bar - - @see ad_context_bar -} { - return [ad_context_bar $args] -} - -ad_proc -public -deprecated ad_admin_context_bar args { - Returns a Yahoo-style hierarchical navbar. Use ad_context_bar instead. - - @param args list of url desc ([list [list url desc] [list url desc] ... "terminal"]) - @return an html fragment generated by ad_context_bar - - @see ad_context_bar -} { - return [ad_context_bar $args] -} - ad_proc -public ad_navbar args { produces navigation bar. notice that navigation bar is different than context bar, which displays packages in the site map. Navbar will Index: openacs-4/packages/acs-tcl/tcl/set-operation-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/Attic/set-operation-procs.tcl,v diff -u -N -r1.5 -r1.6 --- openacs-4/packages/acs-tcl/tcl/set-operation-procs.tcl 7 Aug 2017 23:48:00 -0000 1.5 +++ openacs-4/packages/acs-tcl/tcl/set-operation-procs.tcl 19 Jan 2018 20:56:00 -0000 1.6 @@ -10,140 +10,6 @@ - - - -ad_proc -deprecated set_member? { s v } { -

Tests whether or not $v is a member of set $s.

-} { - if {$v ni $s} { - return 0 - } else { - return 1 - } -} - - - -ad_proc -deprecated set_append! { s-name v } { -

Adds the element v to the set named s-name in the calling - environment, if it isn't already there.

-} { - upvar $s-name s - - if { ![set_member? $s $v] } { - lappend s $v - } -} - - - -ad_proc -deprecated set_union { u v } { -

Returns the union of sets $u and $v.

-} { - set result $u - - foreach ve $v { - if { ![set_member? $result $ve] } { - lappend result $ve - } - } - - return $result -} - -ad_proc -deprecated set_union! { u-name v } { -

Computes the union of the set stored in the variable - named $u-name in the calling environment and the set v, - sets the variable named $u-name in the calling environment - to that union, and also returns that union.

-} { - upvar $u-name u - - foreach ve $v { - if { ![set_member? $u $ve] } { - lappend u $ve - } - } - - return $u -} - - - - -ad_proc -deprecated set_intersection { u v } { -

Returns the intersection of sets $u and $v.

-} { - set result [list] - - foreach ue $u { - if { [set_member? $v $ue] } { - lappend result $ue - } - } - - return $result -} - -ad_proc -deprecated set_intersection! { u-name v } { -

Computes the intersection of the set stored in the variable - named $u-name in the calling environment and the set v, - sets the variable named $u-name in the calling environment - to that intersection, and also returns that intersection.

-} { - upvar $u-name u - set result [list] - - foreach ue $u { - if { [set_member? $v $ue] } { - lappend result $ue - } - } - - set u $result - return $result -} - - - - - -ad_proc -deprecated set_difference { u v } { -

Returns the difference of sets $u and $v. (i.e. The set of all - members of u that aren't also members of $v.)

-} { - set result [list] - - foreach ue $u { - if { ![set_member? $v $ue] } { - lappend result $ue - } - } - - return $result -} - -ad_proc -deprecated set_difference! { u-name v } { -

Computes the difference of the set stored in the variable - named $u-name in the calling environment and the set v, - sets the variable named $u-name in the calling environment - to that difference, and also returns that difference.

-} { - upvar $u-name u - set result [list] - - foreach ue $u { - if { ![set_member? $v $ue] } { - lappend result $ue - } - } - - set u $result - return $result -} - - # Local variables: # mode: tcl # tcl-indent-level: 4 Index: openacs-4/packages/acs-tcl/tcl/table-display-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/Attic/table-display-procs.tcl,v diff -u -N -r1.25 -r1.26 --- openacs-4/packages/acs-tcl/tcl/table-display-procs.tcl 1 Oct 2017 12:16:05 -0000 1.25 +++ openacs-4/packages/acs-tcl/tcl/table-display-procs.tcl 19 Jan 2018 20:56:00 -0000 1.26 @@ -5,891 +5,6 @@ } - - -ad_proc -deprecated ad_dimensional_set_variables {option_list {options_set ""}} { - set the variables defined in option_list from the form provided - (form defaults to ad_conn form) or to default value from option_list if - not in the form data. -

- You only really need to call this if you need the variables - (for example to pick which select statement and table to actually use) -} { - set out {} - - if {$option_list eq ""} { - return - } - - if {$options_set eq ""} { - set options_set [ns_getform] - } - - foreach option $option_list { - # find out what the current option value is. - # check if a default is set otherwise the first value is used - set option_key [lindex $option 0] - set option_val {} - # get the option from the form - if { $options_set ne "" && [ns_set find $options_set $option_key] != -1} { - uplevel [list set $option_key [ns_set get $options_set $option_key]] - } else { - uplevel [list set $option_key [lindex $option 2]] - } - } -} - -ad_proc -deprecated ad_table { - {-Torder_target_url {}} - {-Torderby {}} - {-Tasc_order_img {^}} - {-Tdesc_order_img {v}} - {-Tmissing_text "No data found."} - {-Tsuffix {}} - {-Tcolumns {}} - {-Taudit {}} - {-Trows_per_band 1} - {-Tband_colors {{} "#ececec"}} - {-Tband_classes {{even} {odd}}} - {-Trows_per_page 0} - {-Tmax_rows 0} - {-Ttable_extra_html {cellpadding=3 cellspacing=0 class="table-display"}} - {-Theader_row_extra {style="background-color:#f8f8f8" class="table-header"}} - {-Ttable_break_html "

"} - {-Tpre_row_code {}} - {-Trow_code {[subst $Trow_default]}} - {-Tpost_data_ns_sets {}} - {-Textra_vars {}} - {-Textra_rows {}} - {-bind {}} - {-dbn {}} - statement_name sql_qry Tdatadef -} { - - DRB: New code should use the listbuilder. - - Note: all the variables in this function are named Tblah since we could potentially - have namespace collisions -

- build and return an html fragment given an active query and a data definition. -

- - Datadef structure : -
 
-    { 
-        {column_id "Column_Heading" order_clause display_info}
-        ...
-    }
-    
- - - @param dbn The database name to use. If empty_string, uses the default database. -} { - - set full_statement_name [db_qd_get_fullname $statement_name] - - # This procedure needs a full rewrite! - db_with_handle -dbn $dbn Tdb { - # Execute the query - set selection [db_exec select $Tdb $full_statement_name $sql_qry] - set Tcount 0 - set Tband_count 0 - set Tpage_count 0 - set Tband_color 0 - set Tband_class 0 - set Tn_bands [llength $Tband_colors] - set Tn_band_classes [llength $Tband_classes] - set Tform [ad_conn form] - - # export variables from calling environment - if {$Textra_vars ne ""} { - foreach Tvar $Textra_vars { - upvar $Tvar $Tvar - } - } - - # get the current ordering information - set Torderbykey {::not_sorted::} - set Treverse {} - regexp {^([^*,]+)([*])?} $Torderby match Torderbykey Treverse - if {$Treverse eq "*"} { - set Torder desc - } else { - set Torder asc - } - - # set up the target url for new sorts - if {$Torder_target_url eq ""} { - set Torder_target_url [ad_conn url] - } - set Texport "[uplevel [list export_ns_set_vars url [list orderby$Tsuffix]]]&" - if {$Texport == "&"} { - set Texport {} - } - set Tsort_url "$Torder_target_url?${Texport}orderby$Tsuffix=" - - set Thtml {} - set Theader {} - - # build the list of columns to display... - set Tcolumn_list [ad_table_column_list $Tdatadef $Tcolumns] - - # generate the header code - # - append Theader "\n" - if {$Theader_row_extra eq ""} { - append Theader "\n" - } else { - append Theader "\n" - } - foreach Ti $Tcolumn_list { - set Tcol [lindex $Tdatadef $Ti] - if { ( [ns_set find $selection [lindex $Tcol 0]] < 0 - && ([lindex $Tcol 2] eq "" || [lindex $Tcol 2] ne "sort_by_pos") - ) - || [lindex $Tcol 2] eq "no_sort" - } { - - # not either a column in the select or has sort code - # then just a plain text header so do not do sorty things - append Theader " \n" - } else { - if {[lindex $Tcol 0] eq $Torderbykey } { - if {$Torder eq "desc"} { - set Tasord $Tasc_order_img - } else { - set Tasord $Tdesc_order_img - } - } else { - set Tasord {} - } - set href $Tsort_url[ns_urlencode [ad_new_sort_by [lindex $Tcol 0] $Torderby]] - append Theader \ - [subst { \n" - } - } - append Theader "\n" - - # - # This has gotten kind of ugly. Here we are looping over the - # rows returned and then potentially a list of ns_sets which can - # be passed in (grrr. Richard Li needs for general protections stuff - # for "fake" public record which does not exist in DB). - # - - set Tpost_data 0 - - while { 1 } { - if {!$Tpost_data && [ns_db getrow $Tdb $selection]} { - # in all its evil majesty - set_variables_after_query - } else { - # move on to fake rows... - incr Tpost_data - } - - if { $Tpost_data && $Tpost_data <= [llength $Tpost_data_ns_sets] } { - # bind the Tpost_data_ns_sets row of the passed in data - set_variables_after_query_not_selection [lindex $Tpost_data_ns_sets $Tpost_data-1] - } elseif { $Tpost_data } { - # past the end of the fake data drop out. - break - } - - if { $Tmax_rows && $Tcount >= $Tmax_rows } { - if { ! $Tpost_data } { - # we hit max count and had rows left to read... - ns_db flush $Tdb - } - break - } - - # deal with putting in the header if need - if { $Tcount == 0 } { - append Thtml "$Theader" - } elseif { $Tpage_count == 0 } { - append Thtml "
[lindex $Tcol 1]}] \ - "\n[lindex $Tcol 1] $Tasord
\n$Ttable_break_html\n$Theader" - } - - # first check if we are in audit mode and if the audit columns have changed - set Tdisplay_changes_only 0 - if {$Taudit ne "" && $Tcount > 0} { - # check if the audit key columns changed - foreach Taudit_key $Taudit { - if {[set $Taudit_key] eq [set P$Taudit_key] } { - set Tdisplay_changes_only 1 - } - } - } - - # this is for breaking on sorted field etc. - append Thtml [subst $Tpre_row_code] - - if { ! $Tdisplay_changes_only } { - # in audit mode a record spans multiple rows. - incr Tcount - incr Tband_count - } - incr Tpage_count - - if { $Trows_per_page && $Tpage_count >= $Trows_per_page } { - set Tband_color 0 - set Tband_class 0 - set Tband_count 0 - set Tpage_count 0 - - } - - set Trow_default {} - # generate the row band color - if { $Tband_count >= $Trows_per_band } { - set Tband_count 0 - set Tband_color [expr {($Tband_color + 1) % $Tn_bands} ] - set Tband_class [expr {($Tband_class + 1) % $Tn_band_classes} ] - } - # do this check since we would like the ability to band with - # page background as well - if {$Tn_bands && [lindex $Tband_colors $Tband_color] ne ""} { - append Trow_default " style=\"background-color:[lindex $Tband_colors $Tband_color]\"" - } - if {$Tn_band_classes && [lindex $Tband_classes $Tband_class] ne ""} { - append Trow_default " class=\"[lindex $Tband_classes $Tband_class]\"" - } - - - set Trow_default "" - - append Thtml [subst $Trow_code] - - foreach Ti $Tcolumn_list { - set Tcol [lindex $Tdatadef $Ti] - # If we got some special formatting code we handle it - # single characters r l c are special for alignment - set Tformat [lindex $Tcol 3] - set Tcolumn [lindex $Tcol 0] - switch -- $Tformat { - "" {set Tdisplay_field " [set $Tcolumn]\n"} - r {set Tdisplay_field " [set $Tcolumn]\n"} - l {set Tdisplay_field " [set $Tcolumn]\n"} - c {set Tdisplay_field " [set $Tcolumn]\n"} - tf {set Tdisplay_field " [util_PrettyBoolean [set $Tcolumn]]\n"} - 01 {set Tdisplay_field " [util_PrettyTclBoolean [set $Tcolumn]]\n"} - bz {set Tdisplay_field "  [blank_zero [set $Tcolumn]]\n"} - default {set Tdisplay_field " [subst $Tformat]\n"} - } - - if { $Tdisplay_changes_only - && $Tdisplay_field eq $Tlast_display($Ti) } { - set Tdisplay_field { } - } else { - set Tlast_display($Ti) $Tdisplay_field - } - append Thtml $Tdisplay_field - } - - append Thtml "\n" - - # keep the last row around so we can do fancy things. - # so on next row we can say things like if $Pvar != $var not blank - if { $Tpost_data && $Tpost_data <= [llength $Tpost_data_ns_sets] } { - # bind the Tpost_data_ns_sets row of the passed in data - set_variables_after_query_not_selection [lindex $Tpost_data_ns_sets $Tpost_data-1] P - } else { - set_variables_after_query_not_selection $selection P - } - } - - if { $Tcount > 0} { - append Thtml "$Textra_rows -\n" - } else { - append Thtml $Tmissing_text - } - } - return $Thtml -} - -ad_proc -deprecated ad_table_column_list { - { -sortable all } - datadef columns -} { - build a list of pointers into the list of column definitions -

- returns a list of indexes into the columns one per column it found -

- -sortable from t/f/all -} { - set column_list {} - if {$columns eq ""} { - for {set i 0} {$i < [llength $datadef]} {incr i} { - if {$sortable eq "all" - || ($sortable == "t" && [lindex $datadef $i 2] ne "no_sort") - || ($sortable == "f" && [lindex $datadef $i 2] eq "no_sort") - } { - lappend column_list $i - } - } - } else { - set colnames {} - foreach col $datadef { - if {$sortable eq "all" - || ($sortable == "t" && [lindex $col 2] ne "no_sort") - || ($sortable == "f" && [lindex $col 2] eq "no_sort") - } { - lappend colnames [lindex $col 0] - } else { - # placeholder for invalid column - lappend colnames "X+X" - } - } - foreach col $columns { - set i [lsearch $colnames $col] - if {$i > -1} { - lappend column_list $i - } - } - } - - return $column_list -} - -ad_proc -deprecated ad_sort_primary_key {orderby} { - return the primary (first) key of an order spec - used by -} { - if {[regexp {^([^*,]+)} $orderby match]} { - return $match - } - return $orderby -} - -ad_proc -deprecated ad_table_same varname { - Called from inside ad_table. - - returns true if the variable has same value as - on the previous row. Always false for 1st row. - -} { - if { [uplevel set Tcount] - && [uplevel string compare \$$varname \$P$varname] == 0} { - return 1 - } else { - return 0 - } -} - -ad_proc -deprecated ad_table_span {str {td_html "align=\"left\""}} { - given string the function generates a row which spans the - whole table. -} { - return "$str" -} - -ad_proc -deprecated ad_table_form { - datadef - {type select} - {return_url {}} - {item_group {}} - {item {}} - {columns {}} - {allowed {}} -} { - builds a form for chosing the columns to display -

- columns is a list of the currently selected columns. -

- allowed is the list of all the displayable columns, if empty - all columns are allowed. -} { - # first build a map of all available columns - set sel_list [ad_table_column_list $datadef $allowed] - - # build the map of currently selected columns - set sel_columns [ad_table_column_list $datadef $columns] - - set max_columns [llength $sel_list] - set n_sel_columns [llength $sel_columns] - - set html {} - if {$item eq "CreateNewCustom" } { - set item {} - } - # now spit out the form fragment. - if {$item ne ""} { - append html "

Editing $item

" - append html "" - append html "" - append html "" - append html "[export_vars -form {item_group item}]" - if {$return_url ne ""} { - append html "[export_vars -form {return_url}]" - } - append html "" - } - - append html "
" - if {$return_url ne ""} { - append html "[export_vars -form {return_url}]" - } - if {$item_group eq ""} { - set item_group [ad_conn url] - } - - append html "[export_vars -form {item_group}]" - if {$item ne ""} { - set item_original $item - append html "[export_vars -form {item_original}]" - append html "" - } else { - append html "" - } - - append html "" - append html "" - if {$item ne ""} { - set item_original item - append html "[export_vars -form {item_original}]" - append html "" - } - - if {$type eq "select" } { - # select table - set options "" - foreach opt $sel_list { - append options " " - } - - for {set i 0} { $i < $max_columns} {incr i} { - if {$i < $n_sel_columns} { - set match [lindex $datadef [lindex $sel_columns $i] 0] - regsub "(\n" - } - } else { - # radio button table - append html "" - foreach opt $sel_list { - append html "" - } - append html "" - - foreach opt $sel_list { - append options "" - } - for {set i 0} { $i < $max_columns} {incr i} { - if {$i < $n_sel_columns} { - set match [lindex $datadef [lindex $sel_columns $i] 0] - regsub "( type=\"radio\" )(value=\"$match\">)" $options "\\1 checked=\"checked\" \\2" out - } else { - set out $options - } - regsub -all {@@} $out $i out - append html "$out\n" - } - } - append html "
Name:
 Editing the name will rename the view
[expr {$i + 1}]
Col \#[lindex $datadef $opt 1]
[expr {$i + 1}]
" - - return $html -} - -ad_proc -deprecated ad_table_sort_form { - datadef - {type select} - {return_url {}} - {item_group {}} - {item {}} - {sort_spec {}} - {allowed {}} -} { - builds a form for setting up custom sorts. -

-

    -
  • datadef is the table definition as in ad_table. -
  • type is select or radio (only select is implemented now) -
  • return_url is the return url passed through to the page that validates and saves the - sort customization. -
  • item_group is a string identifying the customization "ticket_tracker_main_sort" for example. -
  • item is the user entered identifier -
  • sort_spec is the sort specifier as in ad_new_sort_by -
  • allowed is the list of all the columns allowed, if empty all are allowed. -
-

- An example from the ticket system: -

-      ad_table_sort_form $tabledef select $return_url ticket_tracker_main_sort $ticket_sort $orderby
-    
-} { - # first build a map of all available columns - set sel_list [ad_table_column_list -sortable t $datadef $allowed] - - # build the map of currently selected columns - set full_column [split $sort_spec ","] - set sel_columns [list] - set direction [list] - foreach col $full_column { - regexp {([^*,]+)([*])?} $col match coln dirn - if {$dirn eq "*"} { - set dirn desc - } else { - set dirn asc - } - lappend sel_columns $coln - lappend direction $dirn - } - - set max_columns 4 - set n_sel_columns [llength $sel_columns] - - set html {} - if {$item eq "CreateNewCustom" } { - set item {} - } - # now spit out the form fragment. - if {$item ne ""} { - append html "

Editing $item

" - append html "
" - append html "" - append html "" - append html "[export_vars -form {item_group item}]" - if {$return_url ne ""} { - append html "[export_vars -form {return_url}]" - } - append html "
" - } - - append html "
" - if {$return_url ne ""} { - append html "[export_vars -form {return_url}]" - } - if {$item_group eq ""} { - set item_group [ad_conn url] - } - - append html "[export_vars -form {item_group}]" - if {$item ne ""} { - set item_original $item - append html "[export_vars -form {item_original}]" - append html "" - } else { - append html "" - } - - append html "" - append html "" - if {$item ne ""} { - set item_original item - append html "[export_vars -form {item_original}]" - append html "" - } - - set options "" - foreach opt $sel_list { - append options " " - } - - for {set i 0} { $i < $max_columns} {incr i} { - if {$i < $n_sel_columns} { - set match [lindex $sel_columns $i] - regsub "(\n" - } - append html "
Name:
 Editing the name will rename the sort
[expr {$i + 1}]" - switch [lindex $direction $i] { - asc { - append html "" - } - default { - append html "" - - } - } - append html "\n
" - - return $html -} - -ad_proc -deprecated ad_order_by_from_sort_spec {sort_by tabledef} { - Takes a sort_by spec, and translates it into into an "order by" clause - with each sort_by key dictated by the sort info in tabledef -} { - set order_by_clause {} - - foreach sort_key_spec [split $sort_by ","] { - if { [regexp {^([A-Za-z_0-9]+)(\*?)$} $sort_key_spec match sort_key reverse] } { - # if there's a "*" after the key, we want to reverse the usual order - foreach order_spec $tabledef { - if { $sort_key == [lindex $order_spec 0] } { - if { $reverse eq "*" } { - set order "desc" - } else { - set order "asc" - } - - if { $order_by_clause eq "" } { - append order_by_clause "\norder by " - } else { - append order_by_clause ", " - } - - # tack on the order by clause - if {[lindex $order_spec 2] ne "" && [lindex $order_spec 2] ne "sort_by_pos"} { - append order_by_clause "[subst [lindex $order_spec 2]]" - } else { - append order_by_clause "$sort_key $order" - } - break - } - } - } - } - return $order_by_clause -} - -ad_proc -deprecated ad_new_sort_by {key keys} { - Makes a new sort_by string, sorting by "key". - - If the key is followed by "*", that indicates the ordering should - be reversed from the default ordering for that key. - - Old sort keys are retained, so the sort appears to be a little more stable. - That is, suppose two things are sorted into an order, and their values for a - different column are the same. If that different column is used as the primary - sort key to reorder, the things which have the same value for the newly-sorted - column will remain in the same relative order. -} { - if { $keys eq "" } { - return $key - - } elseif { [regexp "^${key}(\\*?)," "$keys," match reverse] } { - # if this was already the first key, then reverse order - if { $reverse eq "*" } { - regsub "\\*," "$keys," "," keys - } else { - regsub "," "$keys," "*," keys - } - regsub ",$" $keys "" keys - return $keys - } else { - regsub ",$key\\*?," "$keys," "," keys - regsub ",$" $keys "" keys - return "$key,$keys" - } -} - -ad_proc -deprecated ad_same_page_link {variable value text {form ""}} { - Makes a link to this page, with a new value for "variable". -} { - if { $form eq "" } { - set form [ns_getform] - } - set url_vars [export_ns_set_vars url $variable $form] - set href "[ad_conn url]?$variable=[ns_urlencode $value]$url_vars" - return [subst {[ns_quotehtml $text]}] -} - -ad_proc -deprecated ad_reverse order { - returns the opposite sort order from the - one it is given. Mostly for columns whose natural - sort order is not the default. -} { - switch [string tolower $order] { - desc {return asc} - asc {return desc} - } - return $order -} - -ad_proc -deprecated ad_custom_load {user_id item_group item item_type} { - load a persisted user customization as saved by - for example table-custom.tcl. -} { - - if { - ![db_0or1row load_user_customization { - select value_type, value - from user_custom - where user_id = :user_id - and item_type = :item_type - and item_group = :item_group - and item = :item - }] - } { - set value {} - } - return $value -} - -ad_proc -deprecated ad_custom_list {user_id item_group item_set item_type target_url custom_url {new_string "new view"}} { - Generates the html fragment for choosing, editing and creating - user customized data -} { - - set items [db_list custom_list { - select item from user_custom - where user_id = :user_id - and item_type = :item_type - and item_group = :item_group - }] - - set break {} - foreach item $items { - if {$item_set eq $item } { - append html "$break$item (edit)" - } else { - append html "$break$item" - } - set break " | " - } - append html "$break ($new_string)\n" - - return $html -} - - -ad_proc -deprecated ad_custom_page_defaults {defaults} { - set the page defaults. If the form is - empty do a returnredirect with the defaults set -} { - set form [ns_getform] - if {$form eq "" - && $defaults ne ""} { - # we did not get a form so set all the variables - # and redirect to set them - set redirect "[ad_conn url]?" - set pre {} - foreach kvp $defaults { - append redirect "$pre[lindex $kvp 0]=[ns_urlencode [lindex $kvp 1]]" - set pre {&} - } - ad_returnredirect $redirect - ad_script_abort - } - - # we have a form so stuff in the ones we dont find. - # should think about how to support lists and ns_set persist too. - foreach kvp $defaults { - if {[ns_set find $form [lindex $kvp 0]] < 0} { - ns_set put $form [lindex $kvp 0] [lindex $kvp 1] - } - } -} - -ad_proc -deprecated ad_custom_form {return_url item_group item} { - sets up the head of a form to feed to /tools/form-custom.tcl -} { - append html "
\n" - if {$return_url ne ""} { - append html "[export_vars -form {return_url}]\n" - } - if {$item_group eq ""} { - set item_group [ad_conn url] - } - set item_original $item - append html "[export_vars -form {item_group item item_original}]\n" - append html "" -} - -ad_proc -deprecated ad_dimensional_settings {define current} { - given a dimensional slider definition this routine returns a form to set the - defaults for the given slider. - - NB...this does not close either the table or the form... -} { - foreach opt $define { - append html "[lindex $opt 1]" - append html "\n" - } - return $html -} - -ad_proc -deprecated ad_table_orderby_sql {datadef orderby order} { - create the order by clause consistent with the orderby and order variables - and the datadef which built the table -} { - set orderclause "order by $orderby $order" - foreach col $datadef { - if {$orderby eq [lindex $col 0] } { - if {[lindex $col 2] ne ""} { - set orderclause [subst [lindex $col 2]] - } - } - } - return $orderclause -} - - # Local variables: # mode: tcl # tcl-indent-level: 4 Index: openacs-4/packages/acs-tcl/tcl/text-html-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/text-html-procs.tcl,v diff -u -N -r1.73 -r1.74 --- openacs-4/packages/acs-tcl/tcl/text-html-procs.tcl 17 Jan 2018 22:38:42 -0000 1.73 +++ openacs-4/packages/acs-tcl/tcl/text-html-procs.tcl 19 Jan 2018 20:56:00 -0000 1.74 @@ -2232,92 +2232,6 @@ return $string } - - -#################### -# -# Legacy stuff -# -#################### - - -ad_proc -deprecated util_striphtml {html} { - Deprecated. Use ad_html_to_text instead. - - @see ad_html_to_text -} { - return [ad_html_to_text -- $html] -} - - -ad_proc -deprecated util_convert_plaintext_to_html { raw_string } { - - Almost everything this proc does can be accomplished with the ad_text_to_html. - Use that proc instead. - -

- - Only difference is that ad_text_to_html doesn't check - to see if the plaintext might in fact be HTML already by - mistake. But we usually don't want that anyway, - because maybe the user wanted a <p> tag in his - plaintext. We'd rather let the user change our - opinion about the text, e.g. html_p = 't'. - - @see ad_text_to_html -} { - if { [regexp -nocase {

} $raw_string] || [regexp -nocase {
} $raw_string] } { - # user was already trying to do this as HTML - return $raw_string - } else { - return [ad_text_to_html -no_links -- $raw_string] - } -} - -ad_proc -deprecated util_maybe_convert_to_html {raw_string html_p} { - - This proc is deprecated. Use ad_convert_to_html - instead. - - @see ad_convert_to_html - -} { - if { $html_p == "t" } { - return $raw_string - } else { - return [ad_text_to_html -- $raw_string] - } -} - -ad_proc -deprecated -warn util_quotehtml { arg } { - This proc does exactly the same as ad_quotehtml. - Use that instead. This one will be deleted eventually. - - @see ad_quotehtml -} { - return [ns_quotehtml $arg] -} - -ad_proc -deprecated util_quote_double_quotes {arg} { - This proc does exactly the same as ad_quotehtml. - Use that instead. This one will be deleted eventually. - - @see ad_quotehtml -} { - return [ns_quotehtml $arg] -} - -ad_proc -deprecated philg_quote_double_quotes {arg} { - This proc does exactly the same as ad_quotehtml. - Use that instead. This one will be deleted eventually. - - @see ad_quotehtml -} { - return [ns_quotehtml $arg] -} - # Local variables: # mode: tcl # tcl-indent-level: 4