Index: openacs-4/packages/xotcl-core/xotcl-core.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/xotcl-core.info,v diff -u -N -r1.47.2.1 -r1.47.2.2 --- openacs-4/packages/xotcl-core/xotcl-core.info 18 Jun 2008 06:51:18 -0000 1.47.2.1 +++ openacs-4/packages/xotcl-core/xotcl-core.info 20 Jun 2008 08:25:41 -0000 1.47.2.2 @@ -8,10 +8,10 @@ t xotcl - + Gustaf Neumann XOTcl library functionality (e.g. thread handling, online documentation, Generic Form and List Classes) - 2008-04-05 + 2008-03-14 Gustaf Neumann, WU Wien This component contains some core functionality for OACS applications using XOTcl. It includes @@ -41,7 +41,7 @@ BSD-Style 0 - + Index: openacs-4/packages/xotcl-core/tcl/01-debug-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/01-debug-procs.tcl,v diff -u -N -r1.25.2.2 -r1.25.2.3 --- openacs-4/packages/xotcl-core/tcl/01-debug-procs.tcl 19 Jun 2008 08:45:26 -0000 1.25.2.2 +++ openacs-4/packages/xotcl-core/tcl/01-debug-procs.tcl 20 Jun 2008 08:25:41 -0000 1.25.2.3 @@ -75,7 +75,7 @@ if {[regexp {^::([^:]+)::} $object_type _ head]} { set tail [namespace tail $object_type] set pretty_name "#$head.$tail-$name#" - #my log "--created pretty_name = $pretty_name" + my log "--created pretty_name = $pretty_name" } else { error "Cannot determine automatically message key for pretty name. \ Use namespaces for classes" @@ -169,14 +169,9 @@ ::xotcl::Object instproc debug msg { ns_log debug "[self] [self callingclass]->[self callingproc]: $msg" } -::xotcl::Object instproc msg {{-html false} msg} { +::xotcl::Object instproc msg msg { if {[ns_conn isconnected]} { - set msg "$msg ([self] [self callingclass]->[self callingproc])" - if {$html} { - util_user_message -html -message $msg - } else { - util_user_message -message $msg - } + util_user_message -message "$msg ([self] [self callingclass]->[self callingproc])" } } ::xotcl::Object instproc qn query_name { Index: openacs-4/packages/xotcl-core/tcl/05-db-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/05-db-procs.tcl,v diff -u -N -r1.58.2.9 -r1.58.2.10 --- openacs-4/packages/xotcl-core/tcl/05-db-procs.tcl 19 Jun 2008 08:45:26 -0000 1.58.2.9 +++ openacs-4/packages/xotcl-core/tcl/05-db-procs.tcl 20 Jun 2008 08:25:41 -0000 1.58.2.10 @@ -233,7 +233,7 @@ switch -- $type { string { set type text } long_text { set type text } - date { set type "timestamp with time zone" } + date { set type timestampz } ltree { set type [expr {[::xo::db::has_ltree] ? "ltree" : "text" }] } } return $type @@ -362,7 +362,6 @@ {security_inherit_p t} {auto_save false} {with_table true} - {sql_package_name} } -ad_doc { ::xo::db::Class is a meta class for interfacing with acs_object_types. acs_object_types are instances of this meta class. The meta class defines @@ -374,13 +373,6 @@ ::xo::db::Class set __default_superclass ::xo::db::Object ;# will be supported in XOTcl 1.6 - ::xo::db::Class proc namespace_head {name} { - if {[regexp {^(::)?([^:]+)::} $name _ colons head]} { - return $head - } - return "" - } - # # Define an XOTcl interface for creating new object types # @@ -527,7 +519,6 @@ -pretty_name $pretty_name \ -id_column $id_column \ -table_name $table_name \ - -sql_package_name [namespace tail $classname] \ -noinit } else { #my log "--db we have a class $classname" @@ -854,11 +845,7 @@ my log "We cannot handle object_name = '$object_name' in this version" return } - # - # Object names have the form of e.g. ::xo::db::apm_parameter. - # Therefore, we use the namspace tail as sql_package_name. - # - set package_name [my sql_package_name [namespace tail [self]]] + set package_name [namespace tail [self]] set sql_command [my generate_psql $package_name $object_name] set proc_body [my generate_proc_body] @@ -1013,8 +1000,7 @@ -table_name $table_name \ -id_column $id_column \ -abstract_p $abstract_p \ - -name_method $name_method \ - -package_name [my sql_package_name] + -name_method $name_method } ::xo::db::Class ad_instproc drop_object_type {{-cascade true}} { @@ -1133,25 +1119,17 @@ my check_default_values set table_name_error_tail "" set id_column_error_tail "" - my instvar sql_package_name - - if {![my exists sql_package_name]} { - set sql_package_name [::xo::db::Class namespace_head [self]] - my log "-- sql_package_name of [self] is '$sql_package_name'" - } - if {[string length $sql_package_name] > 31} { - error "SQL package_name '$sql_package_name' can be maximal 31 characters long!" - } - if {$sql_package_name eq ""} { - error "Cannot determine SQL package_name. Please specify it explicitely!" - } - if {![my exists table_name]} { - set tail [namespace tail [self]] - my set table_name [string tolower ${sql_package_name}_$tail] - set table_name_error_tail ", or use different namespaces/class names" + if {[regexp {^::([^:]+)::} [self] _ head]} { + set tail [namespace tail [self]] + my set table_name [string tolower ${head}_$tail] + set table_name_error_tail ", or use different namespaces/class names" + #my log "-- created table_name '[my table_name]'" + } else { + error "Cannot determine automatically table name for class [self]. \ + Use namespaces for classes." + } } - if {![my exists id_column]} { my set id_column [string tolower [namespace tail [self]]]_id set id_column_error_tail ", or use different class names" Index: openacs-4/packages/xotcl-core/tcl/06-param-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/06-param-procs.tcl,v diff -u -N -r1.6.2.3 -r1.6.2.4 --- openacs-4/packages/xotcl-core/tcl/06-param-procs.tcl 18 Jun 2008 06:51:18 -0000 1.6.2.3 +++ openacs-4/packages/xotcl-core/tcl/06-param-procs.tcl 20 Jun 2008 08:25:42 -0000 1.6.2.4 @@ -312,7 +312,7 @@ -sql [::xo::db::apm_parameter instance_select_query] \ -object_class ::xo::db::apm_parameter \ -as_ordered_composite false -named_objects true -destroy_on_cleanup false - ns_log notice "--p got [llength [::xo::db::apm_parameter info instances]] parameters" + #ns_log debug "--p got [llength [::xo::db::apm_parameter info instances]] parameters" #foreach p [::xo::db::apm_parameter info instances] { ns_log notice [$p serialize] } parameter proc initialize_parameters {} { @@ -325,7 +325,7 @@ where p.parameter_id = v.parameter_id and coalesce(attr_value,'') <> coalesce(p.default_value,'') } { - ns_log notice "--p $parameter_id $package_key $package_id $parameter_name <$attr_value>" + ns_log debug "--p $parameter_id $package_key $package_id $parameter_name <$attr_value>" $parameter_id set_per_package_instance_value $package_id $attr_value } } @@ -403,4 +403,4 @@ # $p save # $p delete -} \ No newline at end of file +} Index: openacs-4/packages/xotcl-core/tcl/40-thread-mod-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/40-thread-mod-procs.tcl,v diff -u -N -r1.8.2.1 -r1.8.2.2 --- openacs-4/packages/xotcl-core/tcl/40-thread-mod-procs.tcl 18 Jun 2008 06:51:18 -0000 1.8.2.1 +++ openacs-4/packages/xotcl-core/tcl/40-thread-mod-procs.tcl 20 Jun 2008 08:25:42 -0000 1.8.2.2 @@ -97,9 +97,16 @@ } ################## main thread support ################## +#::xotcl::RecreationClass create ::xotcl::THREAD \ +# -instrecreate 1 \ +# -parameter {{persistent 0}} + Class create ::xotcl::THREAD \ -parameter {{persistent 0} {lightweight 0}} +#Class create ::xotcl::THREAD \ +# -parameter {{persistent 0}} + ::xotcl::THREAD instproc check_blueprint {} { if {![[self class] exists __blueprint_checked]} { if {[string first ::xotcl::THREAD [ns_ictl get]] == -1} { @@ -110,9 +117,7 @@ } ::xotcl::THREAD instproc init cmd { - if {$cmd eq "-noinit"} {return} my instvar initcmd - #ns_log notice "+++ THREAD cmd='$cmd', epoch=[ns_ictl epoch]" if {![ns_ictl epoch]} { #ns_log notice "--THREAD init [self] no epoch" Index: openacs-4/packages/xotcl-core/tcl/context-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/context-procs.tcl,v diff -u -N -r1.33.2.4 -r1.33.2.5 --- openacs-4/packages/xotcl-core/tcl/context-procs.tcl 18 Jun 2008 06:51:18 -0000 1.33.2.4 +++ openacs-4/packages/xotcl-core/tcl/context-procs.tcl 20 Jun 2008 08:25:42 -0000 1.33.2.5 @@ -189,13 +189,12 @@ #my log "--CONN ns_conn url" set url [ns_conn url] } - #my log "--i [self args] URL='$url', pkg=$package_id" + #my log "--i [self args] URL='$url'" # create connection context if necessary if {$package_id == 0} { array set "" [site_node::get_from_url -url $url] set package_id $(package_id) - #my log "--i setting pkg tp $package_id" } # get locale; TODO at some time, we should get rid of the ad_conn init problem @@ -218,20 +217,16 @@ -actual_query $actual_query \ -locale $locale \ -url $url - #::xo::show_stack #my log "--cc ::xo::cc created $url [::xo::cc serialize]" ::xo::cc destroy_on_cleanup } else { - #my log "--cc ::xo::cc reused $url -package_id $package_id" + #my log "--cc ::xo::cc reused $url" ::xo::cc configure \ + -package_id $package_id \ -url $url \ -actual_query $actual_query \ -locale $locale \ [list -parameter_declaration $parameter] - #if {$package_id ne ""} { - # ::xo::cc package_id $package_id - #} - ::xo::cc package_id $package_id ::xo::cc set_user_id $user_id ::xo::cc process_query_parameter } @@ -449,4 +444,6 @@ return $query } -} \ No newline at end of file + +} + Index: openacs-4/packages/xotcl-core/tcl/cr-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/cr-procs.tcl,v diff -u -N -r1.16.2.2 -r1.16.2.3 --- openacs-4/packages/xotcl-core/tcl/cr-procs.tcl 18 Jun 2008 06:51:18 -0000 1.16.2.2 +++ openacs-4/packages/xotcl-core/tcl/cr-procs.tcl 20 Jun 2008 08:25:42 -0000 1.16.2.3 @@ -594,7 +594,7 @@ @param with_subtypes return subtypes as well @param count return the query for counting the solutions @param folder_id parent_id - @param publish_status one of 'live', 'ready', or 'production' + @param publish_status one of 'live', 'ready' or 'production' @param base_table typically automatic view, must contain title and revision_id @return sql query } { @@ -824,7 +824,7 @@ lappend values $v } return "insert into [my set table_name]i ([join $attributes ,]) \ - values (:[join $values ,:])" + values ([join $values ,])" } CrItem instproc fix_content {{-only_text false} revision_id content} { @@ -873,8 +873,8 @@ set sql "update [$domain table_name] \ set $att = :value \ where [$domain id_column] = $revision_id" - db_dml [my qn update_attribute-$att] $sql } + db_dml [my qn update_attribute-$att] $sql } } Index: openacs-4/packages/xotcl-core/tcl/http-client-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/http-client-procs.tcl,v diff -u -N -r1.7.2.2 -r1.7.2.3 --- openacs-4/packages/xotcl-core/tcl/http-client-procs.tcl 18 Jun 2008 06:51:18 -0000 1.7.2.2 +++ openacs-4/packages/xotcl-core/tcl/http-client-procs.tcl 20 Jun 2008 08:25:42 -0000 1.7.2.3 @@ -1,7 +1,5 @@ ad_library { - - XOTcl implementation for synchronous and asynchronous - HTTP and HTTPS requests + XOTcl implementation for synchronous and asynchronous HTTP and HTTPs requests @author Gustaf Neumann, Stefan Sobernig @creation-date 2007-10-05 @@ -11,11 +9,10 @@ namespace eval ::xo { # # Defined classes - # 1) HttpCore (common base class) - # 2) HttpRequest (for blocking requests + timeout support) - # 3) AsyncHttpRequest (for non-blocking requests + timeout support) - # 4) HttpRequestTrace (mixin class) - # 5) Tls (mixin class, applicable to various protocols) + # 1) HttpRequest + # 2) AsyncHttpRequest + # 3) HttpRequestTrace (mixin class) + # 4) Tls (mixin class, applicable to various protocols) # ###################### # @@ -41,27 +38,9 @@ # set r [::xo::HttpRequest new \ # -url http://yourhost.yourdomain/yourpath \ # -post_data [export_vars {var1 var2}] \ - # -content_type application/x-www-form-urlencoded] + # -content_type application/x-www-form-urlencoded \ + # ] # - # More recently, we added timeout support for blocking http - # requests. By passing a timeout parameter, you gain control - # on the total roundtrip time (in milliseconds, ms): - # - # set r [::xo::HttpRequest new \ - # -url http://www.openacs.org/ \ - # -timeout 1500] - # - # Please, make sure that you use a recent distribution of tclthread - # ( > 2.6.5 ) to have the blocking-timeout feature working - # safely. This newly introduced feature makes use of advanced thread - # synchronisation offered by tclthread that needed to be fixed in - # tclthread <= 2.6.5. At the time of this writing, there was no - # post-2.6.5 release of tclthread, hence, you are required to obtain a - # CVS snapshot, dating at least 2008-05-23. E.g.: - # - # cvs -z3 -d:pserver:anonymous@tcl.cvs.sourceforge.net:/cvsroot/tcl co \ - # -D 20080523 -d thread2.6.5~20080523 thread - # # Provided that the Tcl module tls (see e.g. http://tls.sourceforge.net/) # is available and can be loaded via "package require tls" into # the aolserver, you can use both TLS/SSL secured or unsecured requests @@ -74,7 +53,7 @@ # # 2 AsyncHttpRequest # - # AsyncHttpRequest is a subclass for HttpCore implementing + # AsyncHttpRequest is a subclass for HttpRequest implementing # asynchronous HTTP requests without vwait (vwait causes # stalls on aolserver). AsyncHttpRequest requires to provide a listener # or callback object that will be notified upon success or failure of @@ -99,17 +78,9 @@ # the other upon failure or cancellation (done). # # ::bgdelivery do Object ::listener \ - # -proc start_request {payload obj} { - # my log "request $obj started" - # } -proc request_data {payload obj} { - # my log "partial or complete post" - # } -proc start_reply {payload obj} { - # my log "reply $obj started" - # } -proc reply_data {payload obj} { - # my log "partial or complete delivery" - # } -proc success {data obj} { - # my log "Asynchronous request successfully completed" - # } -proc failure {reason obj} { + # -proc deliver {payload obj} { + # my log "Asynchronous request suceeded!" + # } -proc done {reason obj} { # my log "Asynchronous request failed: $reason" # } # @@ -125,109 +96,40 @@ # # 3 HttpRequestTrace # - # HttpRequestTrace can be used to trace one or all requests. + # HttpRequestTrace can be used to trace the one or all requests. # If activated, the class writes protocol data into # /tmp/req-. # # Use # - # ::xo::HttpCore instmixin add ::xo::HttpRequestTrace + # ::xo::HttpRequest instmixin add ::xo::HttpRequestTrace # # to activate trace for all requests, # or mixin the class into a single request to trace it. # - Class create HttpCore \ - -slots { - Attribute host - Attribute protocol -default "http" - Attribute port - Attribute path -default "/" - Attribute url - Attribute post_data -default "" - Attribute content_type -default "text/plain" - Attribute request_header_fields -default {} - Attribute user_agent -default "xohttp/0.2" + Class create HttpRequest \ + -parameter { + {host} + {protocol http} + {port} + {path /} + {url} + {post_data ""} + {content_type text/plain} + {request_manager} + {request_header_fields {}} + {user_agent xohttp/0.1} } - # Provide for mapping from HTTP charset encoding labels - # to Tcl-specific ones (see http://naviserver.cvs.sourceforge.net/naviserver/naviserver/nsd/encoding.c?view=markup) - - HttpCore array set http_to_tcl_encodings { - iso-2022-jp iso2022-jp - iso-2022-kr iso2022-kr - iso-8859-1 iso8859-1 - iso-8859-2 iso8859-2 - iso-8859-3 iso8859-3 - iso-8859-4 iso8859-4 - iso-8859-5 iso8859-5 - iso-8859-6 iso8859-6 - iso-8859-7 iso8859-7 - iso-8859-8 iso8859-8 - iso-8859-9 iso8859-9 - korean ksc5601 - ksc_5601 ksc5601 - mac macRoman - mac-centeuro macCentEuro - mac-centraleupore macCentEuro - mac-croatian macCroatian - mac-cyrillic macCyrillic - mac-greek macGreek - mac-iceland macIceland - mac-japan macJapan - mac-roman macRoman - mac-romania macRomania - mac-thai macThai - mac-turkish macTurkish - mac-ukraine macUkraine - maccenteuro macCentEuro - maccentraleupore macCentEuro - maccroatian macCroatian - maccyrillic macCyrillic - macgreek macGreek - maciceland macIceland - macintosh macRoman - macjapan macJapan - macroman macRoman - macromania macRomania - macthai macThai - macturkish macTurkish - macukraine macUkraine - shift_jis shiftjis - us-ascii ascii - windows-1250 cp1250 - windows-1251 cp1251 - windows-1252 cp1252 - windows-1253 cp1253 - windows-1254 cp1254 - windows-1255 cp1255 - windows-1256 cp1256 - windows-1257 cp1257 - windows-1258 cp1258 - x-mac macRoman - x-mac-centeuro macCentEuro - x-mac-centraleupore macCentEuro - x-mac-croatian macCroatian - x-mac-cyrillic macCyrillic - x-mac-greek macGreek - x-mac-iceland macIceland - x-mac-japan macJapan - x-mac-roman macRoman - x-mac-romania macRomania - x-mac-thai macThai - x-mac-turkish macTurkish - x-mac-ukraine macUkraine - x-macintosh macRoman - } - - HttpCore instproc set_default_port {protocol} { + HttpRequest instproc set_default_port {protocol} { switch $protocol { http {my set port 80} https {my set port 443} } } - HttpCore instproc parse_url {} { + HttpRequest instproc parse_url {} { my instvar protocol url host port path if {[regexp {^(http|https)://([^/]+)(/.*)?$} $url _ protocol host path]} { # Be friendly and allow strictly speaking invalid urls @@ -240,29 +142,21 @@ } } - HttpCore instproc open_connection {} { + HttpRequest instproc open_connection {} { my instvar host port S - set S [socket -async $host $port] + set S [socket $host $port] } - HttpCore instproc set_encoding { + HttpRequest instproc set_encoding { {-text_translation {auto binary}} content_type } { # - # for text, use translation with optional encodings, - # else set translation binary + # for text, use translation with optional encodings, else set translation binary # if {[string match "text/*" $content_type]} { if {[regexp {charset=([^ ]+)$} $content_type _ encoding]} { - [self class] instvar http_to_tcl_encodings - set enc [string tolower $encoding] - if {[info exists http_to_tcl_encodings($enc)]} { - set enc $http_to_tcl_encodings($enc) - } - fconfigure [my set S] \ - -translation $text_translation \ - -encoding $enc + fconfigure [my set S] -translation $text_translation -encoding [string tolower $encoding] } else { fconfigure [my set S] -translation $text_translation } @@ -271,7 +165,7 @@ } } - HttpCore instproc init {} { + HttpRequest instproc init {} { my instvar S post_data host port protocol my destroy_on_cleanup my set meta [list] @@ -299,10 +193,6 @@ my cancel "error during open connection via $protocol to $host $port: $err" return } - } - - HttpCore instproc send_request {} { - my instvar S post_data host if {[catch { set method [expr {$post_data eq "" ? "GET" : "POST"}] puts $S "$method [my path] HTTP/1.0" @@ -316,62 +206,61 @@ } my $method } err]} { - my cancel "error send $host [my port]: $err" + my cancel "error send $host $port: $err" return } } - HttpCore instproc GET {} { + HttpRequest instproc GET {} { my instvar S puts $S "" - my request_done + my query_done } - HttpCore instproc POST {} { + HttpRequest instproc POST {} { my instvar S post_data puts $S "Content-Length: [string length $post_data]" puts $S "Content-Type: [my content_type]" puts $S "" + #fconfigure $S -translation {auto binary} my set_encoding [my content_type] - my send_POST_data - } - HttpCore instproc send_POST_data {} { - my instvar S post_data puts -nonewline $S $post_data - my request_done + my query_done } - HttpCore instproc request_done {} { + HttpRequest instproc query_done {} { my instvar S flush $S - my reply_first_line + my received_first_line } - - HttpCore instproc close {} { - my debug "--- closing socket" + HttpRequest instproc notify {method arg} { + if {[my exists request_manager]} { + [my request_manager] $method $arg [self] + } + } + HttpRequest instproc cancel {reason} { + my log "--- $reason" catch {close [my set S]} + my notify done $reason } - HttpCore instproc cancel {reason} { - my debug "--- $reason" - my close + HttpRequest instproc finish {} { + catch {close [my set S]} + my log "--- [my host] [my port] [my path] has finished" + my notify deliver [my set data] } - - HttpCore instproc finish {} { - my close - my debug "--- [my host] [my port] [my path] has finished" - } - HttpCore instproc getLine {var} { + HttpRequest instproc getLine {var} { my upvar $var response my instvar S set n [gets $S response] if {[eof $S]} { my log "--premature eof" return -2 } - if {$n == -1} {my debug "--input pending, no full line"; return -1} + if {$n == -1} {my log "--input pending, no full line"; return -1} + #my log "got $response" return $n } - HttpCore instproc reply_first_line {} { + HttpRequest instproc received_first_line {} { my instvar S status_code fconfigure $S -translation crlf set n [my getLine response] @@ -381,24 +270,24 @@ } if {[regexp {^HTTP/([0-9.]+) +([0-9]+) *} $response _ \ responseHttpVersion status_code]} { - my reply_first_line_done + my received_first_line_done } else { my log "--unexpected response '$response'" my cancel unexpected-response } } - HttpCore instproc reply_first_line_done {} { + HttpRequest instproc received_first_line_done {} { my header } - HttpCore instproc header {} { + HttpRequest instproc header {} { while {1} { set n [my getLine response] switch -exact -- $n { -2 {my cancel premature-eof; return} -1 {continue} 0 {break} default { - #my debug "--header $response" + #my log "--header $response" if {[regexp -nocase {^content-length:(.+)$} $response _ length]} { my set content_length [string trim $length] } elseif {[regexp -nocase {^content-type:(.+)$} $response _ type]} { @@ -410,11 +299,10 @@ } } } - my reply_header_done + my received_header_done } - HttpCore instproc reply_header_done {} { - # we have received the header, including potentially the - # content_type of the returned data + HttpRequest instproc received_header_done {} { + # we have received the header, including potentially the content_type of the returned data my set_encoding [my content_type] if {[my exists content_length]} { my set data [read [my set S] [my set content_length]] @@ -423,282 +311,56 @@ } } - HttpCore instproc set_status {key newStatus {value ""}} { - nsv_set bgdelivery $key [list $newStatus $value] - } - - HttpCore instproc unset_status {key} { - nsv_unset bgdelivery $key - } - - HttpCore instproc exists_status {key} { - return [nsv_exists bgdelivery $key] - } - - HttpCore instproc get_status {key} { - return [lindex [nsv_get bgdelivery $key] 0] - } - - HttpCore instproc get_value_for_status {key} { - return [lindex [nsv_get bgdelivery $key] 1] - } - - - # - # Synchronous (blocking) requests + # Asynchronous requests # - Class HttpRequest -superclass HttpCore -slots { - Attribute timeout -type integer + Class AsyncHttpRequest -superclass HttpRequest -parameter { + {timeout 10000} } - - HttpRequest instproc init {} { - if {[my exists timeout] && [my timeout] > 0} { - # create a cond and mutex - set cond [thread::cond create] - set mutex [thread::mutex create] - - thread::mutex lock $mutex - - # start the asynchronous request - my log "--a create new ::xo::AsyncHttpRequest" - set req [bgdelivery do -async ::xo::AsyncHttpRequest new \ - -mixin ::xo::AsyncHttpRequest::RequestManager \ - -url [my url] \ - -timeout [my timeout] \ - -post_data [my post_data] \ - -request_header_fields [my request_header_fields] \ - -content_type [my content_type] \ - -user_agent [my user_agent] \ - -condition $cond] - - while {1} { - my set_status $cond COND_WAIT_TIMEOUT - thread::cond wait $cond $mutex [my timeout] - - set status [my get_status $cond] - my log "status after cond-wait $status" - - if {$status ne "COND_WAIT_REFRESH"} break - } - if {$status eq "COND_WAIT_TIMEOUT"} { - my set_status $cond "COND_WAIT_CANCELED" - } - set status_value [my get_value_for_status $cond] - if {$status eq "JOB_COMPLETED"} { - my set data $status_value - } else { - set msg "Timeout-constraint, blocking HTTP request failed. Reason: '$status'" - if {$status_value ne ""} { - append msg " ($status_value)" - } - error $msg - } - thread::cond destroy $cond - thread::mutex unlock $mutex - thread::mutex destroy $mutex - my unset_status $cond - } else { - next;# HttpCore->init() - my send_request - # - # test whether open_connection yielded - # a socket ... - # - if {[my exists S]} { - my send_request - } - } - } - - # - # Asynchronous (non-blocking) requests - # - - Class AsyncHttpRequest -superclass HttpCore -slots { - Attribute timeout -type integer -default 10000 ;# 10 seconds - Attribute request_manager - } - AsyncHttpRequest instproc set_timeout {} { - my log "--a" - my cancel_timeout - my debug "--- setting socket timeout: [my set timeout]" - my set timeout_handle [after [my set timeout] [self] cancel timeout] - } - AsyncHttpRequest instproc cancel_timeout {} { - if {[my exists timeout_handle]} { - after cancel [my set timeout_handle] - } - } - AsyncHttpRequest instproc send_request {} { - my log "--a" - # remove fileevent handler explicitly - fileevent [my set S] writable {} - next - } AsyncHttpRequest instproc init {} { - my log "--a" - my notify start_request - my set_timeout + my set to_identifier [after [my set timeout] [self] cancel timeout] next - # - # test whether open_connection yielded - # a socket ... - # - if {[my exists S]} { - fileevent [my set S] writable [list [self] send_request] - } } - AsyncHttpRequest instproc notify {method {arg ""}} { - if {[my exists request_manager]} { - [my request_manager] $method $arg [self] - } - } AsyncHttpRequest instproc POST {} { if {[my exists S]} {fconfigure [my set S] -blocking false} - fileevent [my set S] writable [list [self] send_POST_data] - my set bytes_sent 0 next } - AsyncHttpRequest instproc send_POST_data {} { - my instvar S post_data bytes_sent - my set_timeout - set l [string length $post_data] - if {$bytes_sent < $l} { - set to_send [expr {$l - $bytes_sent}] - set block_size [expr {$to_send < 4096 ? $to_send : 4096}] - set bytes_sent_1 [expr {$bytes_sent + $block_size}] - set block [string range $post_data $bytes_sent $bytes_sent_1] - my notify request_data $block - puts -nonewline $S $block - set bytes_sent $bytes_sent_1 - } else { - fileevent $S writable "" - my request_done - } - } AsyncHttpRequest instproc cancel {reason} { if {$reason ne "timeout"} { - my cancel_timeout + after cancel [my set to_identifier] } next - my debug "--- canceled for $reason" - my notify failure $reason } AsyncHttpRequest instproc finish {} { - my log "--a" - my cancel_timeout + after cancel [my set to_identifier] next - my debug "--- finished data [my set data]" - my notify success [my set data] } - AsyncHttpRequest instproc request_done {} { - my log "--a" - my notify start_reply - my set_timeout + AsyncHttpRequest instproc query_done {} { my instvar S flush $S fconfigure $S -blocking false - fileevent $S readable [list [self] reply_first_line] + fileevent $S readable [list [self] received_first_line] } - AsyncHttpRequest instproc reply_first_line_done {} { - my log "--a" - my set_timeout - my instvar S - fileevent $S readable [list [self] header] + AsyncHttpRequest instproc received_first_line_done {} { + fileevent [my set S] readable [list [self] header] } - AsyncHttpRequest instproc reply_header_done {} { - my log "--a" - my set_timeout - # we have received the header, including potentially the - # content_type of the returned data + AsyncHttpRequest instproc received_header_done {} { + # we have received the header, including potentially the content_type of the returned data my set_encoding [my content_type] - fileevent [my set S] readable [list [self] receive_reply_data] + fileevent [my set S] readable [list [self] received_data] } - AsyncHttpRequest instproc receive_reply_data {} { - my log "--a" + AsyncHttpRequest instproc received_data {} { my instvar S - my log "JOB receive_reply_data eof=[eof $S]" if {[eof $S]} { my finish } else { - my set_timeout set block [read $S] - my notify reply_data $block my append data $block - #my debug "reveived [string length $block] bytes" + #my log "reveived [string length $block] bytes" } } - # - # Mixin class, used to turn instances of - # AsyncHttpRequest into result callbacks - # in the scope of bgdelivery, realising - # the blocking-timeout feature ... - # - - Class create AsyncHttpRequest::RequestManager \ - -slots { - Attribute condition - } -instproc finalize {obj status value} { - # set the result and do the notify - my instvar condition - # If a job was canceled, the status variable might not exist - # anymore, the condition might be already gone as well. In - # this case, we do not have to perform the cond-notify. - if {[my exists_status $condition] && - [my get_status $condition] eq "COND_WAIT_TIMEOUT"} { - my set_status $condition $status $value - catch {thread::cond notify $condition} - $obj debug "--- destroying after finish" - $obj destroy - } - - } -instproc set_cond_timeout {} { - my instvar condition - if {[my exists_status $condition] && - [my get_status $condition] eq "COND_WAIT_TIMEOUT"} { - my set_status $condition COND_WAIT_REFRESH - catch {thread::cond notify $condition} - } - - } -instproc start_request {payload obj} { - my log "JOB start request $obj" - my set_cond_timeout - - } -instproc request_data {payload obj} { - my log "JOB request data $obj [string length $payload]" - my set_cond_timeout - - } -instproc start_reply {payload obj} { - my log "JOB start reply $obj" - my set_cond_timeout - - } -instproc reply_data {payload obj} { - my log "JOB reply data $obj [string length $payload]" - my set_cond_timeout - - } -instproc success {payload obj} { - my finalize $obj "JOB_COMPLETED" $payload - - } -instproc failure {reason obj} { - my finalize $obj "JOB_FAILED" $reason - - } -instproc init {} { - # register request object as its own request_manager - my request_manager [self] - next - - } -instproc cancel {reason} { - next - my debug "--- destroying after cancel" - my destroy - - } -instproc unknown {method args} { - my log "UNKNOWN $method" - } - # # TLS/SSL support # @@ -768,5 +430,5 @@ # To activate trace for all requests, uncomment the following line. # To trace a single request, mixin ::xo::HttpRequestTrace into the request. # - # HttpCore instmixin add ::xo::HttpRequestTrace + # HttpRequest instmixin add ::xo::HttpRequestTrace } Index: openacs-4/packages/xotcl-core/tcl/ical-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/ical-procs.tcl,v diff -u -N -r1.2.2.1 -r1.2.2.2 --- openacs-4/packages/xotcl-core/tcl/ical-procs.tcl 18 Jun 2008 06:51:18 -0000 1.2.2.1 +++ openacs-4/packages/xotcl-core/tcl/ical-procs.tcl 20 Jun 2008 08:25:42 -0000 1.2.2.2 @@ -13,7 +13,7 @@ importing and exporting single or multiple calendar items in the ical format (see rfc 2445). Currently only the part of ical is implemented, which is used by the mozilla - calendar (Sunbird, or Lightning for Thunderbird). + calendar (sunbird, or the xul-file for thunderbird or firefox). @author Gustaf Neumann } @@ -32,9 +32,6 @@ set TZ [expr {$utc ? "GMT" : ""}] return [clock scan "$year-$month-$day $hour:$min $TZ"] } - ical proc tcl_time_to_utc {time} { - clock format [clock scan $time] -format "%Y%m%dT%H%M%SZ" -gmt 1 - } ical proc clock_to_utc {seconds} { clock format $seconds -format "%Y%m%dT%H%M%SZ" -gmt 1 } @@ -77,320 +74,4 @@ return $text } -} - -namespace eval ::xo { - Class create ::xo::ical::VCALITEM -parameter { - creation_date - last_modified - dtstart - dtstamp - uid - priority - summary - url - description - location - geo - status - } - - ::xo::ical::VCALITEM instproc tag {-tag -conv -value slot} { - if {![info exists tag]} { - set tag [string toupper $slot] - } - if {![info exists value]} { - if {[my exists $slot]} { - set value [my $slot] - } else { - return "" - } - } - if {[info exists conv]} { - return "$tag:[::xo::ical $conv $value]\n" - } else { - return "$tag:$value\n" - } - return "" - } - - ::xo::ical::VCALITEM instproc as_ical {} { - my instvar creation_date last_modified dtstamp - # - # All date/time stamps are provided either by - # the ANSI date (from postgres) or by a date - # which can be processed via clock scan - # - if {![info exists dtstamp]} {set dtstamp $creation_date} - if {![info exists last_modified]} {set last_modified $dtstamp} - - set tcl_stamp [::xo::db::tcl_date $dtstamp tz] - set tcl_creation_date [::xo::db::tcl_date $creation_date tz] - set tcl_last_modified [::xo::db::tcl_date $last_modified tz] - - # status values: - # VEVENT: TENTATIVE, CONFIRMED, CANCELLED - # VTODO: NEEDS-ACTION, COMPLETED, IN-PROCESS, CANCELLED - # VJOURNAL: DRAFT, FINAL, CANCELLED - - set item_type [namespace tail [my info class]] - append t "BEGIN:$item_type\n" \ - [my tag -conv tcl_time_to_utc -value $tcl_creation_date created] \ - [my tag -conv tcl_time_to_utc -value $tcl_last_modified last-modified] \ - [my tag -conv tcl_time_to_utc -value $tcl_stamp dtstamp] \ - [my tag -conv tcl_time_to_utc dtstart] \ - [my tag -conv tcl_time_to_utc dtend] \ - [my tag -conv tcl_time_to_utc completed] \ - [my tag -conv tcl_time_to_utc percent-complete] \ - [my tag uid] \ - [my tag url] \ - [my tag geo] \ - [my tag priority] \ - [my tag location] \ - [my tag status] \ - [my tag -conv text_to_ical description] \ - [my tag -conv text_to_ical summary] \ - [my tag -conv tcl_time_to_utc due] \ - "END:$item_type\n" - return $t - } - # - # VTODO - # - # optional fields, must not occur more than once - # - # class / *completed / *created / *description / *dtstamp / - # *dtstart / *geo / *last-mod / *location / organizer / - # *percent-complete / *priority / recurid / seq / *status / - # *summary / *uid / *url / - # - # optional, but mutual exclusive - # *due / duration / - # - # optional fields, may occur more than once - # - # attach / attendee / categories / comment / contact / - # exdate / exrule / rstatus / related / resources / - # rdate / rrule / x-prop - - Class create ::xo::ical::VTODO -superclass ::xo::ical::VCALITEM -parameter { - due - completed - percent-complete - } - # - # VEVENT - # - # optional fields, must not occur more than once - # - # class / *created / *description / *dtstart / *geo / - # *last-mod / *location / organizer / *priority / - # *dtstamp / seq / *status / *summary / transp / - # *uid / *url / recurid / - # - # dtend or duration may appear, but dtend and duration are mutual exclusive - # *dtend / duration / - # - # optional fields, may occur more than once - # - # attach / attendee / categories / comment / contact / - # exdate / exrule / rstatus / related / resources / - # rdate / rrule / x-prop - # - # just a stub for now - Class create ::xo::ical::VEVENT -superclass ::xo::ical::VCALITEM -parameter { - dtend - } - - # - # This class is designed to be a mixin for an ordered composite - # - Class create ::xo::ical::VCALENDAR -parameter {prodid version method} - ::xo::ical::VCALENDAR instproc as_ical {} { - if {[my exists prodid]} {set prodid "PRODID:[my prodid]\n"} {set prodid ""} - if {[my exists method]} {set method "METHOD:[string toupper [my method]]\n"} {set method ""} - if {[my exists version]} {set version "VERSION:[my version]\n"} {set version "VERSION:2.0\n"} - set t "" - append t "BEGIN:VCALENDAR\n" $prodid $version $method - foreach i [my children] { - append t [$i as_ical] - } - append t "END:VCALENDAR\n" - return $t - } - -} - -namespace eval ::xo { - Class create dav -parameter { - {url /webdav} - {package} - } - - dav ad_instproc unknown {method args} { - Return dav specific connection info similar to ad_conn - } { - my log "--dav unknown called with '$method' <$args>" - switch [llength $args] { - 0 {if {[my exists $method]} {return [my set method]} - return [ad_conn $method] - } - 1 {my set method $args} - default {my log "--dav ignoring <$method> <$args>"} - } - } - - dav ad_instproc set_user_id {} { - Set user_id based on authentication header - } { - set ah [ns_set get [ns_conn headers] Authorization] - if {$ah ne ""} { - # should be something like "Basic 29234k3j49a" - my debug "auth_check authentication info $ah" - # get the second bit, the base64 encoded bit - set up [lindex [split $ah " "] 1] - # after decoding, it should be user:password; get the username - set user [lindex [split [ns_uudecode $up] ":"] 0] - set password [lindex [split [ns_uudecode $up] ":"] 1] - array set auth [auth::authenticate \ - -username $user \ - -authority_id [::auth::get_register_authority] \ - -password $password] - my debug "auth $user $password returned [array get auth]" - if {$auth(auth_status) ne "ok"} { - array set auth [auth::authenticate \ - -email $user \ - -password $password] - if {$auth(auth_status) ne "ok"} { - my debug "auth status $auth(auth_status)" - ns_returnunauthorized - my set user_id 0 - return 0 - } - } - my debug "auth_check user_id='$auth(user_id)'" - ad_conn -set user_id $auth(user_id) - - } else { - # no authenticate header, anonymous visitor - ad_conn -set user_id 0 - ad_conn -set untrusted_user_id 0 - } - my set user_id [ad_conn user_id] - } - - dav ad_instproc initialize {} { - Setup connection object and authenticate user - } { - my instvar uri method urlv destination - ad_conn -reset - set uri [ns_urldecode [ns_conn url]] - set dav_url_regexp "^[my url]" - regsub $dav_url_regexp $uri {} uri - if {$uri eq ""} { - set uri "/" - } - my set_user_id - - set method [string toupper [ns_conn method]] - #my log "--dav conn_setup: uri '$uri' method $method" - set urlv [split [string trimright $uri "/"] "/"] - set destination [ns_urldecode [ns_set iget [ns_conn headers] Destination]] - regsub {https?://[^/]+/} $destination {/} dest - regsub $dav_url_regexp $dest {} destination - #my log "--dav conn_setup: destination = $destination" - } - - dav ad_instproc preauth { args } { - Check if user_id has permission to perform the WebDAV method on - the URI - } { - #my log "--dav preauth args=<$args>" - my instvar user_id - - # Restrict to SSL if required - if { [security::RestrictLoginToSSLP] && ![security::secure_conn_p] } { - ns_returnunauthorized - return filter_return - } - - # set common data for all kind of requests - my initialize - - # for now, require for every user authentification - if {$user_id == 0} { - ns_returnunauthorized - return filter_return - } - - #my log "--dav preauth filter_ok" - return filter_ok - } - - dav ad_instproc register { } { - Register the the aolserver filter and traces. - This method is typically called via *-init.tcl. - } { - set filter_url [my url]* - set url [my url]/* - foreach method { - GET HEAD PUT MKCOL COPY MOVE PROPFIND PROPPATCH - DELETE LOCK UNLOCK - } { - ns_register_filter preauth $method $filter_url [self] - ns_register_proc $method $url [self] handle_request - #my log "--dav ns_register_filter preauth $method $filter_url [self]" - #my log "--dav ns_register_proc $method $url [self] handle_request" - } - } - - dav instproc GET {} { - my instvar uri - my log "--dav handle_request GET method" - #set with_recurrences [ns_queryget with_recurrences 1] - # ... - ns_return 200 text/plain GET-$uri - } - dav instproc PUT {} { - my log "--dav handle_request PUT method [ns_conn content]" - #set calendar_id_list [ns_queryget calendar_id_list 0] - #if {[llength $write_calendar_ids] == 0} { - #ns_return 403 text/plain "no permissions to write to calendar" - #} else { - ns_return 201 text/plain "0 items processed" - #} - } - dav instproc PROPFIND {} { - my log "--dav PROPFIND [ns_conn content]" - ns_return 204 text/xml {} - } - - dav ad_instproc get_package_id {} { - initialize the given package - @return package_id - } { - my instvar uri package - $package initialize -url $uri - #my log "--dav [my package] initialize -url $uri" - return $package_id - } - - dav ad_instproc handle_request { args } { - Process the incoming web-dav request. This method - could be overloaded by the application and - dispatches the HTTP requests. - } { - my instvar uri method user_id - - #my log "--dav handle_request method=$method uri=$uri\ - # userid=$user_id -ns_conn query '[ns_conn query]'" - if {[my exists package]} { - my get_package_id - } - if {[my procsearch $method] ne ""} { - my $method - } else { - ns_return 404 text/plain "not implemented" - } - } -} +} \ No newline at end of file