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) ""
    }

Methods (to be applied on instances)

  • 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
  • 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}]
  • mobile (setter)

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

    Testcases:
    create_workflow_with_instance, xowf
  • 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
  • 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 ""
  • 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
  • url (setter)

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

    Testcases:
    create_workflow_with_instance, xowf, xowiki_test_cases
  • 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