diff options
Diffstat (limited to 'library')
-rwxr-xr-x[-rw-r--r--] | library/encoding/tis-620.enc | 0 | ||||
-rw-r--r-- | library/http/cookiejar.tcl | 745 | ||||
-rw-r--r-- | library/http/effective_tld_names.txt.gz | bin | 0 -> 39188 bytes | |||
-rw-r--r-- | library/http/http.tcl | 121 | ||||
-rw-r--r-- | library/http/idna.tcl | 292 | ||||
-rw-r--r-- | library/http/pkgIndex.tcl | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/af.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/af_za.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/ar.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/ar_in.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/ar_jo.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/ar_lb.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/ar_sy.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/be.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/bg.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/bn.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/bn_in.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/ca.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/cs.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/da.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/de.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/de_at.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/de_be.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/el.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/en_au.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/en_be.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/en_bw.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/en_ca.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/en_gb.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/en_hk.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/en_ie.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/en_in.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/en_nz.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/en_ph.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/en_sg.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/en_za.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/en_zw.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/eo.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es_ar.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es_bo.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es_cl.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es_co.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es_cr.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es_do.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es_ec.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es_gt.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es_hn.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es_mx.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es_ni.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es_pa.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es_pe.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es_pr.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es_py.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es_sv.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es_uy.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/es_ve.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/et.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/eu.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/eu_es.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/fa.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/fa_in.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/fa_ir.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/fi.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/fo.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/fo_fo.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/fr.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/fr_be.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/fr_ca.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/fr_ch.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/ga.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/ga_ie.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/gl.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/gl_es.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/gv.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/gv_gb.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/he.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/hi.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/hi_in.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/hr.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/hu.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/id.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/id_id.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/is.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/it.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/it_ch.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/ja.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/kl.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/kl_gl.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/ko.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/ko_kr.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/kok.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/kok_in.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/kw.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/kw_gb.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/lt.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/lv.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/mk.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/mr.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/mr_in.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/ms.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/ms_my.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/mt.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/nb.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/nl.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/nl_be.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/nn.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/pl.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/pt.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/pt_br.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/ro.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/ru.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/ru_ua.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/sh.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/sk.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/sl.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/sq.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/sr.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/sv.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/sw.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/ta.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/ta_in.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/te.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/te_in.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/th.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/tr.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/uk.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/vi.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/zh.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/zh_cn.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/zh_hk.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/zh_sg.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/msgs/zh_tw.msg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/tzdata/Africa/Asmara | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/tzdata/America/Atikokan | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/tzdata/America/Blanc-Sablon | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/tzdata/America/Indiana/Petersburg | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/tzdata/America/Indiana/Tell_City | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/tzdata/America/Indiana/Vincennes | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/tzdata/America/Indiana/Winamac | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/tzdata/America/Moncton | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/tzdata/America/North_Dakota/New_Salem | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/tzdata/America/Resolute | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/tzdata/Atlantic/Faroe | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/tzdata/Australia/Eucla | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/tzdata/Europe/Guernsey | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/tzdata/Europe/Isle_of_Man | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/tzdata/Europe/Jersey | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/tzdata/Europe/Podgorica | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | library/tzdata/Europe/Volgograd | 0 |
150 files changed, 1159 insertions, 1 deletions
diff --git a/library/encoding/tis-620.enc b/library/encoding/tis-620.enc index c233be5..c233be5 100644..100755 --- a/library/encoding/tis-620.enc +++ b/library/encoding/tis-620.enc diff --git a/library/http/cookiejar.tcl b/library/http/cookiejar.tcl new file mode 100644 index 0000000..309ca7a --- /dev/null +++ b/library/http/cookiejar.tcl @@ -0,0 +1,745 @@ +# cookiejar.tcl -- +# +# Implementation of an HTTP cookie storage engine using SQLite. The +# implementation is done as a TclOO class, and includes a punycode +# encoder and decoder (though only the encoder is currently used). +# +# See the file "license.terms" for information on usage and redistribution of +# this file, and for a DISCLAIMER OF ALL WARRANTIES. + +# Dependencies +package require Tcl 8.6 +package require http 2.8.4 +package require sqlite3 +package require tcl::idna 1.0 + +# +# Configuration for the cookiejar package, plus basic support procedures. +# + +# This is the class that we are creating +if {![llength [info commands ::http::cookiejar]]} { + ::oo::class create ::http::cookiejar +} + +namespace eval [info object namespace ::http::cookiejar] { + proc setInt {*var val} { + upvar 1 ${*var} var + if {[catch {incr dummy $val} msg]} { + return -code error $msg + } + set var $val + } + proc setInterval {trigger *var val} { + upvar 1 ${*var} var + if {![string is integer -strict $val] || $val < 1} { + return -code error "expected positive integer but got \"$val\"" + } + set var $val + {*}$trigger + } + proc setBool {*var val} { + upvar 1 ${*var} var + if {[catch {if {$val} {}} msg]} { + return -code error $msg + } + set var [expr {!!$val}] + } + + proc setLog {*var val} { + upvar 1 ${*var} var + set var [::tcl::prefix match -message "log level" \ + {debug info warn error} $val] + } + + # Keep this in sync with pkgIndex.tcl and with the install directories in + # Makefiles + variable version 0.1 + + variable domainlist \ + http://publicsuffix.org/list/effective_tld_names.dat + variable domainfile \ + [file join [file dirname [info script]] effective_tld_names.txt.gz] + # The list is directed to from http://publicsuffix.org/list/ + variable loglevel info + variable vacuumtrigger 200 + variable retainlimit 100 + variable offline false + variable purgeinterval 60000 + variable refreshinterval 10000000 + variable domaincache {} + + # Some support procedures, none particularly useful in general + namespace eval support { + # Set up a logger if the http package isn't actually loaded yet. + if {![llength [info commands ::http::Log]]} { + proc ::http::Log args { + # Do nothing by default... + } + } + + namespace export * + proc locn {secure domain path {key ""}} { + if {$key eq ""} { + format "%s://%s%s" [expr {$secure?"https":"http"}] \ + [::tcl::idna encode $domain] $path + } else { + format "%s://%s%s?%s" \ + [expr {$secure?"https":"http"}] [::tcl::idna encode $domain] \ + $path $key + } + } + proc splitDomain domain { + set pieces [split $domain "."] + for {set i [llength $pieces]} {[incr i -1] >= 0} {} { + lappend result [join [lrange $pieces $i end] "."] + } + return $result + } + proc splitPath path { + set pieces [split [string trimleft $path "/"] "/"] + for {set j -1} {$j < [llength $pieces]} {incr j} { + lappend result /[join [lrange $pieces 0 $j] "/"] + } + return $result + } + proc isoNow {} { + set ms [clock milliseconds] + set ts [expr {$ms / 1000}] + set ms [format %03d [expr {$ms % 1000}]] + clock format $ts -format "%Y%m%dT%H%M%S.${ms}Z" -gmt 1 + } + proc log {level msg args} { + namespace upvar [info object namespace ::http::cookiejar] \ + loglevel loglevel + set who [uplevel 1 self class] + set mth [uplevel 1 self method] + set map {debug 0 info 1 warn 2 error 3} + if {[string map $map $level] >= [string map $map $loglevel]} { + set msg [format $msg {*}$args] + set LVL [string toupper $level] + ::http::Log "[isoNow] $LVL $who $mth - $msg" + } + } + } +} + +# Now we have enough information to provide the package. +package provide cookiejar \ + [set [info object namespace ::http::cookiejar]::version] + +# The implementation of the cookiejar package +::oo::define ::http::cookiejar { + self { + method configure {{optionName "\u0000\u0000"} {optionValue "\u0000\u0000"}} { + set tbl { + -domainfile {domainfile set} + -domainlist {domainlist set} + -domainrefresh {refreshinterval setInterval} + -loglevel {loglevel setLog} + -offline {offline setBool} + -purgeold {purgeinterval setInterval} + -retain {retainlimit setInt} + -vacuumtrigger {vacuumtrigger setInt} + } + dict lappend tbl -domainrefresh [namespace code { + my IntervalTrigger PostponeRefresh + }] + dict lappend tbl -purgeold [namespace code { + my IntervalTrigger PostponePurge + }] + if {$optionName eq "\u0000\u0000"} { + return [dict keys $tbl] + } + set opt [::tcl::prefix match -message "option" \ + [dict keys $tbl] $optionName] + set setter [lassign [dict get $tbl $opt] varname] + namespace upvar [namespace current] $varname var + if {$optionValue ne "\u0000\u0000"} { + {*}$setter var $optionValue + } + return $var + } + + method IntervalTrigger {method} { + # TODO: handle subclassing + foreach obj [info class instances [self]] { + [info object namespace $obj]::my $method + } + } + } + + variable purgeTimer deletions refreshTimer + constructor {{path ""}} { + namespace import [info object namespace [self class]]::support::* + + if {$path eq ""} { + sqlite3 [namespace current]::db :memory: + set storeorigin "constructed cookie store in memory" + } else { + sqlite3 [namespace current]::db $path + db timeout 500 + set storeorigin "loaded cookie store from $path" + } + + set deletions 0 + db transaction { + db eval { + --;# Store the persistent cookies in this table. + --;# Deletion policy: once they expire, or if explicitly + --;# killed. + CREATE TABLE IF NOT EXISTS persistentCookies ( + id INTEGER PRIMARY KEY, + secure INTEGER NOT NULL, + domain TEXT NOT NULL COLLATE NOCASE, + path TEXT NOT NULL, + key TEXT NOT NULL, + value TEXT NOT NULL, + originonly INTEGER NOT NULL, + expiry INTEGER NOT NULL, + lastuse INTEGER NOT NULL, + creation INTEGER NOT NULL); + CREATE UNIQUE INDEX IF NOT EXISTS persistentUnique + ON persistentCookies (domain, path, key); + CREATE INDEX IF NOT EXISTS persistentLookup + ON persistentCookies (domain, path); + + --;# Store the session cookies in this table. + --;# Deletion policy: at cookiejar instance deletion, if + --;# explicitly killed, or if the number of session cookies is + --;# too large and the cookie has not been used recently. + CREATE TEMP TABLE sessionCookies ( + id INTEGER PRIMARY KEY, + secure INTEGER NOT NULL, + domain TEXT NOT NULL COLLATE NOCASE, + path TEXT NOT NULL, + key TEXT NOT NULL, + originonly INTEGER NOT NULL, + value TEXT NOT NULL, + lastuse INTEGER NOT NULL, + creation INTEGER NOT NULL); + CREATE UNIQUE INDEX sessionUnique + ON sessionCookies (domain, path, key); + CREATE INDEX sessionLookup ON sessionCookies (domain, path); + + --;# View to allow for simple looking up of a cookie. + --;# Deletion policy: NOT SUPPORTED via this view. + CREATE TEMP VIEW cookies AS + SELECT id, domain, ( + CASE originonly WHEN 1 THEN path ELSE '.' || path END + ) AS path, key, value, secure, 1 AS persistent + FROM persistentCookies + UNION + SELECT id, domain, ( + CASE originonly WHEN 1 THEN path ELSE '.' || path END + ) AS path, key, value, secure, 0 AS persistent + FROM sessionCookies; + + --;# Encoded domain permission policy; if forbidden is 1, no + --;# cookie may be ever set for the domain, and if forbidden + --;# is 0, cookies *may* be created for the domain (overriding + --;# the forbiddenSuper table). + --;# Deletion policy: normally not modified. + CREATE TABLE IF NOT EXISTS domains ( + domain TEXT PRIMARY KEY NOT NULL, + forbidden INTEGER NOT NULL); + + --;# Domains that may not have a cookie defined for direct + --;# child domains of them. + --;# Deletion policy: normally not modified. + CREATE TABLE IF NOT EXISTS forbiddenSuper ( + domain TEXT PRIMARY KEY); + + --;# When we last retrieved the domain list. + CREATE TABLE IF NOT EXISTS domainCacheMetadata ( + id INTEGER PRIMARY KEY, + retrievalDate INTEGER, + installDate INTEGER); + } + + set cookieCount "no" + db eval { + SELECT COUNT(*) AS cookieCount FROM persistentCookies + } + log info "%s with %s entries" $storeorigin $cookieCount + + my PostponePurge + + if {$path ne ""} { + if {[db exists {SELECT 1 FROM domains}]} { + my RefreshDomains + } else { + my InitDomainList + my PostponeRefresh + } + } else { + set data [my GetDomainListOffline metadata] + my InstallDomainData $data $metadata + my PostponeRefresh + } + } + } + + method PostponePurge {} { + namespace upvar [info object namespace [self class]] \ + purgeinterval interval + catch {after cancel $purgeTimer} + set purgeTimer [after $interval [namespace code {my PurgeCookies}]] + } + + method PostponeRefresh {} { + namespace upvar [info object namespace [self class]] \ + refreshinterval interval + catch {after cancel $refreshTimer} + set refreshTimer [after $interval [namespace code {my RefreshDomains}]] + } + + method RefreshDomains {} { + # TODO: domain list refresh policy + my PostponeRefresh + } + + method HttpGet {url {timeout 0} {maxRedirects 5}} { + for {set r 0} {$r < $maxRedirects} {incr r} { + set tok [::http::geturl $url -timeout $timeout] + try { + if {[::http::status $tok] eq "timeout"} { + return -code error "connection timed out" + } elseif {[::http::ncode $tok] == 200} { + return [::http::data $tok] + } elseif {[::http::ncode $tok] >= 400} { + return -code error [::http::error $tok] + } elseif {[dict exists [::http::meta $tok] Location]} { + set url [dict get [::http::meta $tok] Location] + continue + } + return -code error \ + "unexpected state: [::http::code $tok]" + } finally { + ::http::cleanup $tok + } + } + return -code error "too many redirects" + } + method GetDomainListOnline {metaVar} { + upvar 1 $metaVar meta + namespace upvar [info object namespace [self class]] \ + domainlist url domaincache cache + lassign $cache when data + if {$when > [clock seconds] - 3600} { + log debug "using cached value created at %s" \ + [clock format $when -format {%Y%m%dT%H%M%SZ} -gmt 1] + dict set meta retrievalDate $when + return $data + } + log debug "loading domain list from %s" $url + try { + set when [clock seconds] + set data [my HttpGet $url] + set cache [list $when $data] + # TODO: Should we use the Last-Modified header instead? + dict set meta retrievalDate $when + return $data + } on error msg { + log error "failed to fetch list of forbidden cookie domains from %s: %s" \ + $url $msg + return {} + } + } + method GetDomainListOffline {metaVar} { + upvar 1 $metaVar meta + namespace upvar [info object namespace [self class]] \ + domainfile filename + log debug "loading domain list from %s" $filename + try { + set f [open $filename] + try { + if {[string match *.gz $filename]} { + zlib push gunzip $f + } + fconfigure $f -encoding utf-8 + dict set meta retrievalDate [file mtime $filename] + return [read $f] + } finally { + close $f + } + } on error {msg opt} { + log error "failed to read list of forbidden cookie domains from %s: %s" \ + $filename $msg + return -options $opt $msg + } + } + method InitDomainList {} { + namespace upvar [info object namespace [self class]] \ + offline offline + if {!$offline} { + try { + set data [my GetDomainListOnline metadata] + if {[string length $data]} { + my InstallDomainData $data $metadata + return + } + } on error {} { + log warn "attempting to fall back to built in version" + } + } + set data [my GetDomainListOffline metadata] + my InstallDomainData $data $metadata + } + + method InstallDomainData {data meta} { + set n [db total_changes] + db transaction { + foreach line [split $data "\n"] { + if {[string trim $line] eq ""} { + continue + } elseif {[string match //* $line]} { + continue + } elseif {[string match !* $line]} { + set line [string range $line 1 end] + set idna [string tolower [::tcl::idna encode $line]] + set utf [::tcl::idna decode [string tolower $line]] + db eval { + INSERT OR REPLACE INTO domains (domain, forbidden) + VALUES ($utf, 0); + } + if {$idna ne $utf} { + db eval { + INSERT OR REPLACE INTO domains (domain, forbidden) + VALUES ($idna, 0); + } + } + } else { + if {[string match {\*.*} $line]} { + set line [string range $line 2 end] + set idna [string tolower [::tcl::idna encode $line]] + set utf [::tcl::idna decode [string tolower $line]] + db eval { + INSERT OR REPLACE INTO forbiddenSuper (domain) + VALUES ($utf); + } + if {$idna ne $utf} { + db eval { + INSERT OR REPLACE INTO forbiddenSuper (domain) + VALUES ($idna); + } + } + } else { + set idna [string tolower [::tcl::idna encode $line]] + set utf [::tcl::idna decode [string tolower $line]] + } + db eval { + INSERT OR REPLACE INTO domains (domain, forbidden) + VALUES ($utf, 1); + } + if {$idna ne $utf} { + db eval { + INSERT OR REPLACE INTO domains (domain, forbidden) + VALUES ($idna, 1); + } + } + } + if {$utf ne [::tcl::idna decode [string tolower $idna]]} { + log warn "mismatch in IDNA handling for %s (%d, %s, %s)" \ + $idna $line $utf [::tcl::idna decode $idna] + } + } + + dict with meta { + set installDate [clock seconds] + db eval { + INSERT OR REPLACE INTO domainCacheMetadata + (id, retrievalDate, installDate) + VALUES (1, $retrievalDate, $installDate); + } + } + } + set n [expr {[db total_changes] - $n}] + log info "constructed domain info with %d entries" $n + } + + # This forces the rebuild of the domain data, loading it from + method forceLoadDomainData {} { + db transaction { + db eval { + DELETE FROM domains; + DELETE FROM forbiddenSuper; + INSERT OR REPLACE INTO domainCacheMetadata + (id, retrievalDate, installDate) + VALUES (1, -1, -1); + } + my InitDomainList + } + } + + destructor { + catch { + after cancel $purgeTimer + } + catch { + after cancel $refreshTimer + } + catch { + db close + } + return + } + + method GetCookiesForHostAndPath {listVar secure host path fullhost} { + upvar 1 $listVar result + log debug "check for cookies for %s" [locn $secure $host $path] + set exact [expr {$host eq $fullhost}] + db eval { + SELECT key, value FROM persistentCookies + WHERE domain = $host AND path = $path AND secure <= $secure + AND (NOT originonly OR domain = $fullhost) + AND originonly = $exact + } { + lappend result $key $value + db eval { + UPDATE persistentCookies SET lastuse = $now WHERE id = $id + } + } + set now [clock seconds] + db eval { + SELECT id, key, value FROM sessionCookies + WHERE domain = $host AND path = $path AND secure <= $secure + AND (NOT originonly OR domain = $fullhost) + AND originonly = $exact + } { + lappend result $key $value + db eval { + UPDATE sessionCookies SET lastuse = $now WHERE id = $id + } + } + } + + method getCookies {proto host path} { + set result {} + set paths [splitPath $path] + if {[regexp {[^0-9.]} $host]} { + set domains [splitDomain [string tolower [::tcl::idna encode $host]]] + } else { + # Ugh, it's a numeric domain! Restrict it to just itself... + set domains [list $host] + } + set secure [string equal -nocase $proto "https"] + # Open question: how to move these manipulations into the database + # engine (if that's where they *should* be). + # + # Suggestion from kbk: + #LENGTH(theColumn) <= LENGTH($queryStr) AND + #SUBSTR(theColumn, LENGTH($queryStr) LENGTH(theColumn)+1) = $queryStr + # + # However, we instead do most of the work in Tcl because that lets us + # do the splitting exactly right, and it's far easier to work with + # strings in Tcl than in SQL. + db transaction { + foreach domain $domains { + foreach p $paths { + my GetCookiesForHostAndPath result $secure $domain $p $host + } + } + return $result + } + } + + method BadDomain options { + if {![dict exists $options domain]} { + log error "no domain present in options" + return 0 + } + dict with options {} + if {$domain ne $origin} { + log debug "cookie domain varies from origin (%s, %s)" \ + $domain $origin + if {[string match .* $domain]} { + set dotd $domain + } else { + set dotd .$domain + } + if {![string equal -length [string length $dotd] \ + [string reverse $dotd] [string reverse $origin]]} { + log warn "bad cookie: domain not suffix of origin" + return 1 + } + } + if {![regexp {[^0-9.]} $domain]} { + if {$domain eq $origin} { + # May set for itself + return 0 + } + log warn "bad cookie: for a numeric address" + return 1 + } + db eval { + SELECT forbidden FROM domains WHERE domain = $domain + } { + if {$forbidden} { + log warn "bad cookie: for a forbidden address" + } + return $forbidden + } + if {[regexp {^[^.]+\.(.+)$} $domain -> super] && [db exists { + SELECT 1 FROM forbiddenSuper WHERE domain = $super + }]} then { + log warn "bad cookie: for a forbidden address" + return 1 + } + return 0 + } + + # A defined extension point to allow users to easily impose extra policies + # on whether to accept cookies from a particular domain and path. + method policyAllow {operation domain path} { + return true + } + + method storeCookie {options} { + db transaction { + if {[my BadDomain $options]} { + return + } + set now [clock seconds] + set persistent [dict exists $options expires] + dict with options {} + if {!$persistent} { + if {![my policyAllow session $domain $path]} { + log warn "bad cookie: $domain prohibited by user policy" + return + } + db eval { + INSERT OR REPLACE INTO sessionCookies ( + secure, domain, path, key, value, originonly, creation, + lastuse) + VALUES ($secure, $domain, $path, $key, $value, $hostonly, + $now, $now); + DELETE FROM persistentCookies + WHERE domain = $domain AND path = $path AND key = $key + AND secure <= $secure AND originonly = $hostonly + } + incr deletions [db changes] + log debug "defined session cookie for %s" \ + [locn $secure $domain $path $key] + } elseif {$expires < $now} { + if {![my policyAllow delete $domain $path]} { + log warn "bad cookie: $domain prohibited by user policy" + return + } + db eval { + DELETE FROM persistentCookies + WHERE domain = $domain AND path = $path AND key = $key + AND secure <= $secure AND originonly = $hostonly + } + set del [db changes] + db eval { + DELETE FROM sessionCookies + WHERE domain = $domain AND path = $path AND key = $key + AND secure <= $secure AND originonly = $hostonly + } + incr deletions [incr del [db changes]] + log debug "deleted %d cookies for %s" \ + $del [locn $secure $domain $path $key] + } else { + if {![my policyAllow set $domain $path]} { + log warn "bad cookie: $domain prohibited by user policy" + return + } + db eval { + INSERT OR REPLACE INTO persistentCookies ( + secure, domain, path, key, value, originonly, expiry, + creation, lastuse) + VALUES ($secure, $domain, $path, $key, $value, $hostonly, + $expires, $now, $now); + DELETE FROM sessionCookies + WHERE domain = $domain AND path = $path AND key = $key + AND secure <= $secure AND originonly = $hostonly + } + incr deletions [db changes] + log debug "defined persistent cookie for %s, expires at %s" \ + [locn $secure $domain $path $key] \ + [clock format $expires] + } + } + } + + method PurgeCookies {} { + namespace upvar [info object namespace [self class]] \ + vacuumtrigger trigger retainlimit retain + my PostponePurge + set now [clock seconds] + log debug "purging cookies that expired before %s" [clock format $now] + db transaction { + db eval { + DELETE FROM persistentCookies WHERE expiry < $now + } + incr deletions [db changes] + db eval { + DELETE FROM persistentCookies WHERE id IN ( + SELECT id FROM persistentCookies ORDER BY lastuse ASC + LIMIT -1 OFFSET $retain) + } + incr deletions [db changes] + db eval { + DELETE FROM sessionCookies WHERE id IN ( + SELECT id FROM sessionCookies ORDER BY lastuse + LIMIT -1 OFFSET $retain) + } + incr deletions [db changes] + } + + # Once we've deleted a fair bit, vacuum the database. Must be done + # outside a transaction. + if {$deletions > $trigger} { + set deletions 0 + log debug "vacuuming cookie database" + catch { + db eval { + VACUUM + } + } + } + } + + forward Database db + + method lookup {{host ""} {key ""}} { + set host [string tolower [::tcl::idna encode $host]] + db transaction { + if {$host eq ""} { + set result {} + db eval { + SELECT DISTINCT domain FROM cookies + ORDER BY domain + } { + lappend result [::tcl::idna decode [string tolower $domain]] + } + return $result + } elseif {$key eq ""} { + set result {} + db eval { + SELECT DISTINCT key FROM cookies + WHERE domain = $host + ORDER BY key + } { + lappend result $key + } + return $result + } else { + db eval { + SELECT value FROM cookies + WHERE domain = $host AND key = $key + LIMIT 1 + } { + return $value + } + return -code error "no such key for that host" + } + } + } +} + +# Local variables: +# mode: tcl +# fill-column: 78 +# End: diff --git a/library/http/effective_tld_names.txt.gz b/library/http/effective_tld_names.txt.gz Binary files differnew file mode 100644 index 0000000..9ce2b69 --- /dev/null +++ b/library/http/effective_tld_names.txt.gz diff --git a/library/http/http.tcl b/library/http/http.tcl index f82bced..7236bae 100644 --- a/library/http/http.tcl +++ b/library/http/http.tcl @@ -20,6 +20,7 @@ namespace eval http { if {![info exists http]} { array set http { -accept */* + -cookiejar {} -pipeline 1 -postfresh 0 -proxyhost {} @@ -127,6 +128,18 @@ namespace eval http { set defaultKeepalive 0 } + # Regular expression used to parse cookies + variable CookieRE {(?x) # EXPANDED SYNTAX + \s* # Ignore leading spaces + ([^][\u0000- ()<>@,;:\\""/?={}\u007f-\uffff]+) # Match the name + = # LITERAL: Equal sign + ([!\u0023-+\u002D-:<-\u005B\u005D-~]*) # Match the value + (?: + \s* ; \s* # LITERAL: semicolon + ([^\u0000]+) # Match the options + )? + } + namespace export geturl config reset wait formatQuery quoteString namespace export register unregister registerError # - Useful, but not exported: data, size, status, code, cleanup, error, @@ -892,8 +905,12 @@ proc http::geturl {url args} { } return -code error "Illegal characters in URL path" } + if {![regexp {^[^?#]+} $srvurl state(path)]} { + set state(path) / + } } else { set srvurl / + set state(path) / } if {$proto eq ""} { set proto http @@ -1354,12 +1371,16 @@ proc http::Connected {token proto phost srvurl} { puts $sock "$how $srvurl HTTP/$state(-protocol)" if {[dict exists $state(-headers) Host]} { # Allow Host spoofing. [Bug 928154] - puts $sock "Host: [dict get $state(-headers) Host]" + set hostHdr [dict get $state(-headers) Host] + regexp {^[^:]+} $hostHdr state(host) + puts $sock "Host: $hostHdr" } elseif {$port == $defport} { # Don't add port in this case, to handle broken servers. [Bug # #504508] + set state(host) $host puts $sock "Host: $host" } else { + set state(host) $host puts $sock "Host: $host:$port" } puts $sock "User-Agent: $http(-useragent)" @@ -1421,6 +1442,22 @@ proc http::Connected {token proto phost srvurl} { seek $state(-querychannel) $start } + # Note that we don't do Cookie2; that's much nastier and not normally + # observed in practice either. It also doesn't fix the multitude of + # bugs in the basic cookie spec. + if {$http(-cookiejar) ne ""} { + set cookies "" + set separator "" + foreach {key value} [{*}$http(-cookiejar) \ + getCookies $proto $host $state(path)] { + append cookies $separator $key = $value + set separator "; " + } + if {$cookies ne ""} { + puts $sock "Cookie: $cookies" + } + } + # Flush the request header and set up the fileevent that will either # push the POST data or read the response. # @@ -2693,6 +2730,11 @@ proc http::Event {sock token} { set state(connection) \ [string trim [string tolower $value]] } + set-cookie { + if {$http(-cookiejar) ne ""} { + ParseCookie $token [string trim $value] + } + } } lappend state(meta) $key [string trim $value] } @@ -2990,6 +3032,83 @@ proc http::IsBinaryContentType {type} { return true } +proc http::ParseCookie {token value} { + variable http + variable CookieRE + variable $token + upvar 0 $token state + + if {![regexp $CookieRE $value -> cookiename cookieval opts]} { + # Bad cookie! No biscuit! + return + } + + # Convert the options into a list before feeding into the cookie store; + # ugly, but quite easy. + set realopts {hostonly 1 path / secure 0 httponly 0} + dict set realopts origin $state(host) + dict set realopts domain $state(host) + foreach option [split [regsub -all {;\s+} $opts \u0000] \u0000] { + regexp {^(.*?)(?:=(.*))?$} $option -> optname optval + switch -exact -- [string tolower $optname] { + expires { + if {[catch { + #Sun, 06 Nov 1994 08:49:37 GMT + dict set realopts expires \ + [clock scan $optval -format "%a, %d %b %Y %T %Z"] + }] && [catch { + # Google does this one + #Mon, 01-Jan-1990 00:00:00 GMT + dict set realopts expires \ + [clock scan $optval -format "%a, %d-%b-%Y %T %Z"] + }] && [catch { + # This is in the RFC, but it is also in the original + # Netscape cookie spec, now online at: + # <URL:http://curl.haxx.se/rfc/cookie_spec.html> + #Sunday, 06-Nov-94 08:49:37 GMT + dict set realopts expires \ + [clock scan $optval -format "%A, %d-%b-%y %T %Z"] + }]} {catch { + #Sun Nov 6 08:49:37 1994 + dict set realopts expires \ + [clock scan $optval -gmt 1 -format "%a %b %d %T %Y"] + }} + } + max-age { + # Normalize + if {[string is integer -strict $optval]} { + dict set realopts expires [expr {[clock seconds] + $optval}] + } + } + domain { + # From the domain-matches definition [RFC 2109, section 2]: + # Host A's name domain-matches host B's if [...] + # A is a FQDN string and has the form NB, where N is a + # non-empty name string, B has the form .B', and B' is a + # FQDN string. (So, x.y.com domain-matches .y.com but + # not y.com.) + if {$optval ne "" && ![string match *. $optval]} { + dict set realopts domain [string trimleft $optval "."] + dict set realopts hostonly [expr { + ! [string match .* $optval] + }] + } + } + path { + if {[string match /* $optval]} { + dict set realopts path $optval + } + } + secure - httponly { + dict set realopts [string tolower $optname] 1 + } + } + } + dict set realopts key $cookiename + dict set realopts value $cookieval + {*}$http(-cookiejar) storeCookie $realopts +} + # http::getTextLine -- # # Get one line with the stream in crlf mode. diff --git a/library/http/idna.tcl b/library/http/idna.tcl new file mode 100644 index 0000000..2a7d289 --- /dev/null +++ b/library/http/idna.tcl @@ -0,0 +1,292 @@ +# cookiejar.tcl -- +# +# Implementation of IDNA (Internationalized Domain Names for +# Applications) encoding/decoding system, built on a punycode engine +# developed directly from the code in RFC 3492, Appendix C (with +# substantial modifications). +# +# This implementation includes code from that RFC, translated to Tcl; the +# other parts are: +# Copyright (c) 2014 Donal K. Fellows +# +# See the file "license.terms" for information on usage and redistribution of +# this file, and for a DISCLAIMER OF ALL WARRANTIES. + +namespace eval ::tcl::idna { + namespace ensemble create -command puny -map { + encode punyencode + decode punydecode + } + namespace ensemble create -command ::tcl::idna -map { + encode IDNAencode + decode IDNAdecode + puny puny + version {::apply {{} {package present tcl::idna} ::}} + } + + proc IDNAencode hostname { + set parts {} + # Split term from RFC 3490, Sec 3.1 + foreach part [split $hostname "\u002E\u3002\uFF0E\uFF61"] { + if {[regexp {[^-A-Za-z0-9]} $part]} { + if {[regexp {[^-A-Za-z0-9\u00a1-\uffff]} $part ch]} { + scan $ch %c c + if {$ch < "!" || $ch > "~"} { + set ch [format "\\u%04x" $c] + } + throw [list IDNA INVALID_NAME_CHARACTER $ch] \ + "bad character \"$ch\" in DNS name" + } + set part xn--[punyencode $part] + # Length restriction from RFC 5890, Sec 2.3.1 + if {[string length $part] > 63} { + throw [list IDNA OVERLONG_PART $part] \ + "hostname part too long" + } + } + lappend parts $part + } + return [join $parts .] + } + proc IDNAdecode hostname { + set parts {} + # Split term from RFC 3490, Sec 3.1 + foreach part [split $hostname "\u002E\u3002\uFF0E\uFF61"] { + if {[string match -nocase "xn--*" $part]} { + set part [punydecode [string range $part 4 end]] + } + lappend parts $part + } + return [join $parts .] + } + + variable digits [split "abcdefghijklmnopqrstuvwxyz0123456789" ""] + # Bootstring parameters for Punycode + variable base 36 + variable tmin 1 + variable tmax 26 + variable skew 38 + variable damp 700 + variable initial_bias 72 + variable initial_n 0x80 + + variable max_codepoint 0x10FFFF + + proc adapt {delta first numchars} { + variable base + variable tmin + variable tmax + variable damp + variable skew + + set delta [expr {$delta / ($first ? $damp : 2)}] + incr delta [expr {$delta / $numchars}] + set k 0 + while {$delta > ($base - $tmin) * $tmax / 2} { + set delta [expr {$delta / ($base-$tmin)}] + incr k $base + } + return [expr {$k + ($base-$tmin+1) * $delta / ($delta+$skew)}] + } + + # Main punycode encoding function + proc punyencode {string {case ""}} { + variable digits + variable tmin + variable tmax + variable base + variable initial_n + variable initial_bias + + if {![string is boolean $case]} { + return -code error "\"$case\" must be boolean" + } + + set in {} + foreach char [set string [split $string ""]] { + scan $char "%c" ch + lappend in $ch + } + set output {} + + # Initialize the state: + set n $initial_n + set delta 0 + set bias $initial_bias + + # Handle the basic code points: + foreach ch $string { + if {$ch < "\u0080"} { + if {$case eq ""} { + append output $ch + } elseif {[string is true $case]} { + append output [string toupper $ch] + } elseif {[string is false $case]} { + append output [string tolower $ch] + } + } + } + + set b [string length $output] + + # h is the number of code points that have been handled, b is the + # number of basic code points. + + if {$b > 0} { + append output "-" + } + + # Main encoding loop: + + for {set h $b} {$h < [llength $in]} {incr delta; incr n} { + # All non-basic code points < n have been handled already. Find + # the next larger one: + + set m inf + foreach ch $in { + if {$ch >= $n && $ch < $m} { + set m $ch + } + } + + # Increase delta enough to advance the decoder's <n,i> state to + # <m,0>, but guard against overflow: + + if {$m-$n > (0xffffffff-$delta)/($h+1)} { + throw {PUNYCODE OVERFLOW} "overflow in delta computation" + } + incr delta [expr {($m-$n) * ($h+1)}] + set n $m + + foreach ch $in { + if {$ch < $n && ([incr delta] & 0xffffffff) == 0} { + throw {PUNYCODE OVERFLOW} "overflow in delta computation" + } + + if {$ch != $n} { + continue + } + + # Represent delta as a generalized variable-length integer: + + for {set q $delta; set k $base} true {incr k $base} { + set t [expr {min(max($k-$bias, $tmin), $tmax)}] + if {$q < $t} { + break + } + append output \ + [lindex $digits [expr {$t + ($q-$t)%($base-$t)}]] + set q [expr {($q-$t) / ($base-$t)}] + } + + append output [lindex $digits $q] + set bias [adapt $delta [expr {$h==$b}] [expr {$h+1}]] + set delta 0 + incr h + } + } + + return $output + } + + # Main punycode decode function + proc punydecode {string {case ""}} { + variable tmin + variable tmax + variable base + variable initial_n + variable initial_bias + variable max_codepoint + + if {![string is boolean $case]} { + return -code error "\"$case\" must be boolean" + } + + # Initialize the state: + + set n $initial_n + set i 0 + set first 1 + set bias $initial_bias + + # Split the string into the "real" ASCII characters and the ones to + # feed into the main decoder. Note that we don't need to check the + # result of [regexp] because that RE will technically match any string + # at all. + + regexp {^(?:(.*)-)?([^-]*)$} $string -> pre post + if {[string is true -strict $case]} { + set pre [string toupper $pre] + } elseif {[string is false -strict $case]} { + set pre [string tolower $pre] + } + set output [split $pre ""] + set out [llength $output] + + # Main decoding loop: + + for {set in 0} {$in < [string length $post]} {incr in} { + # Decode a generalized variable-length integer into delta, which + # gets added to i. The overflow checking is easier if we increase + # i as we go, then subtract off its starting value at the end to + # obtain delta. + + for {set oldi $i; set w 1; set k $base} 1 {incr in} { + if {[set ch [string index $post $in]] eq ""} { + throw {PUNYCODE BAD_INPUT LENGTH} "exceeded input data" + } + if {[string match -nocase {[a-z]} $ch]} { + scan [string toupper $ch] %c digit + incr digit -65 + } elseif {[string match {[0-9]} $ch]} { + set digit [expr {$ch + 26}] + } else { + throw {PUNYCODE BAD_INPUT CHAR} \ + "bad decode character \"$ch\"" + } + incr i [expr {$digit * $w}] + set t [expr {min(max($tmin, $k-$bias), $tmax)}] + if {$digit < $t} { + set bias [adapt [expr {$i-$oldi}] $first [incr out]] + set first 0 + break + } + if {[set w [expr {$w * ($base - $t)}]] > 0x7fffffff} { + throw {PUNYCODE OVERFLOW} \ + "excessively large integer computed in digit decode" + } + incr k $base + } + + # i was supposed to wrap around from out+1 to 0, incrementing n + # each time, so we'll fix that now: + + if {[incr n [expr {$i / $out}]] > 0x7fffffff} { + throw {PUNYCODE OVERFLOW} \ + "excessively large integer computed in character choice" + } elseif {$n > $max_codepoint} { + if {$n >= 0x00d800 && $n < 0x00e000} { + # Bare surrogate?! + throw {PUNYCODE NON_BMP} \ + [format "unsupported character U+%06x" $n] + } + throw {PUNYCODE NON_UNICODE} "bad codepoint $n" + } + set i [expr {$i % $out}] + + # Insert n at position i of the output: + + set output [linsert $output $i [format "%c" $n]] + incr i + } + + return [join $output ""] + } +} + +package provide tcl::idna 1.0 + +# Local variables: +# mode: tcl +# fill-column: 78 +# End: diff --git a/library/http/pkgIndex.tcl b/library/http/pkgIndex.tcl index 4f74635..3bc111f 100644 --- a/library/http/pkgIndex.tcl +++ b/library/http/pkgIndex.tcl @@ -1,2 +1,4 @@ if {![package vsatisfies [package provide Tcl] 8.6-]} {return} package ifneeded http 2.9.0 [list tclPkgSetup $dir http 2.9.0 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}] +package ifneeded cookiejar 0.1 [list source [file join $dir cookiejar.tcl]] +package ifneeded tcl::idna 1.0 [list source [file join $dir idna.tcl]] diff --git a/library/msgs/af.msg b/library/msgs/af.msg index 0892615..0892615 100644..100755 --- a/library/msgs/af.msg +++ b/library/msgs/af.msg diff --git a/library/msgs/af_za.msg b/library/msgs/af_za.msg index fef48ad..fef48ad 100644..100755 --- a/library/msgs/af_za.msg +++ b/library/msgs/af_za.msg diff --git a/library/msgs/ar.msg b/library/msgs/ar.msg index 2d403ec..2d403ec 100644..100755 --- a/library/msgs/ar.msg +++ b/library/msgs/ar.msg diff --git a/library/msgs/ar_in.msg b/library/msgs/ar_in.msg index 185e49c..185e49c 100644..100755 --- a/library/msgs/ar_in.msg +++ b/library/msgs/ar_in.msg diff --git a/library/msgs/ar_jo.msg b/library/msgs/ar_jo.msg index 9a9dda0..9a9dda0 100644..100755 --- a/library/msgs/ar_jo.msg +++ b/library/msgs/ar_jo.msg diff --git a/library/msgs/ar_lb.msg b/library/msgs/ar_lb.msg index c23aa2c..c23aa2c 100644..100755 --- a/library/msgs/ar_lb.msg +++ b/library/msgs/ar_lb.msg diff --git a/library/msgs/ar_sy.msg b/library/msgs/ar_sy.msg index f0daec0..f0daec0 100644..100755 --- a/library/msgs/ar_sy.msg +++ b/library/msgs/ar_sy.msg diff --git a/library/msgs/be.msg b/library/msgs/be.msg index a0aceed..a0aceed 100644..100755 --- a/library/msgs/be.msg +++ b/library/msgs/be.msg diff --git a/library/msgs/bg.msg b/library/msgs/bg.msg index 2e7730d..2e7730d 100644..100755 --- a/library/msgs/bg.msg +++ b/library/msgs/bg.msg diff --git a/library/msgs/bn.msg b/library/msgs/bn.msg index a0aef13..a0aef13 100644..100755 --- a/library/msgs/bn.msg +++ b/library/msgs/bn.msg diff --git a/library/msgs/bn_in.msg b/library/msgs/bn_in.msg index 28c000f..28c000f 100644..100755 --- a/library/msgs/bn_in.msg +++ b/library/msgs/bn_in.msg diff --git a/library/msgs/ca.msg b/library/msgs/ca.msg index 272f682..272f682 100644..100755 --- a/library/msgs/ca.msg +++ b/library/msgs/ca.msg diff --git a/library/msgs/cs.msg b/library/msgs/cs.msg index 4673cd4..4673cd4 100644..100755 --- a/library/msgs/cs.msg +++ b/library/msgs/cs.msg diff --git a/library/msgs/da.msg b/library/msgs/da.msg index abed3c5..abed3c5 100644..100755 --- a/library/msgs/da.msg +++ b/library/msgs/da.msg diff --git a/library/msgs/de.msg b/library/msgs/de.msg index 0bb7399..0bb7399 100644..100755 --- a/library/msgs/de.msg +++ b/library/msgs/de.msg diff --git a/library/msgs/de_at.msg b/library/msgs/de_at.msg index 1a0a0f5..1a0a0f5 100644..100755 --- a/library/msgs/de_at.msg +++ b/library/msgs/de_at.msg diff --git a/library/msgs/de_be.msg b/library/msgs/de_be.msg index 04cf88c..04cf88c 100644..100755 --- a/library/msgs/de_be.msg +++ b/library/msgs/de_be.msg diff --git a/library/msgs/el.msg b/library/msgs/el.msg index 26bdfe9..26bdfe9 100644..100755 --- a/library/msgs/el.msg +++ b/library/msgs/el.msg diff --git a/library/msgs/en_au.msg b/library/msgs/en_au.msg index 7f9870c..7f9870c 100644..100755 --- a/library/msgs/en_au.msg +++ b/library/msgs/en_au.msg diff --git a/library/msgs/en_be.msg b/library/msgs/en_be.msg index 5072986..5072986 100644..100755 --- a/library/msgs/en_be.msg +++ b/library/msgs/en_be.msg diff --git a/library/msgs/en_bw.msg b/library/msgs/en_bw.msg index 8fd20c7..8fd20c7 100644..100755 --- a/library/msgs/en_bw.msg +++ b/library/msgs/en_bw.msg diff --git a/library/msgs/en_ca.msg b/library/msgs/en_ca.msg index 278efe7..278efe7 100644..100755 --- a/library/msgs/en_ca.msg +++ b/library/msgs/en_ca.msg diff --git a/library/msgs/en_gb.msg b/library/msgs/en_gb.msg index 5c61c43..5c61c43 100644..100755 --- a/library/msgs/en_gb.msg +++ b/library/msgs/en_gb.msg diff --git a/library/msgs/en_hk.msg b/library/msgs/en_hk.msg index 8b33bc0..8b33bc0 100644..100755 --- a/library/msgs/en_hk.msg +++ b/library/msgs/en_hk.msg diff --git a/library/msgs/en_ie.msg b/library/msgs/en_ie.msg index ba621cf..ba621cf 100644..100755 --- a/library/msgs/en_ie.msg +++ b/library/msgs/en_ie.msg diff --git a/library/msgs/en_in.msg b/library/msgs/en_in.msg index a1f155d..a1f155d 100644..100755 --- a/library/msgs/en_in.msg +++ b/library/msgs/en_in.msg diff --git a/library/msgs/en_nz.msg b/library/msgs/en_nz.msg index b419017..b419017 100644..100755 --- a/library/msgs/en_nz.msg +++ b/library/msgs/en_nz.msg diff --git a/library/msgs/en_ph.msg b/library/msgs/en_ph.msg index 682666d..682666d 100644..100755 --- a/library/msgs/en_ph.msg +++ b/library/msgs/en_ph.msg diff --git a/library/msgs/en_sg.msg b/library/msgs/en_sg.msg index 4dc5b1d..4dc5b1d 100644..100755 --- a/library/msgs/en_sg.msg +++ b/library/msgs/en_sg.msg diff --git a/library/msgs/en_za.msg b/library/msgs/en_za.msg index fe43797..fe43797 100644..100755 --- a/library/msgs/en_za.msg +++ b/library/msgs/en_za.msg diff --git a/library/msgs/en_zw.msg b/library/msgs/en_zw.msg index 2a5804f..2a5804f 100644..100755 --- a/library/msgs/en_zw.msg +++ b/library/msgs/en_zw.msg diff --git a/library/msgs/eo.msg b/library/msgs/eo.msg index b9b1500..b9b1500 100644..100755 --- a/library/msgs/eo.msg +++ b/library/msgs/eo.msg diff --git a/library/msgs/es.msg b/library/msgs/es.msg index 6090eab..6090eab 100644..100755 --- a/library/msgs/es.msg +++ b/library/msgs/es.msg diff --git a/library/msgs/es_ar.msg b/library/msgs/es_ar.msg index 7d35027..7d35027 100644..100755 --- a/library/msgs/es_ar.msg +++ b/library/msgs/es_ar.msg diff --git a/library/msgs/es_bo.msg b/library/msgs/es_bo.msg index 498ad0d..498ad0d 100644..100755 --- a/library/msgs/es_bo.msg +++ b/library/msgs/es_bo.msg diff --git a/library/msgs/es_cl.msg b/library/msgs/es_cl.msg index 31d465c..31d465c 100644..100755 --- a/library/msgs/es_cl.msg +++ b/library/msgs/es_cl.msg diff --git a/library/msgs/es_co.msg b/library/msgs/es_co.msg index 77e57f0..77e57f0 100644..100755 --- a/library/msgs/es_co.msg +++ b/library/msgs/es_co.msg diff --git a/library/msgs/es_cr.msg b/library/msgs/es_cr.msg index 7a652fa..7a652fa 100644..100755 --- a/library/msgs/es_cr.msg +++ b/library/msgs/es_cr.msg diff --git a/library/msgs/es_do.msg b/library/msgs/es_do.msg index 0e283da..0e283da 100644..100755 --- a/library/msgs/es_do.msg +++ b/library/msgs/es_do.msg diff --git a/library/msgs/es_ec.msg b/library/msgs/es_ec.msg index 9e921e0..9e921e0 100644..100755 --- a/library/msgs/es_ec.msg +++ b/library/msgs/es_ec.msg diff --git a/library/msgs/es_gt.msg b/library/msgs/es_gt.msg index ecd6faf..ecd6faf 100644..100755 --- a/library/msgs/es_gt.msg +++ b/library/msgs/es_gt.msg diff --git a/library/msgs/es_hn.msg b/library/msgs/es_hn.msg index a758ca2..a758ca2 100644..100755 --- a/library/msgs/es_hn.msg +++ b/library/msgs/es_hn.msg diff --git a/library/msgs/es_mx.msg b/library/msgs/es_mx.msg index 7cfb545..7cfb545 100644..100755 --- a/library/msgs/es_mx.msg +++ b/library/msgs/es_mx.msg diff --git a/library/msgs/es_ni.msg b/library/msgs/es_ni.msg index 7c39495..7c39495 100644..100755 --- a/library/msgs/es_ni.msg +++ b/library/msgs/es_ni.msg diff --git a/library/msgs/es_pa.msg b/library/msgs/es_pa.msg index cecacdc..cecacdc 100644..100755 --- a/library/msgs/es_pa.msg +++ b/library/msgs/es_pa.msg diff --git a/library/msgs/es_pe.msg b/library/msgs/es_pe.msg index 9f90595..9f90595 100644..100755 --- a/library/msgs/es_pe.msg +++ b/library/msgs/es_pe.msg diff --git a/library/msgs/es_pr.msg b/library/msgs/es_pr.msg index 8511b12..8511b12 100644..100755 --- a/library/msgs/es_pr.msg +++ b/library/msgs/es_pr.msg diff --git a/library/msgs/es_py.msg b/library/msgs/es_py.msg index aa93d36..aa93d36 100644..100755 --- a/library/msgs/es_py.msg +++ b/library/msgs/es_py.msg diff --git a/library/msgs/es_sv.msg b/library/msgs/es_sv.msg index fc7954d..fc7954d 100644..100755 --- a/library/msgs/es_sv.msg +++ b/library/msgs/es_sv.msg diff --git a/library/msgs/es_uy.msg b/library/msgs/es_uy.msg index b33525c..b33525c 100644..100755 --- a/library/msgs/es_uy.msg +++ b/library/msgs/es_uy.msg diff --git a/library/msgs/es_ve.msg b/library/msgs/es_ve.msg index 7c2a7b0..7c2a7b0 100644..100755 --- a/library/msgs/es_ve.msg +++ b/library/msgs/es_ve.msg diff --git a/library/msgs/et.msg b/library/msgs/et.msg index a782f9b..a782f9b 100644..100755 --- a/library/msgs/et.msg +++ b/library/msgs/et.msg diff --git a/library/msgs/eu.msg b/library/msgs/eu.msg index cf708b6..cf708b6 100644..100755 --- a/library/msgs/eu.msg +++ b/library/msgs/eu.msg diff --git a/library/msgs/eu_es.msg b/library/msgs/eu_es.msg index 2694418..2694418 100644..100755 --- a/library/msgs/eu_es.msg +++ b/library/msgs/eu_es.msg diff --git a/library/msgs/fa.msg b/library/msgs/fa.msg index 6166e28..6166e28 100644..100755 --- a/library/msgs/fa.msg +++ b/library/msgs/fa.msg diff --git a/library/msgs/fa_in.msg b/library/msgs/fa_in.msg index ce32f99..ce32f99 100644..100755 --- a/library/msgs/fa_in.msg +++ b/library/msgs/fa_in.msg diff --git a/library/msgs/fa_ir.msg b/library/msgs/fa_ir.msg index 9ce9284..9ce9284 100644..100755 --- a/library/msgs/fa_ir.msg +++ b/library/msgs/fa_ir.msg diff --git a/library/msgs/fi.msg b/library/msgs/fi.msg index 69be367..69be367 100644..100755 --- a/library/msgs/fi.msg +++ b/library/msgs/fi.msg diff --git a/library/msgs/fo.msg b/library/msgs/fo.msg index 1f1794d..1f1794d 100644..100755 --- a/library/msgs/fo.msg +++ b/library/msgs/fo.msg diff --git a/library/msgs/fo_fo.msg b/library/msgs/fo_fo.msg index 2392b8e..2392b8e 100644..100755 --- a/library/msgs/fo_fo.msg +++ b/library/msgs/fo_fo.msg diff --git a/library/msgs/fr.msg b/library/msgs/fr.msg index a274468..a274468 100644..100755 --- a/library/msgs/fr.msg +++ b/library/msgs/fr.msg diff --git a/library/msgs/fr_be.msg b/library/msgs/fr_be.msg index cdb13bd..cdb13bd 100644..100755 --- a/library/msgs/fr_be.msg +++ b/library/msgs/fr_be.msg diff --git a/library/msgs/fr_ca.msg b/library/msgs/fr_ca.msg index 00ccfff..00ccfff 100644..100755 --- a/library/msgs/fr_ca.msg +++ b/library/msgs/fr_ca.msg diff --git a/library/msgs/fr_ch.msg b/library/msgs/fr_ch.msg index 7e2bac7..7e2bac7 100644..100755 --- a/library/msgs/fr_ch.msg +++ b/library/msgs/fr_ch.msg diff --git a/library/msgs/ga.msg b/library/msgs/ga.msg index 056c9a0..056c9a0 100644..100755 --- a/library/msgs/ga.msg +++ b/library/msgs/ga.msg diff --git a/library/msgs/ga_ie.msg b/library/msgs/ga_ie.msg index b6acbbc..b6acbbc 100644..100755 --- a/library/msgs/ga_ie.msg +++ b/library/msgs/ga_ie.msg diff --git a/library/msgs/gl.msg b/library/msgs/gl.msg index c2fefc9..c2fefc9 100644..100755 --- a/library/msgs/gl.msg +++ b/library/msgs/gl.msg diff --git a/library/msgs/gl_es.msg b/library/msgs/gl_es.msg index d4ed270..d4ed270 100644..100755 --- a/library/msgs/gl_es.msg +++ b/library/msgs/gl_es.msg diff --git a/library/msgs/gv.msg b/library/msgs/gv.msg index 7d332ad..7d332ad 100644..100755 --- a/library/msgs/gv.msg +++ b/library/msgs/gv.msg diff --git a/library/msgs/gv_gb.msg b/library/msgs/gv_gb.msg index 5e96e6f..5e96e6f 100644..100755 --- a/library/msgs/gv_gb.msg +++ b/library/msgs/gv_gb.msg diff --git a/library/msgs/he.msg b/library/msgs/he.msg index 13a81b7..13a81b7 100644..100755 --- a/library/msgs/he.msg +++ b/library/msgs/he.msg diff --git a/library/msgs/hi.msg b/library/msgs/hi.msg index 18c8bf0..18c8bf0 100644..100755 --- a/library/msgs/hi.msg +++ b/library/msgs/hi.msg diff --git a/library/msgs/hi_in.msg b/library/msgs/hi_in.msg index 239793f..239793f 100644..100755 --- a/library/msgs/hi_in.msg +++ b/library/msgs/hi_in.msg diff --git a/library/msgs/hr.msg b/library/msgs/hr.msg index 30491e1..30491e1 100644..100755 --- a/library/msgs/hr.msg +++ b/library/msgs/hr.msg diff --git a/library/msgs/hu.msg b/library/msgs/hu.msg index 46776dd..46776dd 100644..100755 --- a/library/msgs/hu.msg +++ b/library/msgs/hu.msg diff --git a/library/msgs/id.msg b/library/msgs/id.msg index 17c6bb5..17c6bb5 100644..100755 --- a/library/msgs/id.msg +++ b/library/msgs/id.msg diff --git a/library/msgs/id_id.msg b/library/msgs/id_id.msg index bb672c1..bb672c1 100644..100755 --- a/library/msgs/id_id.msg +++ b/library/msgs/id_id.msg diff --git a/library/msgs/is.msg b/library/msgs/is.msg index a369b89..a369b89 100644..100755 --- a/library/msgs/is.msg +++ b/library/msgs/is.msg diff --git a/library/msgs/it.msg b/library/msgs/it.msg index e51aee2..e51aee2 100644..100755 --- a/library/msgs/it.msg +++ b/library/msgs/it.msg diff --git a/library/msgs/it_ch.msg b/library/msgs/it_ch.msg index b36ed36..b36ed36 100644..100755 --- a/library/msgs/it_ch.msg +++ b/library/msgs/it_ch.msg diff --git a/library/msgs/ja.msg b/library/msgs/ja.msg index 76b5fa4..76b5fa4 100644..100755 --- a/library/msgs/ja.msg +++ b/library/msgs/ja.msg diff --git a/library/msgs/kl.msg b/library/msgs/kl.msg index d877bfe..d877bfe 100644..100755 --- a/library/msgs/kl.msg +++ b/library/msgs/kl.msg diff --git a/library/msgs/kl_gl.msg b/library/msgs/kl_gl.msg index 403aa10..403aa10 100644..100755 --- a/library/msgs/kl_gl.msg +++ b/library/msgs/kl_gl.msg diff --git a/library/msgs/ko.msg b/library/msgs/ko.msg index 817c2e7..817c2e7 100644..100755 --- a/library/msgs/ko.msg +++ b/library/msgs/ko.msg diff --git a/library/msgs/ko_kr.msg b/library/msgs/ko_kr.msg index f23bd6b..f23bd6b 100644..100755 --- a/library/msgs/ko_kr.msg +++ b/library/msgs/ko_kr.msg diff --git a/library/msgs/kok.msg b/library/msgs/kok.msg index 231853b..231853b 100644..100755 --- a/library/msgs/kok.msg +++ b/library/msgs/kok.msg diff --git a/library/msgs/kok_in.msg b/library/msgs/kok_in.msg index abcb1ff..abcb1ff 100644..100755 --- a/library/msgs/kok_in.msg +++ b/library/msgs/kok_in.msg diff --git a/library/msgs/kw.msg b/library/msgs/kw.msg index aaf79b3..aaf79b3 100644..100755 --- a/library/msgs/kw.msg +++ b/library/msgs/kw.msg diff --git a/library/msgs/kw_gb.msg b/library/msgs/kw_gb.msg index 2967680..2967680 100644..100755 --- a/library/msgs/kw_gb.msg +++ b/library/msgs/kw_gb.msg diff --git a/library/msgs/lt.msg b/library/msgs/lt.msg index 15829a9..15829a9 100644..100755 --- a/library/msgs/lt.msg +++ b/library/msgs/lt.msg diff --git a/library/msgs/lv.msg b/library/msgs/lv.msg index 730fd33..730fd33 100644..100755 --- a/library/msgs/lv.msg +++ b/library/msgs/lv.msg diff --git a/library/msgs/mk.msg b/library/msgs/mk.msg index 9b7bd9d..9b7bd9d 100644..100755 --- a/library/msgs/mk.msg +++ b/library/msgs/mk.msg diff --git a/library/msgs/mr.msg b/library/msgs/mr.msg index e475615..e475615 100644..100755 --- a/library/msgs/mr.msg +++ b/library/msgs/mr.msg diff --git a/library/msgs/mr_in.msg b/library/msgs/mr_in.msg index 1889da5..1889da5 100644..100755 --- a/library/msgs/mr_in.msg +++ b/library/msgs/mr_in.msg diff --git a/library/msgs/ms.msg b/library/msgs/ms.msg index e954431..e954431 100644..100755 --- a/library/msgs/ms.msg +++ b/library/msgs/ms.msg diff --git a/library/msgs/ms_my.msg b/library/msgs/ms_my.msg index c1f93d4..c1f93d4 100644..100755 --- a/library/msgs/ms_my.msg +++ b/library/msgs/ms_my.msg diff --git a/library/msgs/mt.msg b/library/msgs/mt.msg index c479e47..c479e47 100644..100755 --- a/library/msgs/mt.msg +++ b/library/msgs/mt.msg diff --git a/library/msgs/nb.msg b/library/msgs/nb.msg index 4dd76c7..4dd76c7 100644..100755 --- a/library/msgs/nb.msg +++ b/library/msgs/nb.msg diff --git a/library/msgs/nl.msg b/library/msgs/nl.msg index 4c5c675..4c5c675 100644..100755 --- a/library/msgs/nl.msg +++ b/library/msgs/nl.msg diff --git a/library/msgs/nl_be.msg b/library/msgs/nl_be.msg index 4b19670..4b19670 100644..100755 --- a/library/msgs/nl_be.msg +++ b/library/msgs/nl_be.msg diff --git a/library/msgs/nn.msg b/library/msgs/nn.msg index b61a2dd..b61a2dd 100644..100755 --- a/library/msgs/nn.msg +++ b/library/msgs/nn.msg diff --git a/library/msgs/pl.msg b/library/msgs/pl.msg index 821eea7..821eea7 100644..100755 --- a/library/msgs/pl.msg +++ b/library/msgs/pl.msg diff --git a/library/msgs/pt.msg b/library/msgs/pt.msg index 425c1f6..425c1f6 100644..100755 --- a/library/msgs/pt.msg +++ b/library/msgs/pt.msg diff --git a/library/msgs/pt_br.msg b/library/msgs/pt_br.msg index 8684327..8684327 100644..100755 --- a/library/msgs/pt_br.msg +++ b/library/msgs/pt_br.msg diff --git a/library/msgs/ro.msg b/library/msgs/ro.msg index f4452ba..f4452ba 100644..100755 --- a/library/msgs/ro.msg +++ b/library/msgs/ro.msg diff --git a/library/msgs/ru.msg b/library/msgs/ru.msg index 983a253..983a253 100644..100755 --- a/library/msgs/ru.msg +++ b/library/msgs/ru.msg diff --git a/library/msgs/ru_ua.msg b/library/msgs/ru_ua.msg index 6e1f8a8..6e1f8a8 100644..100755 --- a/library/msgs/ru_ua.msg +++ b/library/msgs/ru_ua.msg diff --git a/library/msgs/sh.msg b/library/msgs/sh.msg index 2e4143d..2e4143d 100644..100755 --- a/library/msgs/sh.msg +++ b/library/msgs/sh.msg diff --git a/library/msgs/sk.msg b/library/msgs/sk.msg index dc6f6b6..dc6f6b6 100644..100755 --- a/library/msgs/sk.msg +++ b/library/msgs/sk.msg diff --git a/library/msgs/sl.msg b/library/msgs/sl.msg index 2ee0a03..2ee0a03 100644..100755 --- a/library/msgs/sl.msg +++ b/library/msgs/sl.msg diff --git a/library/msgs/sq.msg b/library/msgs/sq.msg index 65da407..65da407 100644..100755 --- a/library/msgs/sq.msg +++ b/library/msgs/sq.msg diff --git a/library/msgs/sr.msg b/library/msgs/sr.msg index 3d84d6c..3d84d6c 100644..100755 --- a/library/msgs/sr.msg +++ b/library/msgs/sr.msg diff --git a/library/msgs/sv.msg b/library/msgs/sv.msg index 5716092..5716092 100644..100755 --- a/library/msgs/sv.msg +++ b/library/msgs/sv.msg diff --git a/library/msgs/sw.msg b/library/msgs/sw.msg index b888b43..b888b43 100644..100755 --- a/library/msgs/sw.msg +++ b/library/msgs/sw.msg diff --git a/library/msgs/ta.msg b/library/msgs/ta.msg index ea62552..ea62552 100644..100755 --- a/library/msgs/ta.msg +++ b/library/msgs/ta.msg diff --git a/library/msgs/ta_in.msg b/library/msgs/ta_in.msg index 24590ac..24590ac 100644..100755 --- a/library/msgs/ta_in.msg +++ b/library/msgs/ta_in.msg diff --git a/library/msgs/te.msg b/library/msgs/te.msg index f35ece4..f35ece4 100644..100755 --- a/library/msgs/te.msg +++ b/library/msgs/te.msg diff --git a/library/msgs/te_in.msg b/library/msgs/te_in.msg index 84dd2b3..84dd2b3 100644..100755 --- a/library/msgs/te_in.msg +++ b/library/msgs/te_in.msg diff --git a/library/msgs/th.msg b/library/msgs/th.msg index edaa149..edaa149 100644..100755 --- a/library/msgs/th.msg +++ b/library/msgs/th.msg diff --git a/library/msgs/tr.msg b/library/msgs/tr.msg index 12869ee..12869ee 100644..100755 --- a/library/msgs/tr.msg +++ b/library/msgs/tr.msg diff --git a/library/msgs/uk.msg b/library/msgs/uk.msg index 42eb095..42eb095 100644..100755 --- a/library/msgs/uk.msg +++ b/library/msgs/uk.msg diff --git a/library/msgs/vi.msg b/library/msgs/vi.msg index 3437ebf..3437ebf 100644..100755 --- a/library/msgs/vi.msg +++ b/library/msgs/vi.msg diff --git a/library/msgs/zh.msg b/library/msgs/zh.msg index 9c1d08b..9c1d08b 100644..100755 --- a/library/msgs/zh.msg +++ b/library/msgs/zh.msg diff --git a/library/msgs/zh_cn.msg b/library/msgs/zh_cn.msg index da2869a..da2869a 100644..100755 --- a/library/msgs/zh_cn.msg +++ b/library/msgs/zh_cn.msg diff --git a/library/msgs/zh_hk.msg b/library/msgs/zh_hk.msg index 7f1b181..7f1b181 100644..100755 --- a/library/msgs/zh_hk.msg +++ b/library/msgs/zh_hk.msg diff --git a/library/msgs/zh_sg.msg b/library/msgs/zh_sg.msg index 690edf7..690edf7 100644..100755 --- a/library/msgs/zh_sg.msg +++ b/library/msgs/zh_sg.msg diff --git a/library/msgs/zh_tw.msg b/library/msgs/zh_tw.msg index 17a6dd7..17a6dd7 100644..100755 --- a/library/msgs/zh_tw.msg +++ b/library/msgs/zh_tw.msg diff --git a/library/tzdata/Africa/Asmara b/library/tzdata/Africa/Asmara index 3d33c94..3d33c94 100644..100755 --- a/library/tzdata/Africa/Asmara +++ b/library/tzdata/Africa/Asmara diff --git a/library/tzdata/America/Atikokan b/library/tzdata/America/Atikokan index e72b04f..e72b04f 100644..100755 --- a/library/tzdata/America/Atikokan +++ b/library/tzdata/America/Atikokan diff --git a/library/tzdata/America/Blanc-Sablon b/library/tzdata/America/Blanc-Sablon index d5485e8..d5485e8 100644..100755 --- a/library/tzdata/America/Blanc-Sablon +++ b/library/tzdata/America/Blanc-Sablon diff --git a/library/tzdata/America/Indiana/Petersburg b/library/tzdata/America/Indiana/Petersburg index 6992bfc..6992bfc 100644..100755 --- a/library/tzdata/America/Indiana/Petersburg +++ b/library/tzdata/America/Indiana/Petersburg diff --git a/library/tzdata/America/Indiana/Tell_City b/library/tzdata/America/Indiana/Tell_City index 9eebcf7..9eebcf7 100644..100755 --- a/library/tzdata/America/Indiana/Tell_City +++ b/library/tzdata/America/Indiana/Tell_City diff --git a/library/tzdata/America/Indiana/Vincennes b/library/tzdata/America/Indiana/Vincennes index 1af7fc9..1af7fc9 100644..100755 --- a/library/tzdata/America/Indiana/Vincennes +++ b/library/tzdata/America/Indiana/Vincennes diff --git a/library/tzdata/America/Indiana/Winamac b/library/tzdata/America/Indiana/Winamac index fb6cd37..fb6cd37 100644..100755 --- a/library/tzdata/America/Indiana/Winamac +++ b/library/tzdata/America/Indiana/Winamac diff --git a/library/tzdata/America/Moncton b/library/tzdata/America/Moncton index d286c88..d286c88 100644..100755 --- a/library/tzdata/America/Moncton +++ b/library/tzdata/America/Moncton diff --git a/library/tzdata/America/North_Dakota/New_Salem b/library/tzdata/America/North_Dakota/New_Salem index 5a9d229..5a9d229 100644..100755 --- a/library/tzdata/America/North_Dakota/New_Salem +++ b/library/tzdata/America/North_Dakota/New_Salem diff --git a/library/tzdata/America/Resolute b/library/tzdata/America/Resolute index a9881b4..a9881b4 100644..100755 --- a/library/tzdata/America/Resolute +++ b/library/tzdata/America/Resolute diff --git a/library/tzdata/Atlantic/Faroe b/library/tzdata/Atlantic/Faroe index d2c314a..d2c314a 100644..100755 --- a/library/tzdata/Atlantic/Faroe +++ b/library/tzdata/Atlantic/Faroe diff --git a/library/tzdata/Australia/Eucla b/library/tzdata/Australia/Eucla index 8008980..8008980 100644..100755 --- a/library/tzdata/Australia/Eucla +++ b/library/tzdata/Australia/Eucla diff --git a/library/tzdata/Europe/Guernsey b/library/tzdata/Europe/Guernsey index 4372c64..4372c64 100644..100755 --- a/library/tzdata/Europe/Guernsey +++ b/library/tzdata/Europe/Guernsey diff --git a/library/tzdata/Europe/Isle_of_Man b/library/tzdata/Europe/Isle_of_Man index 870ac45..870ac45 100644..100755 --- a/library/tzdata/Europe/Isle_of_Man +++ b/library/tzdata/Europe/Isle_of_Man diff --git a/library/tzdata/Europe/Jersey b/library/tzdata/Europe/Jersey index e4da512..e4da512 100644..100755 --- a/library/tzdata/Europe/Jersey +++ b/library/tzdata/Europe/Jersey diff --git a/library/tzdata/Europe/Podgorica b/library/tzdata/Europe/Podgorica index f4f9066..f4f9066 100644..100755 --- a/library/tzdata/Europe/Podgorica +++ b/library/tzdata/Europe/Podgorica diff --git a/library/tzdata/Europe/Volgograd b/library/tzdata/Europe/Volgograd index 3938683..3938683 100644..100755 --- a/library/tzdata/Europe/Volgograd +++ b/library/tzdata/Europe/Volgograd |