%3 ::xowiki::Includelet ::xowiki::Includelet → available_includelets → describe_includelets → glob_clause → html_encode → html_id → html_to_text → js_encode → js_name → listing → locale_clause → parent_id_clause → publish_status_clause → require_YUI_CSS → require_YUI_JS category_clause get_current_folder get_page_order include_head_entries initialize js_name resolve_page_name screen_name tableWidget ::xo::Context ::xo::Context exists_query_parameter export_vars get_all_query_parameter get_parameters initialize original_url_and_query process_query_parameter query_parameter set_query_parameter unset_query_parameter ::xowiki::Includelet->::xo::Context ::xo::ConnectionContext ::xo::ConnectionContext → require → require_package_id_from_url cache cache_exists cache_get cache_set cache_unset eval_as_user exists_form_parameter exists_parameter form_parameter get_all_form_parameter get_parameter get_user_id init lang load_form_parameter load_form_parameter_from_values perconnection_parameter_get_all perconnection_parameter_set_all permission query_parameter requestor require_form_parameter returnredirect role=admin role=all role=app_group_member role=community_member role=creator role=registered_user role=swa role=unregistered_user set_parameter set_user_id unset_parameter ::xo::ConnectionContext->::xo::Context ::xotcl::Object ::xotcl::Object → getExitHandler → setExitHandler → unsetExitHandler __object_configureparameter __timediff abstract ad_doc ad_forward ad_proc asHTML check class db_0or1row db_1row debug destroy_on_cleanup ds extractConfigureArg filter filtersearch forward hasclass init invar isclass ismetaclass ismixin isobject istype log method mixin mset msg parametercmd proc procsearch qn self serialize set_instance_vars_defaults unknown vwait www-show-object ::xo::Context->::xotcl::Object

Class ::xo::ConnectionContext

::xo::ConnectionContext[i] create ... \
           [ -mobile mobile ] \
           [ -requester requester ] \
           [ -url url ] \
           [ -user user ] \
           [ -user_id user_id ]

Defined in

Class Relations

  • class: ::xotcl::Class[i]
  • superclass: ::xo::Context[i]
::xotcl::Class create ::xo::ConnectionContext \
     -superclass ::xo::Context

Methods (to be applied on the object)

  • require (scripted)

     xo::ConnectionContext[i] require

    Testcases:
    test_xo_cc, xotcl-core
    #
    # This is a private method used for low-level connection context
    # creation. This function has to be called either with a valid
    # "-url" when being used outside connection threads.
    #
    set exists_cc [nsf::is object ::xo::cc]
    
    # if we have a connection context and we want to keep it, do
    # nothing and return.
    if {$exists_cc && $keep_cc} {
      return
    }
    
    if {[info exists ::ds_show_p] && [ds_database_enabled_p]} {
      ::xo::dc profile on
    }
    
    if {![info exists url]} {
      #:log "--CONN ns_conn url"
      if {[ns_conn isconnected]} {
        set url [ad_conn url]
      } else {
        set url ""
        ad_log error "fallback to empty url"
      }
    }
    set package_id [:require_package_id_from_url -package_id $package_id $url]
    #:log "--i [self args] URL='$url', pkg=$package_id"
    
    # get locale; TODO at some time, we should get rid of the ad_conn init problem
    if {[ns_conn isconnected]} {
      # This can be called, before ad_conn is initialized.
      # Since it is not possible to pass the user_id and ad_conn barfs
      # when it tries to detect it, we try to get it and reset it later
      ad_try {
        set locale [lang::conn::locale -package_id $package_id]
      } on error {errorMsg} {
        ns_log warning "fall back to locale en_US"
        set locale en_US
      }
    } else {
      set locale [lang::system::locale -package_id $package_id]
    }
    if {!$exists_cc} {
      try {
        :create ::xo::cc  -package_id $package_id  -parameter_declaration $parameter  -user_id $user_id  -actual_query $actual_query  -locale $locale  -url $url
      } on error {errorMsg} {
        if {[nsf::is object ::xo::cc]} {
          ::xo::cc destroy
        }
        return -code error -errorcode $::errorCode -errorinfo $::errorInfo $errorMsg
      }
      ::xo::cc destroy_on_cleanup
    
      # if {[ns_conn isconnected]} {
      #   ns_log notice "XXX ::xo::cc created [ns_conn id] [ns_conn request]"
      #   ::xo::cc set ID [ns_conn id]
      # } else {
      #   ns_log notice "XXX ::xo::cc created without connection"
      #   ::xo::cc set ID UNKNOWN
      # }
      # ::xo::cc proc destroy {args} {
      #   set ID [expr {[info exists :ID] ? ${:ID} : {-}}]
      #   ns_log notice "::xo::cc destroyed ID $ID"
      #   next
      # }
    
      #::xo::show_stack
      #:msg "--cc ::xo::cc created $url [::xo::cc serialize]"
    
    } else {
      #:msg "--cc ::xo::cc reused $url -package_id $package_id"
      ::xo::cc configure  -url $url  -actual_query $actual_query  -locale $locale  -parameter_declaration $parameter
    
      ::xo::cc package_id $package_id
      ::xo::cc set_user_id $user_id
      ::xo::cc process_query_parameter
    }
    
    # simple mobile detection
    ::xo::cc mobile 0
    if {[ns_conn isconnected]} {
      set user_agent [string tolower [ns_set iget [ns_conn headers] User-Agent]]
      ::xo::cc mobile [regexp (android|webos|iphone|ipad) $user_agent]
    }
    
    if {![info exists ::ad_conn(charset)]} {
      set ::ad_conn(charset) [lang::util::charset_for_locale $locale]
      set ::ad_conn(language) [::xo::cc lang]
      set ::ad_conn(file) ""
    }
  • require_package_id_from_url (scripted)

    #
    # Get package_id from URL in case it is not known. In case, the
    # package_id is known, this method is essentially a no-op, but
    # takes care about ::ad_conn initialization.
    #
    if {$package_id == 0} {
      set node_info [site_node::get_from_url -url $url]
      set package_id [dict get $node_info package_id]
    }
    if {![info exists ::ad_conn(node_id)] && [info exists node_info]} {
      #
      # The following should not be necessary, but is here for
      # cases, where some oacs-code assumes wrongly it is running in a
      # connection thread (e.g. the site master requires to have a
      # node_id and a URL accessible via ad_conn)
      #
      if {![dict exists $node_info node_id]} {
        if {$url eq ""} {
          set url [lindex [site_node::get_url_from_object_id -object_id $package_id] 0]
        }
        set node_info [site_node::get_from_url -url $url]
      }
      set ::ad_conn(node_id) [dict get $node_info node_id]
      set ::ad_conn(url) $url
      set ::ad_conn(extra_url) [string range $url [string length [dict get $node_info url]] end]
    }
    return $package_id

Methods (to be applied on instances)

  • cache (scripted)

    set key :cache($cmd)
    if {![info exists $key]} {set $key [:uplevel $cmd]}
    return [set $key]
  • cache_exists (scripted)

    return [info exists :cache($cmd)]
  • cache_get (scripted)

    return [set :cache($cmd)]
  • cache_set (scripted)

    return [set :cache($cmd$value]
  • cache_unset (scripted)

    return [unset :cache($cmd)]
  • eval_as_user (scripted, public)

     <instance of xo::ConnectionContext[i]> eval_as_user \
        [ -user_id user_id ] cmd

    Run a command as the specified different user. Essentially, this method updates xo::cc and the ad_conn array array with the specified user, runs the command and resets the user to the previous value.

    Switches:
    -user_id (optional, integer)
    switch temporarily to this user
    Parameters:
    cmd (required)
    command to be exevuted

    Testcases:
    create_test_items
    #ns_log notice "RUN AS USER $user_id $cmd"
    set result ""
    set current_user_id [:get_user_id]
    try  {
      :set_user_id $user_id
      :uplevel $cmd
    } on ok {r} {
      set result $r
    } finally {
      :set_user_id $current_user_id
    }
    return $result
  • exists_form_parameter (scripted)

    :require_form_parameter
    info exists :form_parameter($name)
  • exists_parameter (scripted)

    info exists :perconnectionparam($name)
  • form_parameter (scripted)

     <instance of xo::ConnectionContext[i]> form_parameter

    Testcases:
    create_workflow_with_instance, xowf, xowiki_test_cases
    :require_form_parameter
    
    set name $spec
    regexp {^([^:]+):(.*)$} $spec . name constraint
    
    if {[info exists :form_parameter($name)]} {
      if {[info exists :form_parameter_multiple($name)]} {
        set value [set :form_parameter($name)]
      } else {
        set value [lindex [set :form_parameter($name)] 0]
      }
      if {[info exists constraint]} {
        set r [xo::validate_parameter_constraints $name $constraint $value]
        if {$r ne $value} {
          ns_log notice "converting value checker: form parameter validate <$spec> -> '$value' -> '$r'"
          set value $r
        }
      } else {
        #:msg "FORM_PARAMETER spec <$spec> no constraint -> '$value'"
      }
      return $value
    } else {
      return $default
    }
  • get_all_form_parameter (scripted)

     <instance of xo::ConnectionContext[i]> get_all_form_parameter

    Testcases:
    xowiki_test_cases, xowiki, create_form_with_form_instance
    :require_form_parameter
    return [array get :form_parameter]
  • get_parameter (scripted)

     <instance of xo::ConnectionContext[i]> get_parameter

    Testcases:
    xowiki_test_cases, xowiki, link_tests
    return [expr {[info exists :perconnectionparam($name)]
                  ? [set :perconnectionparam($name)]
                  : $default}]
  • get_user_id (scripted)

    #
    # If the untrusted user_id exists, return it. This will return
    # consistently the user_id also in situations, where the login
    # cookie was expired. If no untrusted_user_id exists Otherwise
    # (maybe in a remoting setup), return the user_id.
    #
    if {[info exists :untrusted_user_id]} {
      return ${:untrusted_user_id}
    }
    return ${:user_id}
  • init (scripted)

    :set_user_id ${:user_id}
    set pa [expr {[ns_conn isconnected] ? [ad_conn peeraddr] : "nowhere"}]
    
    if {${:user_id} != 0} {
      set :requester ${:user_id}
    } else {
      #
      # For requests bypassing the ordinary connection setup
      # (resources in oacs 5.2+) we have to get the user_id by
      # ourselves.
      #
      ad_try {
        set cookie_list [ad_get_signed_cookie_with_expr "ad_session_id"]
        set cookie_data [split [lindex $cookie_list 0] {,}]
        set untrusted_user_id [lindex $cookie_data 1]
        set :requester $untrusted_user_id
      } on error {errorMsg } {
        set :requester 0
      }
    }
    
    # if user not authorized, use peer address as requester key
    if {${:requester} == 0} {
      set :requester $pa
      set :user "client from $pa"
    } else {
      set user_url [acs_community_member_admin_url -user_id ${:requester}]
      set :user "<a href='$user_url'>${:requester}</a>"
    }
    #:log "--i requester = ${:requester}"
    
    :process_query_parameter
  • lang (scripted)

    return [string range [:locale] 0 1]
  • load_form_parameter (scripted)

    if {[ns_conn isconnected] && [ns_conn method] eq "POST"} {
      :load_form_parameter_from_values [ns_set array [ns_getform]]
    } else {
      array set :form_parameter {}
    }
  • load_form_parameter_from_values (scripted)

    foreach {att value} $values {
      # For some unknown reasons, Safari 3.* returns sometimes
      # entries with empty names... We ignore these for now
      if {$att eq ""} continue
      if {[info exists :form_parameter($att)]} {
        set :form_parameter_multiple($att) 1
      }
      lappend :form_parameter($att$value
    }
  • mobile (setter)

     <instance of xo::ConnectionContext[i]> mobile

    Testcases:
    create_workflow_with_instance, xowf
  • perconnection_parameter_get_all (scripted)

    array get :perconnectionparam
  • perconnection_parameter_set_all (scripted)

    unset -nocomplain :perconnectionparam
    array set :perconnectionparam $pairs
  • permission (scripted, public)

     <instance of xo::ConnectionContext[i]> permission \
        -object_id object_id  -privilege privilege  [ -party_id party_id ]

    Call ::permission::permission_p but avoid multiple calls in the same request through caching in the connection context

    Switches:
    -object_id (required, integer)
    -privilege (required)
    -party_id (optional, integer)

    Testcases:
    xowiki_test_cases
    if {![info exists party_id]} {
      set party_id ${:user_id}
    }
    # :log "--  context permission user_id=$party_id uid=[::xo::cc user_id]"  "untrusted=[::xo::cc set untrusted_user_id]"
    if {$party_id == 0} {
      set granted [permission::permission_p -no_login -party_id $party_id  -object_id $object_id  -privilege $privilege]
      #:msg "--p lookup $key ==> $granted uid=${:user_id} uuid=${:untrusted_user_id}"
      if {$granted || ${:user_id} == ${:untrusted_user_id}} {
        return $granted
      }
      # The permission is not granted for the public.
      # We force the user to login
      #:log "-- require login"
      #auth::require_login
      return 0
    }
    
    #:msg "--p lookup $key"
    return [permission::permission_p -no_login  -party_id $party_id  -object_id $object_id  -privilege $privilege]
    #:log "--  context return [set :$key]"
    #set :$key
  • query_parameter (scripted, public)

     <instance of xo::ConnectionContext[i]> query_parameter __spec \
        [ default ]

    Get query parameter with default and optional value constraints. In case the value check for the query parameter fails, and no further precautions are performed (::aa_test_noabort is set), the method raises an exception with "ad_return_complaint" and aborts the script.

    Parameters:
    __spec (required)
    has the formname or name:value_constraint
    default (optional)
    default value
    Returns:
    actual value of the query parameter

    Testcases:
    api__context, test_xo_cc, path_resolve
    #
    # Try to split up provided "__spec" argument into name and
    # value constraint components.
    #
    set __name $__spec
    regexp {^([^:]+):(.*)$} $__spec . __name constraint
    
    if {[:exists_parameter $__name]} {
      set value [:get_parameter $__name]
    } else {
      set value [next $__name $default]
    }
    #
    # If we have a value-constraint, we check for empty values only in
    # cases, where multiplicity is specified. This means effectively
    # that the default multiplicity is "0..1".
    #
    if {[info exists constraint]} {
      set r [xo::validate_parameter_constraints $__name $constraint $value]
      if {$r ne $value} {
        ns_log notice "converting value checker: query parameter <$__spec> -> '$value' -> '$r'"
        set value $r
      }
    }
    return $value
  • requester (setter)

  • requestor (scripted)

    #
    # Helper method to ease migration to the name without the spelling
    # error.
    #
    ad_log_deprecated method "... requestor" "... requester"
    return [expr {[info exists :requester] ? ${:requester} : ${:requester}}]
  • require_form_parameter (scripted)

    if {![info exists :form_parameter]} {
      :load_form_parameter
    }
  • returnredirect (scripted)

     <instance of xo::ConnectionContext[i]> returnredirect

    Testcases:
    xowiki_test_cases, xowiki
    #:log "--rp"
    set :__continuation [expr {$allow_complete_url
                                 ? [list ad_returnredirect -allow_complete_url $url]
                                 : [list ad_returnredirect $url]}]
    return ""
  • role=admin (scripted)

    return [:permission -object_id $package_id -privilege admin -party_id $user_id]
  • role=all (scripted)

    return 1
  • role=app_group_member (scripted)

    return [:cache [list application_group::contains_party_p  -party_id $user_id  -package_id $package_id]]
  • role=community_member (scripted)

    if {[info commands ::dotlrn_community::get_community_id] ne ""} {
      set community_id [:cache [list [dotlrn_community::get_community_id -package_id $package_id]]]
      if {$community_id ne ""} {
        return [:cache [list dotlrn::user_is_community_member_p  -user_id $user_id  -community_id $community_id]]
      }
    }
    return 0
  • role=creator (scripted)

    $object instvar creation_user
    return [expr {$creation_user == $user_id}]
  • role=registered_user (scripted)

    return [expr {$user_id != 0}]
  • role=swa (scripted)

    return [:cache [list acs_user::site_wide_admin_p -user_id $user_id]]
  • role=unregistered_user (scripted)

    return [expr {$user_id == 0}]
  • set_parameter (scripted)

     <instance of xo::ConnectionContext[i]> set_parameter

    Testcases:
    create_workflow_with_instance, xowf
    set key [list get_parameter $name]
    if {[:cache_exists $key]} {:cache_unset $key}
    set :perconnectionparam($name$value
  • set_user_id (scripted)

    if {$user_id == -1} {  ;# not specified
      if {[info exists ::ad_conn(user_id)]} {
        set :user_id [ad_conn user_id]
        ad_try {
          set :untrusted_user_id [ad_conn untrusted_user_id]
        } on error {errorMsg} {
          set :untrusted_user_id ${:user_id}
        }
      } else {
        set :user_id 0
        set :untrusted_user_id 0
        array set ::ad_conn [list user_id $user_id untrusted_user_id $user_id session_id ""]
      }
    } else {
      set :user_id $user_id
      set :untrusted_user_id $user_id
      if {![info exists ::ad_conn(user_id)]} {
        array set ::ad_conn [list user_id $user_id untrusted_user_id $user_id session_id ""]
      }
    }
  • unset_parameter (scripted)

    set key [list get_parameter $name]
    if {[:cache_exists $key]} {:cache_unset $key}
    unset -nocomplain :perconnectionparam($name)
  • url (setter)

     <instance of xo::ConnectionContext[i]> url

    Testcases:
    create_workflow_with_instance, xowf, xowiki_test_cases
  • user (setter)

  • user_id (setter)

     <instance of xo::ConnectionContext[i]> user_id

    Testcases:
    xotcl_core_tutorial_2, xotcl-core, create_workflow_with_instance, package_normalize_path, xowiki_test_cases, link_tests, slot_interactions, path_resolve, create_form_with_form_instance