瀏覽代碼

Add files via upload

Daniel Voipan 5 年之前
父節點
當前提交
346e0ab05d

+ 71 - 15
BlackTools.tcl

@@ -23,20 +23,20 @@
 #              + Script updated : 08.05.2018 22:13 PM (Romanian TimeZone) #
 ###########################################################################
 #                                                                         #
-#                       #####    ######     #####                         #
-#                           #    #              #                         #
-#                           #    #              #                         #
+#                       #####    ######     #                             #
+#                           #    #          #                             #
+#                           #    #          #                             #
 #                       ####     ######     #####                         #
 #                       #             #         #                         #
 #                       #             #         #                         #
-#                       #####  # ######  #  #####                         #
+#                       #####  # ######  #      #                         #
 #                                                                         #
 #                                                                         #
 #                   THE    NEXT    GENERATION    TCL                      #
 #                                                                         #
 #                      - #TCL-HELP @ UNDERNET -     	                  #
 #                                                                         #
-#			      Copyright 2008 - 2020 @ WwW.TCLScripts.NET  #
+#			      Copyright 2008 - 2021 @ WwW.TCLScripts.NET 			  #
 #                                                                         #
 ###########################################################################
 #                                                                         #
@@ -62,7 +62,7 @@
 #                                                                         #
 #  Special thanks to:                                                     #
 #                   o Time2Go [ #Tcl-Help Admin ]                         #
-#		    o Florian [ florian@tclscripts.net ]                  #
+#		  		    o Florian [ florian@tclscripts.net ]               	  #
 #                     without whom this script would not have gone so far.#
 # -------                                                         ------- #
 #  Thanks to the many people who have contributed over the years, in a    #
@@ -94,8 +94,38 @@
 set black(dirname) "scripts"
 
 ###########################################################################
-#--------------------------- Dns Host Excepts ----------------------------#
-###								        ###
+#-------------------------- AutoUpdate Module ----------------------------#
+###																		###
+
+###
+#How do you want for the update to be made
+# 0 - autoupdate on TIME interval and by command
+# 1 - update ONLY on command
+
+set black(update_type) "1"
+
+###
+#Do you want the eggdrop to send NOTE to OWNERS if a new update is found?
+# 0 - no
+# 1 - yes
+
+set black(update_note) "1"
+
+###
+#Time interval check (<x>m (minutes), <x>h (hours), <x>d (days))
+
+set black(update_time_check) "60"
+
+###########################################################################
+#-------------------------------- Dns Host  ------------------------------#
+###								        								###
+
+###
+#Enable DNS-onjoin ? 0 - no ; 1 - yes (please be advised that it will make 
+#the bot a bit slower on big channels with lot of joins)
+
+set black(dns_onjoin) "0"
+
 #This host excepts will not receive DNS onjoin, onban etc to improve the
 #performance of the eggdrop.
 
@@ -108,12 +138,13 @@ set black(dns:host_excepts) {
 "10.101.*"
 "172.29.7.*"
 }
+
 ###########################################################################
 #------------------------ Home Chan (Optional) ---------------------------#
 # Here you set your eggdrop's homechan. If you modify here the eggdrop    #
 #will join homechan. If not leave it "#no_home_chan" or "" (empty)        #
 ###									###
-set black(homechan) "#no_home_chan"
+set black(homechan) "#bt"
 
 ###########################################################################
 #---------------------------- First Char ---------------------------------#
@@ -127,7 +158,7 @@ set black(cmdchar) "! . ` \^"
 ###									###
 #Default language of the script ( RO / EN )
 
-set black(default_lang) "RO"
+set black(default_lang) "EN"
 
 ###########################################################################
 #-------------------------- Default host ---------------------------------#
@@ -140,7 +171,7 @@ set black(default_lang) "RO"
 #4 - nick!*@*
 #5 - *!user@*
 
-set black(hello:mask) "2"
+set black(hello:mask) "1"
 
 ###########################################################################
 #------------------------ Default Output Method --------------------------#
@@ -227,6 +258,21 @@ set black(notice:flood) "3:5"
 
 set black(notice:flood:notc_time) "10"
 
+###########################################################################
+#-------------------------- Chanserv MASSBAN -----------------------------#
+#Time to execute chanserv suspend (must have +400 access)
+
+set black(chanserv:suspend_time) "1d"
+
+#Level to execute chanserv suspend (must have +400 access)
+
+set black(chanserv:suspend_level) "400"
+
+#How many percent from channel users the ban should cover in order for
+#eggdrop to identify as being a massban
+
+set black(chanserv:percent_ban) "20%"
+
 ###########################################################################
 #--------------------------- Join Flood ----------------------------------#
 ###									###
@@ -311,11 +357,11 @@ set black(hostchanserv) "x@channels.undernet.org"
 
 #--------------------------- Chanserv User -------------------------------#
 
-set black(username) "Xusername"
+set black(username) "noxcape"
 
 #--------------------------- Chanserv Pass -------------------------------#
 
-set black(password) "Xpassword"
+set black(password) "191926"
 
 #----------------------------- Login Mode --------------------------------#
 
@@ -372,6 +418,7 @@ set black(webchat_hosts) {
 "*!*@195.154.52.250"
 "*!*@207.192.75.252"
 "*!*@212.83.148.225"
+"*!*@aaa"
 }
 
 ###########################################################################
@@ -1687,13 +1734,20 @@ set black(exempt:default_time) "0"
 
 set black(name) "BlackToolS"
 set black(author) "BLaCkShaDoW"
-set black(vers) "2.5.3"
+set black(vers) "2.5.4"
 set black(site) "wWw.TclScriptS.NeT"
+set black(current_modif) "1613241542"
 
 	bind evnt - init-server loginpublic
 	bind time - "* * * * *" timer:login:check
  
- set black(loader_error) [catch {source $black(dirname)/BlackTools/BT.Loader.tcl} black(loader_error_stats)]
+if {[info exists black(backup_update)]} {
+	set black(backdir) $black(backup_dir)
+} else {
+	set black(backdir) $black(dirname)
+}
+
+ set black(loader_error) [catch {source $black(backdir)/BlackTools/BT.Loader.tcl} black(loader_error_stats)]
 
 if {$black(loader_error) == "1"} {
 	die "\[BT\] Error. Couldn't load the \"BT Loader\". Reason: \"$black(loader_error_stats)\""
@@ -1743,3 +1797,5 @@ if {[info exists black(current_lang)]} {
 ###########################################################################
 ##       Copyright (c) 2008-2018 Daniel Voipan (aka BLaCkShaDoW)         ##
 ###########################################################################
+
+

+ 78 - 0
BlackTools/Addons/github.tcl

@@ -0,0 +1,78 @@
+#!/usr/bin/env tclsh
+# file github/github.tcl
+#https://wiki.tcl-lang.org/page/github%3A%3Agithub
+
+# chicken and egg problem we need non-standard packages tls and json ...
+package require tls
+package require http
+::http::register https 443 ::tls::socket
+
+namespace eval ::github {
+    variable libdir [file normalize [file join [file dirname [info script]] ..]]
+    if {[lsearch $::auto_path $libdir] == -1} {
+        lappend auto_path $libdir
+    }
+} 
+
+# I already placed the json folder below of the github folder
+package require json
+package provide github::github 0.2
+package provide github 0.2
+
+# Tcl package download
+proc ::github::github {cmd owner repo folder} {
+    variable libdir
+    set url https://api.github.com/repos/$owner/$repo/contents/
+    #puts $url
+    #puts [lindex $d 1]
+    download $url $folder
+}
+
+# Folder download
+proc ::github::download {url folder {debug true}} {
+    if {![file exists $folder]} {
+        file mkdir $folder
+    }
+    set data [http::data [http::geturl $url]]
+    set d [json::json2dict $data]
+    set l [llength $d]
+    set files [list]
+    for {set i 0} {$i < $l} {incr i 1} {
+        set dic [dict create {*}[lindex $d $i]]
+        set file [dict get $dic download_url]
+        set type [dict get $dic type]
+        if {$file eq "null" &&  $type eq "dir"} {
+            set file [dict get $dic url]
+            set file [regsub {.ref=master} $file ""]
+        }
+        lappend files [list $type $file]
+    }
+
+    # TODO subfolders (done)
+    foreach item $files {
+        set file [lindex $item 1]
+        set type [lindex $item 0]
+        if {$debug} {
+            puts "fetching $file"
+        }
+        if {$type eq "file"} {
+            set fname [file tail $file]
+            set fname [file join $folder $fname]
+            set f [open $fname w]
+            fconfigure $f -translation binary
+            set tok [http::geturl $file -channel $f]
+            set Stat [::http::status $tok]
+            flush $f
+            close $f
+            http::cleanup $tok
+        } else {
+            if {$debug} {
+                puts "fetch new folder $file ..."
+            }
+            set nfolder [file join $folder [file tail $file]]
+            download $file $nfolder $debug
+        }
+    }
+    
+}
+

+ 1506 - 0
BlackTools/Addons/http.tcl

@@ -0,0 +1,1506 @@
+# http.tcl --
+#
+#	Client-side HTTP for GET, POST, and HEAD commands. These routines can
+#	be used in untrusted code that uses the Safesock security policy.
+#	These procedures use a callback interface to avoid using vwait, which
+#	is not defined in the safe base.
+#
+# See the file "license.terms" for information on usage and redistribution of
+# this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+package require Tcl 8.6
+# Keep this in sync with pkgIndex.tcl and with the install directories in
+# Makefiles
+package provide http 2.8.5
+
+namespace eval http {
+    # Allow resourcing to not clobber existing data
+
+    variable http
+    if {![info exists http]} {
+	array set http {
+	    -accept */*
+	    -proxyhost {}
+	    -proxyport {}
+	    -proxyfilter http::ProxyRequired
+	    -urlencoding utf-8
+	}
+	# We need a useragent string of this style or various servers will refuse to
+	# send us compressed content even when we ask for it. This follows the
+	# de-facto layout of user-agent strings in current browsers.
+	set http(-useragent) "Mozilla/5.0\
+            ([string totitle $::tcl_platform(platform)]; U;\
+            $::tcl_platform(os) $::tcl_platform(osVersion))\
+            http/[package provide http] Tcl/[package provide Tcl]"
+    }
+
+    proc init {} {
+	# Set up the map for quoting chars. RFC3986 Section 2.3 say percent
+	# encode all except: "... percent-encoded octets in the ranges of
+	# ALPHA (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D), period
+	# (%2E), underscore (%5F), or tilde (%7E) should not be created by URI
+	# producers ..."
+	for {set i 0} {$i <= 256} {incr i} {
+	    set c [format %c $i]
+	    if {![string match {[-._~a-zA-Z0-9]} $c]} {
+		set map($c) %[format %.2X $i]
+	    }
+	}
+	# These are handled specially
+	set map(\n) %0D%0A
+	variable formMap [array get map]
+
+	# Create a map for HTTP/1.1 open sockets
+	variable socketmap
+	if {[info exists socketmap]} {
+	    # Close but don't remove open sockets on re-init
+	    foreach {url sock} [array get socketmap] {
+		catch {close $sock}
+	    }
+	}
+	array set socketmap {}
+    }
+    init
+
+    variable urlTypes
+    if {![info exists urlTypes]} {
+	set urlTypes(http) [list 80 ::socket]
+    }
+
+    variable encodings [string tolower [encoding names]]
+    # This can be changed, but iso8859-1 is the RFC standard.
+    variable defaultCharset
+    if {![info exists defaultCharset]} {
+	set defaultCharset "iso8859-1"
+    }
+
+    # Force RFC 3986 strictness in geturl url verification?
+    variable strict
+    if {![info exists strict]} {
+	set strict 1
+    }
+
+    # Let user control default keepalive for compatibility
+    variable defaultKeepalive
+    if {![info exists defaultKeepalive]} {
+	set defaultKeepalive 0
+    }
+
+    namespace export geturl config reset wait formatQuery register unregister
+    # Useful, but not exported: data size status code
+}
+
+# http::Log --
+#
+#	Debugging output -- define this to observe HTTP/1.1 socket usage.
+#	Should echo any args received.
+#
+# Arguments:
+#     msg	Message to output
+#
+if {[info command http::Log] eq {}} {proc http::Log {args} {}}
+
+# http::register --
+#
+#     See documentation for details.
+#
+# Arguments:
+#     proto	URL protocol prefix, e.g. https
+#     port	Default port for protocol
+#     command	Command to use to create socket
+# Results:
+#     list of port and command that was registered.
+
+proc http::register {proto port command} {
+    variable urlTypes
+    set urlTypes($proto) [list $port $command]
+}
+
+# http::unregister --
+#
+#     Unregisters URL protocol handler
+#
+# Arguments:
+#     proto	URL protocol prefix, e.g. https
+# Results:
+#     list of port and command that was unregistered.
+
+proc http::unregister {proto} {
+    variable urlTypes
+    if {![info exists urlTypes($proto)]} {
+	return -code error "unsupported url type \"$proto\""
+    }
+    set old $urlTypes($proto)
+    unset urlTypes($proto)
+    return $old
+}
+
+# http::config --
+#
+#	See documentation for details.
+#
+# Arguments:
+#	args		Options parsed by the procedure.
+# Results:
+#        TODO
+
+proc http::config {args} {
+    variable http
+    set options [lsort [array names http -*]]
+    set usage [join $options ", "]
+    if {[llength $args] == 0} {
+	set result {}
+	foreach name $options {
+	    lappend result $name $http($name)
+	}
+	return $result
+    }
+    set options [string map {- ""} $options]
+    set pat ^-(?:[join $options |])$
+    if {[llength $args] == 1} {
+	set flag [lindex $args 0]
+	if {![regexp -- $pat $flag]} {
+	    return -code error "Unknown option $flag, must be: $usage"
+	}
+	return $http($flag)
+    } else {
+	foreach {flag value} $args {
+	    if {![regexp -- $pat $flag]} {
+		return -code error "Unknown option $flag, must be: $usage"
+	    }
+	    set http($flag) $value
+	}
+    }
+}
+
+# http::Finish --
+#
+#	Clean up the socket and eval close time callbacks
+#
+# Arguments:
+#	token	    Connection token.
+#	errormsg    (optional) If set, forces status to error.
+#       skipCB      (optional) If set, don't call the -command callback. This
+#		    is useful when geturl wants to throw an exception instead
+#		    of calling the callback. That way, the same error isn't
+#		    reported to two places.
+#
+# Side Effects:
+#        Closes the socket
+
+proc http::Finish {token {errormsg ""} {skipCB 0}} {
+    variable $token
+    upvar 0 $token state
+    global errorInfo errorCode
+    if {$errormsg ne ""} {
+	set state(error) [list $errormsg $errorInfo $errorCode]
+	set state(status) "error"
+    }
+    if {
+	($state(status) eq "timeout") || ($state(status) eq "error") ||
+	([info exists state(connection)] && ($state(connection) eq "close"))
+    } {
+        CloseSocket $state(sock) $token
+    }
+    if {[info exists state(after)]} {
+	after cancel $state(after)
+    }
+    if {[info exists state(-command)] && !$skipCB
+	    && ![info exists state(done-command-cb)]} {
+	set state(done-command-cb) yes
+	if {[catch {eval $state(-command) {$token}} err] && $errormsg eq ""} {
+	    set state(error) [list $err $errorInfo $errorCode]
+	    set state(status) error
+	}
+    }
+}
+
+# http::CloseSocket -
+#
+#	Close a socket and remove it from the persistent sockets table.  If
+#	possible an http token is included here but when we are called from a
+#	fileevent on remote closure we need to find the correct entry - hence
+#	the second section.
+
+proc ::http::CloseSocket {s {token {}}} {
+    variable socketmap
+    catch {fileevent $s readable {}}
+    set conn_id {}
+    if {$token ne ""} {
+        variable $token
+        upvar 0 $token state
+        if {[info exists state(socketinfo)]} {
+	    set conn_id $state(socketinfo)
+        }
+    } else {
+        set map [array get socketmap]
+        set ndx [lsearch -exact $map $s]
+        if {$ndx != -1} {
+	    incr ndx -1
+	    set conn_id [lindex $map $ndx]
+        }
+    }
+    if {$conn_id eq {} || ![info exists socketmap($conn_id)]} {
+        Log "Closing socket $s (no connection info)"
+        if {[catch {close $s} err]} {
+	    Log "Error: $err"
+	}
+    } else {
+	if {[info exists socketmap($conn_id)]} {
+	    Log "Closing connection $conn_id (sock $socketmap($conn_id))"
+	    if {[catch {close $socketmap($conn_id)} err]} {
+		Log "Error: $err"
+	    }
+	    unset socketmap($conn_id)
+	} else {
+	    Log "Cannot close connection $conn_id - no socket in socket map"
+	}
+    }
+}
+
+# http::reset --
+#
+#	See documentation for details.
+#
+# Arguments:
+#	token	Connection token.
+#	why	Status info.
+#
+# Side Effects:
+#       See Finish
+
+proc http::reset {token {why reset}} {
+    variable $token
+    upvar 0 $token state
+    set state(status) $why
+    catch {fileevent $state(sock) readable {}}
+    catch {fileevent $state(sock) writable {}}
+    Finish $token
+    if {[info exists state(error)]} {
+	set errorlist $state(error)
+	unset state
+	eval ::error $errorlist
+    }
+}
+
+# http::geturl --
+#
+#	Establishes a connection to a remote url via http.
+#
+# Arguments:
+#       url		The http URL to goget.
+#       args		Option value pairs. Valid options include:
+#				-blocksize, -validate, -headers, -timeout
+# Results:
+#	Returns a token for this connection. This token is the name of an
+#	array that the caller should unset to garbage collect the state.
+
+proc http::geturl {url args} {
+    variable http
+    variable urlTypes
+    variable defaultCharset
+    variable defaultKeepalive
+    variable strict
+
+    # Initialize the state variable, an array. We'll return the name of this
+    # array as the token for the transaction.
+
+    if {![info exists http(uid)]} {
+	set http(uid) 0
+    }
+    set token [namespace current]::[incr http(uid)]
+    variable $token
+    upvar 0 $token state
+    reset $token
+
+    # Process command options.
+
+    array set state {
+	-binary		false
+	-blocksize	8192
+	-queryblocksize 8192
+	-validate	0
+	-headers	{}
+	-timeout	0
+	-type		application/x-www-form-urlencoded
+	-queryprogress	{}
+	-protocol	1.1
+	binary		0
+	state		connecting
+	meta		{}
+	coding		{}
+	currentsize	0
+	totalsize	0
+	querylength	0
+	queryoffset	0
+	type		text/html
+	body		{}
+	status		""
+	http		""
+	connection	close
+    }
+    set state(-keepalive) $defaultKeepalive
+    set state(-strict) $strict
+    # These flags have their types verified [Bug 811170]
+    array set type {
+	-binary		boolean
+	-blocksize	integer
+	-queryblocksize integer
+	-strict		boolean
+	-timeout	integer
+	-validate	boolean
+    }
+    set state(charset)	$defaultCharset
+    set options {
+	-binary -blocksize -channel -command -handler -headers -keepalive
+	-method -myaddr -progress -protocol -query -queryblocksize
+	-querychannel -queryprogress -strict -timeout -type -validate
+    }
+    set usage [join [lsort $options] ", "]
+    set options [string map {- ""} $options]
+    set pat ^-(?:[join $options |])$
+    foreach {flag value} $args {
+	if {[regexp -- $pat $flag]} {
+	    # Validate numbers
+	    if {
+		[info exists type($flag)] &&
+		![string is $type($flag) -strict $value]
+	    } {
+		unset $token
+		return -code error \
+		    "Bad value for $flag ($value), must be $type($flag)"
+	    }
+	    set state($flag) $value
+	} else {
+	    unset $token
+	    return -code error "Unknown option $flag, can be: $usage"
+	}
+    }
+
+    # Make sure -query and -querychannel aren't both specified
+
+    set isQueryChannel [info exists state(-querychannel)]
+    set isQuery [info exists state(-query)]
+    if {$isQuery && $isQueryChannel} {
+	unset $token
+	return -code error "Can't combine -query and -querychannel options!"
+    }
+
+    # Validate URL, determine the server host and port, and check proxy case
+    # Recognize user:pass@host URLs also, although we do not do anything with
+    # that info yet.
+
+    # URLs have basically four parts.
+    # First, before the colon, is the protocol scheme (e.g. http)
+    # Second, for HTTP-like protocols, is the authority
+    #	The authority is preceded by // and lasts up to (but not including)
+    #	the following / and it identifies up to four parts, of which only one,
+    #	the host, is required (if an authority is present at all). All other
+    #	parts of the authority (user name, password, port number) are optional.
+    # Third is the resource name, which is split into two parts at a ?
+    #	The first part (from the single "/" up to "?") is the path, and the
+    #	second part (from that "?" up to "#") is the query. *HOWEVER*, we do
+    #	not need to separate them; we send the whole lot to the server.
+    # Fourth is the fragment identifier, which is everything after the first
+    #	"#" in the URL. The fragment identifier MUST NOT be sent to the server
+    #	and indeed, we don't bother to validate it (it could be an error to
+    #	pass it in here, but it's cheap to strip).
+    #
+    # An example of a URL that has all the parts:
+    #
+    #     http://jschmoe:xyzzy@www.bogus.net:8000/foo/bar.tml?q=foo#changes
+    #
+    # The "http" is the protocol, the user is "jschmoe", the password is
+    # "xyzzy", the host is "www.bogus.net", the port is "8000", the path is
+    # "/foo/bar.tml", the query is "q=foo", and the fragment is "changes".
+    #
+    # Note that the RE actually combines the user and password parts, as
+    # recommended in RFC 3986. Indeed, that RFC states that putting passwords
+    # in URLs is a Really Bad Idea, something with which I would agree utterly.
+    #
+    # From a validation perspective, we need to ensure that the parts of the
+    # URL that are going to the server are correctly encoded.  This is only
+    # done if $state(-strict) is true (inherited from $::http::strict).
+
+    set URLmatcher {(?x)		# this is _expanded_ syntax
+	^
+	(?: (\w+) : ) ?			# <protocol scheme>
+	(?: //
+	    (?:
+		(
+		    [^@/\#?]+		# <userinfo part of authority>
+		) @
+	    )?
+	    (				# <host part of authority>
+		[^/:\#?]+ |		# host name or IPv4 address
+		\[ [^/\#?]+ \]		# IPv6 address in square brackets
+	    )
+	    (?: : (\d+) )?		# <port part of authority>
+	)?
+	( / [^\#]*)?			# <path> (including query)
+	(?: \# (.*) )?			# <fragment>
+	$
+    }
+
+    # Phase one: parse
+    if {![regexp -- $URLmatcher $url -> proto user host port srvurl]} {
+	unset $token
+	return -code error "Unsupported URL: $url"
+    }
+    # Phase two: validate
+    set host [string trim $host {[]}]; # strip square brackets from IPv6 address
+    if {$host eq ""} {
+	# Caller has to provide a host name; we do not have a "default host"
+	# that would enable us to handle relative URLs.
+	unset $token
+	return -code error "Missing host part: $url"
+	# Note that we don't check the hostname for validity here; if it's
+	# invalid, we'll simply fail to resolve it later on.
+    }
+    if {$port ne "" && $port > 65535} {
+	unset $token
+	return -code error "Invalid port number: $port"
+    }
+    # The user identification and resource identification parts of the URL can
+    # have encoded characters in them; take care!
+    if {$user ne ""} {
+	# Check for validity according to RFC 3986, Appendix A
+	set validityRE {(?xi)
+	    ^
+	    (?: [-\w.~!$&'()*+,;=:] | %[0-9a-f][0-9a-f] )+
+	    $
+	}
+	if {$state(-strict) && ![regexp -- $validityRE $user]} {
+	    unset $token
+	    # Provide a better error message in this error case
+	    if {[regexp {(?i)%(?![0-9a-f][0-9a-f]).?.?} $user bad]} {
+		return -code error \
+			"Illegal encoding character usage \"$bad\" in URL user"
+	    }
+	    return -code error "Illegal characters in URL user"
+	}
+    }
+    if {$srvurl ne ""} {
+	# Check for validity according to RFC 3986, Appendix A
+	set validityRE {(?xi)
+	    ^
+	    # Path part (already must start with / character)
+	    (?:	      [-\w.~!$&'()*+,;=:@/]  | %[0-9a-f][0-9a-f] )*
+	    # Query part (optional, permits ? characters)
+	    (?: \? (?: [-\w.~!$&'()*+,;=:@/?] | %[0-9a-f][0-9a-f] )* )?
+	    $
+	}
+	if {$state(-strict) && ![regexp -- $validityRE $srvurl]} {
+	    unset $token
+	    # Provide a better error message in this error case
+	    if {[regexp {(?i)%(?![0-9a-f][0-9a-f])..} $srvurl bad]} {
+		return -code error \
+		    "Illegal encoding character usage \"$bad\" in URL path"
+	    }
+	    return -code error "Illegal characters in URL path"
+	}
+    } else {
+	set srvurl /
+    }
+    if {$proto eq ""} {
+	set proto http
+    }
+    if {![info exists urlTypes($proto)]} {
+	unset $token
+	return -code error "Unsupported URL type \"$proto\""
+    }
+    set defport [lindex $urlTypes($proto) 0]
+    set defcmd [lindex $urlTypes($proto) 1]
+
+    if {$port eq ""} {
+	set port $defport
+    }
+    if {![catch {$http(-proxyfilter) $host} proxy]} {
+	set phost [lindex $proxy 0]
+	set pport [lindex $proxy 1]
+    }
+
+    # OK, now reassemble into a full URL
+    set url ${proto}://
+    if {$user ne ""} {
+	append url $user
+	append url @
+    }
+    append url $host
+    if {$port != $defport} {
+	append url : $port
+    }
+    append url $srvurl
+    # Don't append the fragment!
+    set state(url) $url
+
+    # If a timeout is specified we set up the after event and arrange for an
+    # asynchronous socket connection.
+
+    set sockopts [list]
+    if {$state(-timeout) > 0} {
+	set state(after) [after $state(-timeout) \
+		[list http::reset $token timeout]]
+	lappend sockopts -async
+    }
+
+    # If we are using the proxy, we must pass in the full URL that includes
+    # the server name.
+
+    if {[info exists phost] && ($phost ne "")} {
+	set srvurl $url
+	set targetAddr [list $phost $pport]
+    } else {
+	set targetAddr [list $host $port]
+    }
+    # Proxy connections aren't shared among different hosts.
+    set state(socketinfo) $host:$port
+
+    # See if we are supposed to use a previously opened channel.
+    if {$state(-keepalive)} {
+	variable socketmap
+	if {[info exists socketmap($state(socketinfo))]} {
+	    if {[catch {fconfigure $socketmap($state(socketinfo))}]} {
+		Log "WARNING: socket for $state(socketinfo) was closed"
+		unset socketmap($state(socketinfo))
+	    } else {
+		set sock $socketmap($state(socketinfo))
+		Log "reusing socket $sock for $state(socketinfo)"
+		catch {fileevent $sock writable {}}
+		catch {fileevent $sock readable {}}
+	    }
+	}
+	# don't automatically close this connection socket
+	set state(connection) {}
+    }
+    if {![info exists sock]} {
+	# Pass -myaddr directly to the socket command
+	if {[info exists state(-myaddr)]} {
+	    lappend sockopts -myaddr $state(-myaddr)
+	}
+        if {[catch {eval $defcmd $sockopts $targetAddr} sock]} {
+	    # something went wrong while trying to establish the connection.
+	    # Clean up after events and such, but DON'T call the command
+	    # callback (if available) because we're going to throw an
+	    # exception from here instead.
+
+	    set state(sock) $sock
+	    Finish $token "" 1
+	    cleanup $token
+	    return -code error $sock
+        }
+    }
+    set state(sock) $sock
+    Log "Using $sock for $state(socketinfo)" \
+        [expr {$state(-keepalive)?"keepalive":""}]
+    if {$state(-keepalive)} {
+        set socketmap($state(socketinfo)) $sock
+    }
+
+    # Wait for the connection to complete.
+
+    if {$state(-timeout) > 0} {
+	fileevent $sock writable [list http::Connect $token]
+	http::wait $token
+
+	if {![info exists state]} {
+	    # If we timed out then Finish has been called and the users
+	    # command callback may have cleaned up the token. If so we end up
+	    # here with nothing left to do.
+	    return $token
+	} elseif {$state(status) eq "error"} {
+	    # Something went wrong while trying to establish the connection.
+	    # Clean up after events and such, but DON'T call the command
+	    # callback (if available) because we're going to throw an
+	    # exception from here instead.
+	    set err [lindex $state(error) 0]
+	    cleanup $token
+	    return -code error $err
+	} elseif {$state(status) ne "connect"} {
+	    # Likely to be connection timeout
+	    return $token
+	}
+	set state(status) ""
+    }
+
+    # Send data in cr-lf format, but accept any line terminators
+
+    fconfigure $sock -translation {auto crlf} -buffersize $state(-blocksize)
+
+    # The following is disallowed in safe interpreters, but the socket is
+    # already in non-blocking mode in that case.
+
+    catch {fconfigure $sock -blocking off}
+    set how GET
+    if {$isQuery} {
+	set state(querylength) [string length $state(-query)]
+	if {$state(querylength) > 0} {
+	    set how POST
+	    set contDone 0
+	} else {
+	    # There's no query data.
+	    unset state(-query)
+	    set isQuery 0
+	}
+    } elseif {$state(-validate)} {
+	set how HEAD
+    } elseif {$isQueryChannel} {
+	set how POST
+	# The query channel must be blocking for the async Write to
+	# work properly.
+	fconfigure $state(-querychannel) -blocking 1 -translation binary
+	set contDone 0
+    }
+    if {[info exists state(-method)] && $state(-method) ne ""} {
+	set how $state(-method)
+    }
+    # We cannot handle chunked encodings with -handler, so force HTTP/1.0
+    # until we can manage this.
+    if {[info exists state(-handler)]} {
+	set state(-protocol) 1.0
+    }
+    if {[catch {
+	puts $sock "$how $srvurl HTTP/$state(-protocol)"
+	puts $sock "Accept: $http(-accept)"
+	array set hdrs $state(-headers)
+	if {[info exists hdrs(Host)]} {
+	    # Allow Host spoofing. [Bug 928154]
+	    puts $sock "Host: $hdrs(Host)"
+	} elseif {$port == $defport} {
+	    # Don't add port in this case, to handle broken servers. [Bug
+	    # #504508]
+	    puts $sock "Host: $host"
+	} else {
+	    puts $sock "Host: $host:$port"
+	}
+	unset hdrs
+	puts $sock "User-Agent: $http(-useragent)"
+        if {$state(-protocol) == 1.0 && $state(-keepalive)} {
+	    puts $sock "Connection: keep-alive"
+        }
+        if {$state(-protocol) > 1.0 && !$state(-keepalive)} {
+	    puts $sock "Connection: close" ;# RFC2616 sec 8.1.2.1
+        }
+        if {[info exists phost] && ($phost ne "") && $state(-keepalive)} {
+	    puts $sock "Proxy-Connection: Keep-Alive"
+        }
+        set accept_encoding_seen 0
+	set content_type_seen 0
+	foreach {key value} $state(-headers) {
+	    if {[string equal -nocase $key "host"]} {
+		continue
+	    }
+	    if {[string equal -nocase $key "accept-encoding"]} {
+		set accept_encoding_seen 1
+	    }
+	    if {[string equal -nocase $key "content-type"]} {
+		set content_type_seen 1
+	    }
+	    set value [string map [list \n "" \r ""] $value]
+	    set key [string trim $key]
+	    if {[string equal -nocase $key "content-length"]} {
+		set contDone 1
+		set state(querylength) $value
+	    }
+	    if {[string length $key]} {
+		puts $sock "$key: $value"
+	    }
+	}
+        if {!$accept_encoding_seen && ![info exists state(-handler)]} {
+	    puts $sock "Accept-Encoding: deflate,gzip,compress"
+        }
+	if {$isQueryChannel && $state(querylength) == 0} {
+	    # Try to determine size of data in channel. If we cannot seek, the
+	    # surrounding catch will trap us
+
+	    set start [tell $state(-querychannel)]
+	    seek $state(-querychannel) 0 end
+	    set state(querylength) \
+		    [expr {[tell $state(-querychannel)] - $start}]
+	    seek $state(-querychannel) $start
+	}
+
+	# Flush the request header and set up the fileevent that will either
+	# push the POST data or read the response.
+	#
+	# fileevent note:
+	#
+	# It is possible to have both the read and write fileevents active at
+	# this point. The only scenario it seems to affect is a server that
+	# closes the connection without reading the POST data. (e.g., early
+	# versions TclHttpd in various error cases). Depending on the
+	# platform, the client may or may not be able to get the response from
+	# the server because of the error it will get trying to write the post
+	# data. Having both fileevents active changes the timing and the
+	# behavior, but no two platforms (among Solaris, Linux, and NT) behave
+	# the same, and none behave all that well in any case. Servers should
+	# always read their POST data if they expect the client to read their
+	# response.
+
+	if {$isQuery || $isQueryChannel} {
+	    if {!$content_type_seen} {
+		puts $sock "Content-Type: $state(-type)"
+	    }
+	    if {!$contDone} {
+		puts $sock "Content-Length: $state(querylength)"
+	    }
+	    puts $sock ""
+	    fconfigure $sock -translation {auto binary}
+	    fileevent $sock writable [list http::Write $token]
+	} else {
+	    puts $sock ""
+	    flush $sock
+	    fileevent $sock readable [list http::Event $sock $token]
+	}
+
+	if {![info exists state(-command)]} {
+	    # geturl does EVERYTHING asynchronously, so if the user calls it
+	    # synchronously, we just do a wait here.
+
+	    wait $token
+	    if {$state(status) eq "error"} {
+		# Something went wrong, so throw the exception, and the
+		# enclosing catch will do cleanup.
+		return -code error [lindex $state(error) 0]
+	    }
+	}
+    } err]} {
+	# The socket probably was never connected, or the connection dropped
+	# later.
+
+	# Clean up after events and such, but DON'T call the command callback
+	# (if available) because we're going to throw an exception from here
+	# instead.
+
+	# if state(status) is error, it means someone's already called Finish
+	# to do the above-described clean up.
+	if {$state(status) ne "error"} {
+	    Finish $token $err 1
+	}
+	cleanup $token
+	return -code error $err
+    }
+
+    return $token
+}
+
+# Data access functions:
+# Data - the URL data
+# Status - the transaction status: ok, reset, eof, timeout
+# Code - the HTTP transaction code, e.g., 200
+# Size - the size of the URL data
+
+proc http::data {token} {
+    variable $token
+    upvar 0 $token state
+    return $state(body)
+}
+proc http::status {token} {
+    if {![info exists $token]} {
+	return "error"
+    }
+    variable $token
+    upvar 0 $token state
+    return $state(status)
+}
+proc http::code {token} {
+    variable $token
+    upvar 0 $token state
+    return $state(http)
+}
+proc http::ncode {token} {
+    variable $token
+    upvar 0 $token state
+    if {[regexp {[0-9]{3}} $state(http) numeric_code]} {
+	return $numeric_code
+    } else {
+	return $state(http)
+    }
+}
+proc http::size {token} {
+    variable $token
+    upvar 0 $token state
+    return $state(currentsize)
+}
+proc http::meta {token} {
+    variable $token
+    upvar 0 $token state
+    return $state(meta)
+}
+proc http::error {token} {
+    variable $token
+    upvar 0 $token state
+    if {[info exists state(error)]} {
+	return $state(error)
+    }
+    return ""
+}
+
+# http::cleanup
+#
+#	Garbage collect the state associated with a transaction
+#
+# Arguments
+#	token	The token returned from http::geturl
+#
+# Side Effects
+#	unsets the state array
+
+proc http::cleanup {token} {
+    variable $token
+    upvar 0 $token state
+    if {[info exists state]} {
+	unset state
+    }
+}
+
+# http::Connect
+#
+#	This callback is made when an asyncronous connection completes.
+#
+# Arguments
+#	token	The token returned from http::geturl
+#
+# Side Effects
+#	Sets the status of the connection, which unblocks
+# 	the waiting geturl call
+
+proc http::Connect {token} {
+    variable $token
+    upvar 0 $token state
+    set err "due to unexpected EOF"
+    if {
+	[eof $state(sock)] ||
+	[set err [fconfigure $state(sock) -error]] ne ""
+    } {
+	Finish $token "connect failed $err" 1
+    } else {
+	set state(status) connect
+	fileevent $state(sock) writable {}
+    }
+    return
+}
+
+# http::Write
+#
+#	Write POST query data to the socket
+#
+# Arguments
+#	token	The token for the connection
+#
+# Side Effects
+#	Write the socket and handle callbacks.
+
+proc http::Write {token} {
+    variable $token
+    upvar 0 $token state
+    set sock $state(sock)
+
+    # Output a block.  Tcl will buffer this if the socket blocks
+    set done 0
+    if {[catch {
+	# Catch I/O errors on dead sockets
+
+	if {[info exists state(-query)]} {
+	    # Chop up large query strings so queryprogress callback can give
+	    # smooth feedback.
+
+	    puts -nonewline $sock \
+		[string range $state(-query) $state(queryoffset) \
+		     [expr {$state(queryoffset) + $state(-queryblocksize) - 1}]]
+	    incr state(queryoffset) $state(-queryblocksize)
+	    if {$state(queryoffset) >= $state(querylength)} {
+		set state(queryoffset) $state(querylength)
+		set done 1
+	    }
+	} else {
+	    # Copy blocks from the query channel
+
+	    set outStr [read $state(-querychannel) $state(-queryblocksize)]
+	    puts -nonewline $sock $outStr
+	    incr state(queryoffset) [string length $outStr]
+	    if {[eof $state(-querychannel)]} {
+		set done 1
+	    }
+	}
+    } err]} {
+	# Do not call Finish here, but instead let the read half of the socket
+	# process whatever server reply there is to get.
+
+	set state(posterror) $err
+	set done 1
+    }
+    if {$done} {
+	catch {flush $sock}
+	fileevent $sock writable {}
+	fileevent $sock readable [list http::Event $sock $token]
+    }
+
+    # Callback to the client after we've completely handled everything.
+
+    if {[string length $state(-queryprogress)]} {
+	eval $state(-queryprogress) \
+	    [list $token $state(querylength) $state(queryoffset)]
+    }
+}
+
+# http::Event
+#
+#	Handle input on the socket
+#
+# Arguments
+#	sock	The socket receiving input.
+#	token	The token returned from http::geturl
+#
+# Side Effects
+#	Read the socket and handle callbacks.
+
+proc http::Event {sock token} {
+    variable $token
+    upvar 0 $token state
+
+    if {![info exists state]} {
+	Log "Event $sock with invalid token '$token' - remote close?"
+	if {![eof $sock]} {
+	    if {[set d [read $sock]] ne ""} {
+		Log "WARNING: additional data left on closed socket"
+	    }
+	}
+	CloseSocket $sock
+	return
+    }
+    if {$state(state) eq "connecting"} {
+	if {[catch {gets $sock state(http)} n]} {
+	    return [Finish $token $n]
+	} elseif {$n >= 0} {
+	    set state(state) "header"
+	}
+    } elseif {$state(state) eq "header"} {
+	if {[catch {gets $sock line} n]} {
+	    return [Finish $token $n]
+	} elseif {$n == 0} {
+	    # We have now read all headers
+	    # We ignore HTTP/1.1 100 Continue returns. RFC2616 sec 8.2.3
+	    if {$state(http) == "" || [lindex $state(http) 1] == 100} {
+		return
+	    }
+
+	    set state(state) body
+
+	    # If doing a HEAD, then we won't get any body
+	    if {$state(-validate)} {
+		Eof $token
+		return
+	    }
+
+	    # For non-chunked transfer we may have no body - in this case we
+	    # may get no further file event if the connection doesn't close
+	    # and no more data is sent. We can tell and must finish up now -
+	    # not later.
+	    if {
+		!(([info exists state(connection)]
+			&& ($state(connection) eq "close"))
+		    || [info exists state(transfer)])
+		&& ($state(totalsize) == 0)
+	    } {
+		Log "body size is 0 and no events likely - complete."
+		Eof $token
+		return
+	    }
+
+	    # We have to use binary translation to count bytes properly.
+	    fconfigure $sock -translation binary
+
+	    if {
+		$state(-binary) || ![string match -nocase text* $state(type)]
+	    } {
+		# Turn off conversions for non-text data
+		set state(binary) 1
+	    }
+	    if {[info exists state(-channel)]} {
+		if {$state(binary) || [llength [ContentEncoding $token]]} {
+		    fconfigure $state(-channel) -translation binary
+		}
+		if {![info exists state(-handler)]} {
+		    # Initiate a sequence of background fcopies
+		    fileevent $sock readable {}
+		    CopyStart $sock $token
+		    return
+		}
+	    }
+	} elseif {$n > 0} {
+	    # Process header lines
+	    if {[regexp -nocase {^([^:]+):(.+)$} $line x key value]} {
+		switch -- [string tolower $key] {
+		    content-type {
+			set state(type) [string trim [string tolower $value]]
+			# grab the optional charset information
+			if {[regexp -nocase \
+				 {charset\s*=\s*\"((?:[^""]|\\\")*)\"} \
+				 $state(type) -> cs]} {
+			    set state(charset) [string map {{\"} \"} $cs]
+			} else {
+			    regexp -nocase {charset\s*=\s*(\S+?);?} \
+				$state(type) -> state(charset)
+			}
+		    }
+		    content-length {
+			set state(totalsize) [string trim $value]
+		    }
+		    content-encoding {
+			set state(coding) [string trim $value]
+		    }
+		    transfer-encoding {
+			set state(transfer) \
+			    [string trim [string tolower $value]]
+		    }
+		    proxy-connection -
+		    connection {
+			set state(connection) \
+			    [string trim [string tolower $value]]
+		    }
+		}
+		lappend state(meta) $key [string trim $value]
+	    }
+	}
+    } else {
+	# Now reading body
+	if {[catch {
+	    if {[info exists state(-handler)]} {
+		set n [eval $state(-handler) [list $sock $token]]
+	    } elseif {[info exists state(transfer_final)]} {
+		set line [getTextLine $sock]
+		set n [string length $line]
+		if {$n > 0} {
+		    Log "found $n bytes following final chunk"
+		    append state(transfer_final) $line
+		} else {
+		    Log "final chunk part"
+		    Eof $token
+		}
+	    } elseif {
+		[info exists state(transfer)]
+		&& $state(transfer) eq "chunked"
+	    } {
+		set size 0
+		set chunk [getTextLine $sock]
+		set n [string length $chunk]
+		if {[string trim $chunk] ne ""} {
+		    scan $chunk %x size
+		    if {$size != 0} {
+			set bl [fconfigure $sock -blocking]
+			fconfigure $sock -blocking 1
+			set chunk [read $sock $size]
+			fconfigure $sock -blocking $bl
+			set n [string length $chunk]
+			if {$n >= 0} {
+			    append state(body) $chunk
+			}
+			if {$size != [string length $chunk]} {
+			    Log "WARNING: mis-sized chunk:\
+				was [string length $chunk], should be $size"
+			}
+			getTextLine $sock
+		    } else {
+			set state(transfer_final) {}
+		    }
+		}
+	    } else {
+		#Log "read non-chunk $state(currentsize) of $state(totalsize)"
+		set block [read $sock $state(-blocksize)]
+		set n [string length $block]
+		if {$n >= 0} {
+		    append state(body) $block
+		}
+	    }
+	    if {[info exists state]} {
+		if {$n >= 0} {
+		    incr state(currentsize) $n
+		}
+		# If Content-Length - check for end of data.
+		if {
+		    ($state(totalsize) > 0)
+		    && ($state(currentsize) >= $state(totalsize))
+		} {
+		    Eof $token
+		}
+	    }
+	} err]} {
+	    return [Finish $token $err]
+	} else {
+	    if {[info exists state(-progress)]} {
+		eval $state(-progress) \
+		    [list $token $state(totalsize) $state(currentsize)]
+	    }
+	}
+    }
+
+    # catch as an Eof above may have closed the socket already
+    if {![catch {eof $sock} eof] && $eof} {
+	if {[info exists $token]} {
+	    set state(connection) close
+	    Eof $token
+	} else {
+	    # open connection closed on a token that has been cleaned up.
+	    CloseSocket $sock
+	}
+	return
+    }
+}
+
+# http::getTextLine --
+#
+#	Get one line with the stream in blocking crlf mode
+#
+# Arguments
+#	sock	The socket receiving input.
+#
+# Results:
+#	The line of text, without trailing newline
+
+proc http::getTextLine {sock} {
+    set tr [fconfigure $sock -translation]
+    set bl [fconfigure $sock -blocking]
+    fconfigure $sock -translation crlf -blocking 1
+    set r [gets $sock]
+    fconfigure $sock -translation $tr -blocking $bl
+    return $r
+}
+
+# http::CopyStart
+#
+#	Error handling wrapper around fcopy
+#
+# Arguments
+#	sock	The socket to copy from
+#	token	The token returned from http::geturl
+#
+# Side Effects
+#	This closes the connection upon error
+
+proc http::CopyStart {sock token {initial 1}} {
+    upvar #0 $token state
+    if {[info exists state(transfer)] && $state(transfer) eq "chunked"} {
+	foreach coding [ContentEncoding $token] {
+	    lappend state(zlib) [zlib stream $coding]
+	}
+	make-transformation-chunked $sock [namespace code [list CopyChunk $token]]
+    } else {
+	if {$initial} {
+	    foreach coding [ContentEncoding $token] {
+		zlib push $coding $sock
+	    }
+	}
+	if {[catch {
+	    fcopy $sock $state(-channel) -size $state(-blocksize) -command \
+		[list http::CopyDone $token]
+	} err]} {
+	    Finish $token $err
+	}
+    }
+}
+
+proc http::CopyChunk {token chunk} {
+    upvar 0 $token state
+    if {[set count [string length $chunk]]} {
+	incr state(currentsize) $count
+	if {[info exists state(zlib)]} {
+	    foreach stream $state(zlib) {
+		set chunk [$stream add $chunk]
+	    }
+	}
+	puts -nonewline $state(-channel) $chunk
+	if {[info exists state(-progress)]} {
+	    eval [linsert $state(-progress) end \
+		      $token $state(totalsize) $state(currentsize)]
+	}
+    } else {
+	Log "CopyChunk Finish $token"
+	if {[info exists state(zlib)]} {
+	    set excess ""
+	    foreach stream $state(zlib) {
+		catch {set excess [$stream add -finalize $excess]}
+	    }
+	    puts -nonewline $state(-channel) $excess
+	    foreach stream $state(zlib) { $stream close }
+	    unset state(zlib)
+	}
+	Eof $token ;# FIX ME: pipelining.
+    }
+}
+
+# http::CopyDone
+#
+#	fcopy completion callback
+#
+# Arguments
+#	token	The token returned from http::geturl
+#	count	The amount transfered
+#
+# Side Effects
+#	Invokes callbacks
+
+proc http::CopyDone {token count {error {}}} {
+    variable $token
+    upvar 0 $token state
+    set sock $state(sock)
+    incr state(currentsize) $count
+    if {[info exists state(-progress)]} {
+	eval $state(-progress) \
+	    [list $token $state(totalsize) $state(currentsize)]
+    }
+    # At this point the token may have been reset
+    if {[string length $error]} {
+	Finish $token $error
+    } elseif {[catch {eof $sock} iseof] || $iseof} {
+	Eof $token
+    } else {
+	CopyStart $sock $token 0
+    }
+}
+
+# http::Eof
+#
+#	Handle eof on the socket
+#
+# Arguments
+#	token	The token returned from http::geturl
+#
+# Side Effects
+#	Clean up the socket
+
+proc http::Eof {token {force 0}} {
+    variable $token
+    upvar 0 $token state
+    if {$state(state) eq "header"} {
+	# Premature eof
+	set state(status) eof
+    } else {
+	set state(status) ok
+    }
+
+    if {[string length $state(body)] > 0} {
+	if {[catch {
+	    foreach coding [ContentEncoding $token] {
+		set state(body) [zlib $coding $state(body)]
+	    }
+	} err]} {
+	    Log "error doing $coding '$state(body)'"
+	    return [Finish $token $err]
+	}
+
+	if {!$state(binary)} {
+	    # If we are getting text, set the incoming channel's encoding
+	    # correctly.  iso8859-1 is the RFC default, but this could be any IANA
+	    # charset.  However, we only know how to convert what we have
+	    # encodings for.
+
+	    set enc [CharsetToEncoding $state(charset)]
+	    if {$enc ne "binary"} {
+		set state(body) [encoding convertfrom $enc $state(body)]
+	    }
+
+	    # Translate text line endings.
+	    set state(body) [string map {\r\n \n \r \n} $state(body)]
+	}
+    }
+    Finish $token
+}
+
+# http::wait --
+#
+#	See documentation for details.
+#
+# Arguments:
+#	token	Connection token.
+#
+# Results:
+#        The status after the wait.
+
+proc http::wait {token} {
+    variable $token
+    upvar 0 $token state
+
+    if {![info exists state(status)] || $state(status) eq ""} {
+	# We must wait on the original variable name, not the upvar alias
+	vwait ${token}(status)
+    }
+
+    return [status $token]
+}
+
+# http::formatQuery --
+#
+#	See documentation for details.  Call http::formatQuery with an even
+#	number of arguments, where the first is a name, the second is a value,
+#	the third is another name, and so on.
+#
+# Arguments:
+#	args	A list of name-value pairs.
+#
+# Results:
+#	TODO
+
+proc http::formatQuery {args} {
+    set result ""
+    set sep ""
+    foreach i $args {
+	append result $sep [mapReply $i]
+	if {$sep eq "="} {
+	    set sep &
+	} else {
+	    set sep =
+	}
+    }
+    return $result
+}
+
+# http::mapReply --
+#
+#	Do x-www-urlencoded character mapping
+#
+# Arguments:
+#	string	The string the needs to be encoded
+#
+# Results:
+#       The encoded string
+
+proc http::mapReply {string} {
+    variable http
+    variable formMap
+
+    # The spec says: "non-alphanumeric characters are replaced by '%HH'". Use
+    # a pre-computed map and [string map] to do the conversion (much faster
+    # than [regsub]/[subst]). [Bug 1020491]
+
+    if {$http(-urlencoding) ne ""} {
+	set string [encoding convertto $http(-urlencoding) $string]
+	return [string map $formMap $string]
+    }
+    set converted [string map $formMap $string]
+    if {[string match "*\[\u0100-\uffff\]*" $converted]} {
+	regexp {[\u0100-\uffff]} $converted badChar
+	# Return this error message for maximum compatability... :^/
+	return -code error \
+	    "can't read \"formMap($badChar)\": no such element in array"
+    }
+    return $converted
+}
+
+# http::ProxyRequired --
+#	Default proxy filter.
+#
+# Arguments:
+#	host	The destination host
+#
+# Results:
+#       The current proxy settings
+
+proc http::ProxyRequired {host} {
+    variable http
+    if {[info exists http(-proxyhost)] && [string length $http(-proxyhost)]} {
+	if {
+	    ![info exists http(-proxyport)] ||
+	    ![string length $http(-proxyport)]
+	} {
+	    set http(-proxyport) 8080
+	}
+	return [list $http(-proxyhost) $http(-proxyport)]
+    }
+}
+
+# http::CharsetToEncoding --
+#
+#	Tries to map a given IANA charset to a tcl encoding.  If no encoding
+#	can be found, returns binary.
+#
+
+proc http::CharsetToEncoding {charset} {
+    variable encodings
+
+    set charset [string tolower $charset]
+    if {[regexp {iso-?8859-([0-9]+)} $charset -> num]} {
+	set encoding "iso8859-$num"
+    } elseif {[regexp {iso-?2022-(jp|kr)} $charset -> ext]} {
+	set encoding "iso2022-$ext"
+    } elseif {[regexp {shift[-_]?js} $charset]} {
+	set encoding "shiftjis"
+    } elseif {[regexp {(?:windows|cp)-?([0-9]+)} $charset -> num]} {
+	set encoding "cp$num"
+    } elseif {$charset eq "us-ascii"} {
+	set encoding "ascii"
+    } elseif {[regexp {(?:iso-?)?lat(?:in)?-?([0-9]+)} $charset -> num]} {
+	switch -- $num {
+	    5 {set encoding "iso8859-9"}
+	    1 - 2 - 3 {
+		set encoding "iso8859-$num"
+	    }
+	}
+    } else {
+	# other charset, like euc-xx, utf-8,...  may directly map to encoding
+	set encoding $charset
+    }
+    set idx [lsearch -exact $encodings $encoding]
+    if {$idx >= 0} {
+	return $encoding
+    } else {
+	return "binary"
+    }
+}
+
+# Return the list of content-encoding transformations we need to do in order.
+proc http::ContentEncoding {token} {
+    upvar 0 $token state
+    set r {}
+    if {[info exists state(coding)]} {
+	foreach coding [split $state(coding) ,] {
+	    switch -exact -- $coding {
+		deflate { lappend r inflate }
+		gzip - x-gzip { lappend r gunzip }
+		compress - x-compress { lappend r decompress }
+		identity {}
+		default {
+		    return -code error "unsupported content-encoding \"$coding\""
+		}
+	    }
+	}
+    }
+    return $r
+}
+
+proc http::make-transformation-chunked {chan command} {
+    set lambda {{chan command} {
+        set data ""
+        set size -1
+        yield
+        while {1} {
+            chan configure $chan -translation {crlf binary}
+            while {[gets $chan line] < 1} { yield }
+            chan configure $chan -translation {binary binary}
+            if {[scan $line %x size] != 1} { return -code error "invalid size: \"$line\"" }
+            set chunk ""
+            while {$size && ![chan eof $chan]} {
+                set part [chan read $chan $size]
+                incr size -[string length $part]
+                append chunk $part
+            }
+            if {[catch {
+		uplevel #0 [linsert $command end $chunk]
+	    }]} {
+		http::Log "Error in callback: $::errorInfo"
+	    }
+            if {[string length $chunk] == 0} {
+		# channel might have been closed in the callback
+                catch {chan event $chan readable {}}
+                return
+            }
+        }
+    }}
+    coroutine dechunk$chan ::apply $lambda $chan $command
+    chan event $chan readable [namespace origin dechunk$chan]
+    return
+}
+
+# Local variables:
+# indent-tabs-mode: t
+# End:

+ 274 - 0
BlackTools/Addons/json.tcl

@@ -0,0 +1,274 @@
+#
+#   JSON parser for Tcl.
+#
+#   See http://www.json.org/ && http://www.ietf.org/rfc/rfc4627.txt
+#
+#   Copyright 2006 ActiveState Software Inc.
+#
+#   $Id: json.tcl,v 1.2 2006/08/25 23:19:53 hobbs Exp $
+#
+
+if {$::tcl_version < 8.5} {
+    package require dict
+}
+
+package provide json 1.0
+
+namespace eval json {}
+
+proc json::getc {{txtvar txt}} {
+    # pop single char off the front of the text
+    upvar 1 $txtvar txt
+    if {$txt eq ""} {
+    	return -code error "unexpected end of text"
+    }
+
+    set c [string index $txt 0]
+    set txt [string range $txt 1 end]
+    return $c
+}
+
+proc json::json2dict {txt} {
+    return [_json2dict]
+}
+
+proc json::_json2dict {{txtvar txt}} {
+    upvar 1 $txtvar txt
+
+    set state TOP
+
+    set txt [string trimleft $txt]
+    while {$txt ne ""} {
+    	set c [string index $txt 0]
+
+    	# skip whitespace
+    	while {[string is space $c]} {
+    	    getc
+    	    set c [string index $txt 0]
+    	}
+
+	if {$c eq "\{"} {
+	    # object
+	    switch -- $state {
+		TOP {
+		    # we are dealing with an Object
+		    getc
+		    set state OBJECT
+		    set dictVal [dict create]
+		}
+		VALUE {
+		    # this object element's value is an Object
+		    dict set dictVal $name [_json2dict]
+		    set state COMMA
+		}
+		LIST {
+		    # next element of list is an Object
+		    lappend listVal [_json2dict]
+		    set state COMMA
+		}
+		default {
+		    return -code error "unexpected open brace in $state mode"
+		}
+	    }
+	} elseif {$c eq "\}"} {
+	    getc
+	    if {$state ne "OBJECT" && $state ne "COMMA"} {
+		return -code error "unexpected close brace in $state mode"
+	    }
+	    return $dictVal
+	} elseif {$c eq ":"} {
+	    # name separator
+	    getc
+
+	    if {$state eq "COLON"} {
+		set state VALUE
+	    } else {
+		return -code error "unexpected colon in $state mode"
+	    }
+	} elseif {$c eq ","} {
+	    # element separator
+	    if {$state eq "COMMA"} {
+		getc
+		if {[info exists listVal]} {
+		    set state LIST
+		} elseif {[info exists dictVal]} {
+		    set state OBJECT
+		}
+	    } else {
+		return -code error "unexpected comma in $state mode"
+	    }
+	} elseif {$c eq "\""} {
+	    # string
+	    # capture quoted string with backslash sequences
+	    set reStr {(?:(?:\")(?:[^\\\"]*(?:\\.[^\\\"]*)*)(?:\"))}
+	    set string ""
+	    if {![regexp $reStr $txt string]} {
+		set txt [string replace $txt 32 end ...]
+		return -code error "invalid formatted string in $txt"
+	    }
+	    set txt [string range $txt [string length $string] end]
+	    # chop off outer ""s and substitute backslashes
+	    # This does more than the RFC-specified backslash sequences,
+	    # but it does cover them all
+	    set string [subst -nocommand -novariable \
+			    [string range $string 1 end-1]]
+
+	    switch -- $state {
+		TOP {
+		    return $string
+		}
+		OBJECT {
+		    set name $string
+		    set state COLON
+		}
+		LIST {
+		    lappend listVal $string
+		    set state COMMA
+		}
+		VALUE {
+		    dict set dictVal $name $string
+		    unset name
+		    set state COMMA
+		}
+	    }
+	} elseif {$c eq "\["} {
+	    # JSON array == Tcl list
+	    switch -- $state {
+		TOP {
+		    getc
+		    set state LIST
+		}
+		LIST {
+		    lappend listVal [_json2dict]
+		    set state COMMA
+		}
+		VALUE {
+		    dict set dictVal $name [_json2dict]
+		    set state COMMA
+		}
+		default {
+		    return -code error "unexpected open bracket in $state mode"
+		}
+	    }
+	} elseif {$c eq "\]"} {
+	    # end of list
+	    getc
+	    if {![info exists listVal]} {
+		#return -code error "unexpected close bracket in $state mode"
+		# must be an empty list
+		return ""
+	    }
+
+	    return $listVal
+	} elseif {0 && $c eq "/"} {
+	    # comment
+	    # XXX: Not in RFC 4627
+	    getc
+	    set c [getc]
+	    switch -- $c {
+		/ {
+		    # // comment form
+		    set i [string first "\n" $txt]
+		    if {$i == -1} {
+			set txt ""
+		    } else {
+			set txt [string range $txt [incr i] end]
+		    }
+		}
+		* {
+		    # /* comment */ form
+		    getc
+		    set i [string first "*/" $txt]
+		    if {$i == -1} {
+			return -code error "incomplete /* comment"
+		    } else {
+			set txt [string range $txt [incr i] end]
+		    }
+		}
+		default {
+		    return -code error "unexpected slash in $state mode"
+		}
+	    }
+	} elseif {[string match {[-0-9]} $c]} {
+	    # one last check for a number, no leading zeros allowed,
+	    # but it may be 0.xxx
+	    string is double -failindex last $txt
+	    if {$last > 0} {
+		set num [string range $txt 0 [expr {$last - 1}]]
+		set txt [string range $txt $last end]
+
+		switch -- $state {
+		    TOP {
+			return $num
+		    }
+		    LIST {
+			lappend listVal $num
+			set state COMMA
+		    }
+		    VALUE {
+			dict set dictVal $name $num
+			set state COMMA
+		    }
+		    default {
+			getc
+			return -code error "unexpected number '$c' in $state mode"
+		    }
+		}
+	    } else {
+		getc
+		return -code error "unexpected '$c' in $state mode"
+	    }
+	} elseif {[string match {[ftn]} $c]
+		  && [regexp {^(true|false|null)} $txt val]} {
+	    # bare word value: true | false | null
+	    set txt [string range $txt [string length $val] end]
+
+	    switch -- $state {
+		TOP {
+		    return $val
+		}
+		LIST {
+		    lappend listVal $val
+		    set state COMMA
+		}
+		VALUE {
+		    dict set dictVal $name $val
+		    set state COMMA
+		}
+		default {
+		    getc
+		    return -code error "unexpected '$c' in $state mode"
+		}
+	    }
+	} else {
+	    # error, incorrect format or unexpected end of text
+	    return -code error "unexpected '$c' in $state mode"
+	}
+    }
+}
+
+proc json::dict2json {dictVal} {
+    # XXX: Currently this API isn't symmetrical, as to create proper
+    # XXX: JSON text requires type knowledge of the input data
+    set json ""
+
+    dict for {key val} $dictVal {
+	# key must always be a string, val may be a number, string or
+	# bare word (true|false|null)
+	if {0 && ![string is double -strict $val]
+	    && ![regexp {^(?:true|false|null)$} $val]} {
+	    set val "\"$val\""
+	}
+    	append json "\"$key\": $val," \n
+    }
+
+    return "\{${json}\}"
+}
+
+proc json::list2json {listVal} {
+    return "\[$[join $listVal ,]\]"
+}
+
+proc json::string2json {str} {
+    return "\"$str\""
+}

+ 7 - 5
BlackTools/BT.Binds.tcl

@@ -4,14 +4,14 @@
 #########################################################################
 ###########################   BINDS TCL   ###############################
 #########################################################################
-##						                       ##
-##   BlackTools  : http://blacktools.tclscripts.net	    	       ##
+##						                       						   ##
+##   BlackTools  : http://blacktools.tclscripts.net	    	       	   ##
 ##   Bugs report : http://www.tclscripts.net/	                       ##
-##   GitHub page : https://github.com/tclscripts/BlackToolS-TCL-script ##
-##   Online Help : irc://irc.undernet.org/tcl-help 	 	       ##
+##   GitHub page : https://github.com/tclscripts/BlackToolS-TCL		   ##
+##   Online Help : irc://irc.undernet.org/tcl-help 	 	       		   ##
 ##                 #TCL-HELP / UnderNet                                ##
 ##                 You can ask in english or romanian                  ##
-##					                               ##
+##					                               					   ##
 #########################################################################
 
 if {[info exists black(notlogged)]} {
@@ -90,6 +90,8 @@ bind splt - * badchan:split
 bind kick - * badchan:kick
 bind nick - * badchan:nickchange
 
+bind kick - * massban:kick
+
 bind join - * flood:join:protection
 bind join - * join:count
 bind join - * first:join

+ 60 - 33
BlackTools/BT.Core.tcl

@@ -4,14 +4,14 @@
 ###########################################################################
 ############################   CORE TCL   #################################
 ###########################################################################
-##						       		         ##
-##   BlackTools  : http://blacktools.tclscripts.net	   	         ##
+##						       		         							 ##
+##   BlackTools  : http://blacktools.tclscripts.net	   	         		 ##
 ##   Bugs report : http://www.tclscripts.net/	                         ##
-##   GitHub page : https://github.com/tclscripts/BlackToolS-TCL-script   ##
-##   Online Help : irc://irc.undernet.org/tcl-help 	       	         ##
+##   GitHub page : https://github.com/tclscripts/BlackToolS-TCL		     ##
+##   Online Help : irc://irc.undernet.org/tcl-help 	       	         	 ##
 ##                 #TCL-HELP / UnderNet        	                         ##
 ##                 You can ask in english or romanian                    ##
-##					                                 ##	
+##					                                 					 ##	
 ###########################################################################
 ########################## Default protection flags #######################
 
@@ -31,23 +31,24 @@ if {![file exists $black(files_file)]} {
 	file mkdir $black(files_file)
 }
 
-if {![file exists $black(tempdir)]} {
-	file mkdir $black(tempdir)
+if {![file exists $black(backdir)]} {
+	file mkdir $black(backdir)
 }
 
-set black(s_file) "$black(dirname)/BlackTools/FILES/$username.suspend.txt"
-set black(status_file) "$black(dirname)/BlackTools/FILES/$username.status.txt"
-set black(seen_file) "$black(dirname)/BlackTools/FILES/$username.seen_db.txt"
-set black(old_seen) "$black(dirname)/BlackTools/FILES/$username.Seen.db"
-set black(uptime_file) "$black(dirname)/BlackTools/FILES/$username.uptime.txt"
-set black(bans_file) "$black(dirname)/BlackTools/FILES/$username.bans.txt"
-set black(join_file) "$black(dirname)/BlackTools/FILES/$username.othermodule.txt"
-set black(extra_file) "$black(dirname)/BlackTools/FILES/$username.flags.txt"
-set black(add_file) "$black(dirname)/BlackTools/FILES/$username.extra.txt"
-set black(quote_file) "$black(dirname)/BlackTools/FILES/$username.quote.txt"
-set black(notes_file) "$black(dirname)/BlackTools/FILES/$username.notes.txt"
-set black(temp_banner) "$black(dirname)/BlackTools/temp/banner"
-set black(temp_motd) "$black(dirname)/BlackTools/temp/motd"
+set black(files_file) "$black(backdir)/BlackTools/FILES"
+set black(s_file) "$black(backdir)/BlackTools/FILES/$username.suspend.txt"
+set black(status_file) "$black(backdir)/BlackTools/FILES/$username.status.txt"
+set black(seen_file) "$black(backdir)/BlackTools/FILES/$username.seen_db.txt"
+set black(old_seen) "$black(backdir)/BlackTools/FILES/$username.Seen.db"
+set black(uptime_file) "$black(backdir)/BlackTools/FILES/$username.uptime.txt"
+set black(bans_file) "$black(backdir)/BlackTools/FILES/$username.bans.txt"
+set black(join_file) "$black(backdir)/BlackTools/FILES/$username.othermodule.txt"
+set black(extra_file) "$black(backdir)/BlackTools/FILES/$username.flags.txt"
+set black(add_file) "$black(backdir)/BlackTools/FILES/$username.extra.txt"
+set black(quote_file) "$black(backdir)/BlackTools/FILES/$username.quote.txt"
+set black(notes_file) "$black(backdir)/BlackTools/FILES/$username.notes.txt"
+set black(temp_banner) "$black(backdir)/BlackTools/temp/banner"
+set black(temp_motd) "$black(backdir)/BlackTools/temp/motd"
 
 set black(files) "$black(s_file) $black(status_file) $black(seen_file) $black(uptime_file) $black(bans_file) $black(join_file) $black(extra_file) $black(add_file) $black(quote_file) $black(notes_file)"
 
@@ -58,7 +59,6 @@ if {[file exists $black(temp_banner)] && [file exists $black(temp_motd)]} {
 	file rename -force $black(temp_motd) "text/motd"
 	file delete -force $black(temp_banner)
 	file delete -force $black(temp_motd)
-	
 		}
 	}
 }
@@ -278,7 +278,7 @@ set black(extra_flag) {
 	accessonly voiceme onlyonmode securemode strictsecured nextshortcmd inviteban quoteofday chanlink
 }
 
-set black(validcmds) "o omsg v ho man version mode cycle say act i stats t myset h r msg add set userlist info delacc del auto chuser s us addhost delhost b black stick dr bot n id spam bw mb vr gag ungag troll ub sb banlist k w purge set unset show ignore enable disable addchan delchan suspend unsuspend channels die jump save rehash nick uptime status cp chat next noidle skip helped anunt bt idle limit seen clonescan badchan securemode private tcl guestnick greet broadcast leave topic timer topwords next q note login"
+set black(validcmds) "o omsg v ho man version mode cycle say act i stats t myset h r msg add set userlist info delacc del auto chuser s us addhost delhost b black stick dr bot n id spam bw mb vr gag ungag troll ub sb banlist k w purge set unset show ignore enable disable addchan delchan suspend unsuspend channels die jump save rehash nick uptime status cp chat next noidle skip helped anunt bt idle limit seen clonescan badchan securemode private tcl guestnick greet broadcast leave topic timer topwords next q note login update"
 
 ########################## BackChan ############################
 
@@ -1666,6 +1666,16 @@ if {![botisop $chan] && ![setting:get $chan xonly]} {
 }
 if {$bans == "*!*@*"} { putserv "MODE $chan -b $bans"
 	return
+}
+if {$black(logged) == 1} {
+	set massban [check:massban $bans $chan]
+if {$massban == 1} {
+if {![info exists black(massban_start:$chan)]} {
+	set black(massban_start:$chan) [unixtime]
+	putquick "PRIVMSG $black(chanserv) :unban $chan $bans"
+	utimer 60 [list massban:kick_unset $chan]
+		}
+	}
 }
 	set list [userlist $black(exceptflags) $chan]
 foreach user $list {
@@ -1677,11 +1687,35 @@ if {[onchan $black(chanserv) $chan] && ([setting:get $chan xtools] || [setting:g
 				} else {
 	putserv "MODE $chan -b $bans"
 				}
+	break
+			}
+		}
+	}
+}
+
+proc massban:kick {nick host hand chan kicked reason} {
+	global black
+if {[info exists black(massban_start:$chan)]} {
+if {[string equal -nocase $nick $black(chanserv)]} {
+		set lang [setting:get $chan lang]
+if {$lang == ""} { set lang [string tolower $black(default_lang)] }
+	set reason_k $black(say.$lang.b.9)
+	regexp {\((.+)\) (.*)} $reason string user reason
+if {$user != ""} {
+	putquick "PRIVMSG $black(chanserv) :suspend $chan $user $black(chanserv:suspend_time) $black(chanserv:suspend_level) $reason_k - [ctime $black(massban_start:$chan)]"
+	massban:kick_unset $chan
 			}
 		}
 	}
 }
 
+proc massban:kick_unset {chan} {
+	global black
+if {[info exists black(massban_start:$chan)]} {
+	unset black(massban_start:$chan)
+	}
+}
+
 ########################### Text Wrapper ##################################
 
 proc wordwrap {str {len 100} {splitChr { }}} { 
@@ -3005,7 +3039,7 @@ if {[string match -nocase $host $gethost]} {
 	set counter [expr $counter + 1]
 	}
 }
-if {[expr 100 * $counter / $totuser] > 80} {
+if {[expr 100 * $counter / $totuser] > $black(chanserv:percent_ban)} {
 	return 1
 }
 	return 0
@@ -5973,7 +6007,6 @@ for {set i 0} { $i < 1 } { incr i} {
 
 proc bans:day:reset {minute hour day month year} {
 	global black
-
 foreach user [userlist] {
 	foreach chan [channels] {
 	set cmds_today [getuser $user XTRA CMD_STATS_TODAY($chan)]
@@ -6324,15 +6357,6 @@ pushmode $chan +o $nick
 	}
 }
 
-######################## h flood #######################
-
-proc unset:floodcmd {host chan} {
-global black
-if {[info exists black(floodcmd:$host:$chan)]} {
-	unset black(floodcmd:$host:$chan)
-	}
-}
-
 ######################## get level #####################
 
 proc blacktools:getlevelname {num hand} {
@@ -7085,6 +7109,9 @@ proc dns:resolve:join {ip host status hostip nick fullhost hand chan} {
 proc dns:checkexcept {host} {
 	global black
 	set valid_except 0
+if {$black(dns_onjoin) == 0} {
+	return 0
+}
 	set host [lindex [split $host "@"] 1]
 foreach h $black(dns:host_excepts) {
 if {[string match -nocase $h $host]} {

+ 28 - 13
BlackTools/BT.Loader.tcl

@@ -4,32 +4,47 @@
 #########################################################################
 ##########################   LOADER TCL   ###############################
 #########################################################################
-##						                       ##
-##   BlackTools  : http://blacktools.tclscripts.net	               ##
+##						                       						   ##
+##   BlackTools  : http://blacktools.tclscripts.net	               	   ##
 ##   Bugs report : http://www.tclscripts.net/	                       ##
-##   GitHub page : https://github.com/tclscripts/BlackToolS-TCL-script ##
-##   Online Help : irc://irc.undernet.org/tcl-help 	               ##
+##   GitHub page : https://github.com/tclscripts/BlackToolS-TCL        ##
+##   Online Help : irc://irc.undernet.org/tcl-help 	               	   ##
 ##                 #TCL-HELP / UnderNet                                ##
 ##                 You can ask in english or romanian                  ##
-##					                               ##
+##					                              					   ##
 #########################################################################
 
+if {[info exists black(backup_update)]} {
+	set black(backdir) $black(backup_dir)
+} else {
+	set black(backdir) $black(dirname)
+}
+
+if {[info exists black(update_disabled)]} {
+	unset black(update_disabled)
+}
+
 #Load modules
 
-	set modules_files [glob -directory "$black(dirname)/BlackTools/Modules/" "*.tcl"]
+	set modules_files [glob -directory "$black(backdir)/BlackTools/Modules/" "*.tcl"]
 foreach file $modules_files {
 	set split_file [split $file "."]
 	set themodule [lindex $split_file 1]
 	set black(module_error_$themodule) [catch {source $file} black(module_error_stats_$themodule)]
 if {$black(module_error_$themodule) == "1"} {
+if {$themodule == "AutoUpdate"} {
+	putlog "\[BT\] :Couldn't load the AutoUpdate module. Reason: $black(module_error_stats_$themodule)."
+	set black(update_disabled) $black(module_error_stats_$themodule)
+	continue
+		}
 	die "\[BT\] :Couldn't load the module file \"$file\".Reason: \"$black(module_error_stats_$themodule)\""
-	} 
+	}
 }
 
 
 #Load cmds
 
-	set cmds_files [glob -directory "$black(dirname)/BlackTools/Commands/" "*.tcl"]
+	set cmds_files [glob -directory "$black(backdir)/BlackTools/Commands/" "*.tcl"]
 foreach file $cmds_files {
 	set split_file [split $file "."]
 	set themodule [lindex $split_file 1]
@@ -41,7 +56,7 @@ if {$black(cmds_error_$themodule) == "1"} {
 
 #Load protections
 
-	set prot_files [glob -directory "$black(dirname)/BlackTools/Protections/" "*.tcl"]
+	set prot_files [glob -directory "$black(backdir)/BlackTools/Protections/" "*.tcl"]
 foreach file $prot_files {
 	set split_file [split $file "."]
 	set themodule [lindex $split_file 1]
@@ -53,10 +68,10 @@ if {$black(prot_error_$themodule) == "1"} {
 
 #Load script files
 
-set black(timers_error) [catch {source $black(dirname)/BlackTools/BT.Timers.tcl} black(timers_error_stats)]
-set black(binds_error) [catch {source $black(dirname)/BlackTools/BT.Binds.tcl} black(binds_error_stats)]
-set black(core_error) [catch {source $black(dirname)/BlackTools/BT.Core.tcl} black(core_error_stats)]
-set black(loader_error) [catch {source $black(dirname)/BlackTools/lang/loader.tcl} black(loader_error_stats)]
+set black(timers_error) [catch {source $black(backdir)/BlackTools/BT.Timers.tcl} black(timers_error_stats)]
+set black(binds_error) [catch {source $black(backdir)/BlackTools/BT.Binds.tcl} black(binds_error_stats)]
+set black(core_error) [catch {source $black(backdir)/BlackTools/BT.Core.tcl} black(core_error_stats)]
+set black(loader_error) [catch {source $black(backdir)/BlackTools/lang/loader.tcl} black(loader_error_stats)]
 
 #Check for errors in script files
 if {$black(timers_error) == "1"} {

+ 10 - 5
BlackTools/BT.Timers.tcl

@@ -4,17 +4,16 @@
 #########################################################################
 ###########################  LOCAL TIMERS  ##############################
 #########################################################################
-##						                       ##
-##   BlackTools  : http://blacktools.tclscripts.net	               ##
+##						                       						   ##
+##   BlackTools  : http://blacktools.tclscripts.net	               	   ##
 ##   Bugs report : http://www.tclscripts.net/	                       ##
 ##   GitHub page : https://github.com/tclscripts/BlackToolS-TCL-script ##
-##   Online Help : irc://irc.undernet.org/tcl-help 	               ##
+##   Online Help : irc://irc.undernet.org/tcl-help 	               	   ##
 ##                 #TCL-HELP / UnderNet                                ##
 ##                 You can ask in english or romanian                  ##
-##					                               ##
+##					                               					   ##
 #########################################################################
 
-
 proc blacktools:timers:load {chan} {
 	global black
 if {[validchan $chan]} {
@@ -156,6 +155,12 @@ if {![info exists black(broadcast:timer_start)]} {
 #end
 }
 
+#AutoUpdate Check
+if {![info exists black(update_check_start)]} {
+	timer $black(update_time_check) blacktools:update:timer
+	set black(update_check_start) 1
+}
+
 #run by minute
 
 proc blacktools:timers:runtime {} {

+ 11 - 0
BlackTools/Commands/BT.ChanCmds.tcl

@@ -1642,6 +1642,17 @@ if {[matchattr $hand q]} { blacktools:tell $nick $host $hand $chan $chan1 gl.gls
 	}
 }
 
+update {
+if {[matchattr $hand n]} {
+if {[matchattr $hand q]} { blacktools:tell $nick $host $hand $chan $chan1 gl.glsuspend none
+	return
+}
+	set what [lindex [split $arg] 1]
+	set type 0
+	update:process $nick $char $hand $chan $chan $what $type
+	}
+}
+
 nick {
 if {[matchattr $hand nm]} {
 	set thenick [lindex [split $arg] 1]

+ 15 - 4
BlackTools/Commands/BT.ForCmds.tcl

@@ -23,7 +23,18 @@ global botnick wordsdir sdir black seendir count server uptime {server-online} v
 	set chan1 $chan
 if {[isbotnick $nick]} { return }
 if {[string equal -nocase $for "for"] && ([lsearch -exact -nocase $split_bots $botnick] > -1)} {
-switch -exact -- [string tolower $the_cmd] {
+switch [string tolower $the_cmd] {
+
+update {
+if {[matchattr $hand n]} {
+if {[matchattr $hand q]} { blacktools:tell $nick $host $hand $chan $chan1 gl.glsuspend none
+	return
+}
+	set what [lindex [split $arg] 3]
+	set type 1
+	update:process $nick $host $hand $chan $chan $what $type
+	}
+}
 
 exempt {
 if {[matchattr $hand mno|M $chan]} {
@@ -101,7 +112,7 @@ if {[matchattr $hand mn]} {
 }
 
 report {
-	set type "1"
+	set type 1
 	set w [lindex [split $arg] 3]
 	set message [join [lrange [split $arg] 4 end]]
 	set chan1 $chan
@@ -208,8 +219,8 @@ enable {
 if {[matchattr $hand nmo|M $chan]} {
 	set what [lindex [split $arg] 3]
 	set user [lindex [split $arg] 4]
-	set chan1 "$chan"
-	set type "1"
+	set chan1 $chan
+	set type 1
 if {[regexp {^[&#]} $what] && [matchattr $hand nmo|M $what]} {
 	set chan "$what"
 	set what [lindex [split $arg] 4]

+ 4 - 4
BlackTools/Commands/BT.Manual.tcl

@@ -15,7 +15,7 @@
 #########################################################################
 
 proc man:process {nick host hand chan chan1 type command} {
-	global black count
+	global black
 	set cmd_status [btcmd:status $chan $hand "man" 0]
 if {$cmd_status == "1"} { 
 	return
@@ -42,7 +42,7 @@ if {![info exists black(floodcmd:$host:$chan)]} {
 	set black(floodcmd:$host:$chan) 0 
 }
 	incr black(floodcmd:$host:$chan)
-	utimer $timer [list unset:floodcmd $host $chan]
+	utimer $timer [list unset black(floodcmd:$host:$chan)]
 
 if {$black(floodcmd:$host:$chan) == "$number"} {
 	blacktools:tell $nick $host $hand $chan $chan1 h.16 "30 man"
@@ -71,7 +71,7 @@ if {[regexp {[+-]} $command]} {
 		set command [string map {"+" ""
 								 "-" ""	} $command]
 }
-switch $command {
+switch [string tolower $command] {
 
 man {
 if {[matchattr $hand nmo|MAOV $chan]} {
@@ -2567,4 +2567,4 @@ default {
 ##############
 #########################################################################
 ##   END                                                               ##
-#########################################################################
+#########################################################################

+ 12 - 1
BlackTools/Commands/BT.MeCmds.tcl

@@ -21,7 +21,18 @@ global botnick wordsdir sdir black seendir count server uptime {server-online} v
 	set chan1 $chan
 if {[isbotnick $nick]} { return }
 if {[isbotnick $bnick]} {
-switch -exact -- [string tolower $what] {
+switch [string tolower $what] {
+
+update {
+if {[matchattr $hand n]} {
+if {[matchattr $hand q]} { blacktools:tell $nick $host $hand $chan $chan1 gl.glsuspend none
+	return
+}
+	set what [lindex [split $arg] 2]
+	set type 1
+	update:process $nick $host $hand $chan $chan $what $type
+	}
+}
 
 exempt {
 if {[matchattr $hand mno|M $chan]} {

+ 67 - 2
BlackTools/Commands/BT.OwnerCmds.tcl

@@ -7,8 +7,8 @@
 ##						                      						   ##
 ##   BlackTools  : http://blacktools.tclscripts.net	            	   ##
 ##   Bugs report : http://www.tclscripts.net/	                       ##
-##   GitHub page : https://github.com/tclscripts/BlackToolS-TCL-script ##
-##   Online Help : irc://irc.undernet.org/tcl-help 	               ##
+##   GitHub page : https://github.com/tclscripts/BlackToolS-TCL        ##
+##   Online Help : irc://irc.undernet.org/tcl-help 	               	   ##
 ##                 #TCL-HELP / UnderNet                                ##
 ##                 You can ask in english or romanian                  ##
 ##					                              					   ##
@@ -17,6 +17,71 @@
 
 ################################ Commands ###################################
 
+################################## update ###################################
+
+proc update:process {nick host hand chan chan1 what type} {
+	global black
+	set cmd_status [btcmd:status $chan $hand "update" 0]
+	set chan1 $chan
+if {$cmd_status == "1"} { 
+	return 
+}
+switch $what {
+	on {
+	set out [blacktools:update_on_off 1]
+if {$out == 1} {
+	blacktools:tell $nick $host $hand $chan $chan1 autoupdate.35 ""
+} elseif {$out == 3} {
+	blacktools:tell $nick $host $hand $chan $chan1 autoupdate.36 ""
+}
+	}
+	off {
+	set out [blacktools:update_on_off 0]
+if {$out == 0} {
+	blacktools:tell $nick $host $hand $chan $chan1 autoupdate.37 ""
+} elseif {$out == 2} {
+	blacktools:tell $nick $host $hand $chan $chan1 autoupdate.38 ""
+}
+	}
+	start {
+if {[info exists black(update_disabled)]} {
+	blacktools:tell $nick $host $hand $chan $chan1 autoupdate.34 "$black(update_disabled)"
+	return
+}
+if {[info exists black(backup_update)]} {
+	blacktools:tell $nick $host $hand $chan $chan1 autoupdate.39 ""
+	return
+}
+	blacktools:update $nick $host $chan
+}
+	check {
+if {[info exists black(update_disabled)]} {
+	blacktools:tell $nick $host $hand $chan $chan1 autoupdate.34 "$black(update_disabled)"
+	return
+}
+if {[info exists black(backup_update)]} {
+	blacktools:tell $nick $host $hand $chan $chan1 autoupdate.39 ""
+	return
+}
+	blacktools:update_check $nick $hand $host $chan
+}
+	default {
+switch $type {
+	0 {
+	blacktools:tell $nick $host $hand $chan $chan gl.instr "update"
+	}
+	1 {
+	blacktools:tell $nick $host $hand $chan $chan gl.instr_nick "update"
+	}
+	2 {
+	blacktools:tell $nick $host $hand $chan $chan gl.instr_priv "update"
+		}
+	}
+	return		
+		}
+	}
+}
+
 ################################## login ####################################
 
 proc login:process {nick host hand chan chan1} {

+ 12 - 1
BlackTools/Commands/BT.PrvCmds.tcl

@@ -34,10 +34,21 @@ if {[validchan $mychan] && [matchattr $hand nmo|OVMA $mychan] && ![string equal
 
 switch [string tolower $cmd] {
 
+update {
+if {[matchattr $hand n]} {
+if {[matchattr $hand q]} { blacktools:tell $nick $host $hand $chan $chan1 gl.glsuspend none
+	return
+}
+	set what [lindex [split $arg] 2]
+	set type 2
+	update:process $nick "prv" $hand $chan $chan $what $type
+	}
+}
+
 exempt {
 if {[matchattr $hand mno|M $chan]} {
 	set chan1 $chan
-	set type 1
+	set type 2
 	set gl 0
 if {$mychan_use == "0"} {
 	set ecmd [lindex [split $arg] 2]

+ 5 - 5
BlackTools/Modules/BT.Anunt.tcl

@@ -4,14 +4,14 @@
 #########################################################################
 ########################   ANUNT/ADVERT TCL   ###########################
 #########################################################################
-##						                       ##
-##   BlackTools  : http://blacktools.tclscripts.net	               ##
+##						                       						   ##
+##   BlackTools  : http://blacktools.tclscripts.net	               	   ##
 ##   Bugs report : http://www.tclscripts.net/	                       ##
 ##   GitHub page : https://github.com/tclscripts/BlackToolS-TCL-script ##
-##   Online Help : irc://irc.undernet.org/tcl-help 	               ##
+##   Online Help : irc://irc.undernet.org/tcl-help 	               	   ##
 ##                 #TCL-HELP / UnderNet                                ##
 ##                 You can ask in english or romanian                  ##
-##					                               ##
+##					                               					   ##
 #########################################################################
 
 proc anunt:process {nick host hand chan chan1 who message number type} {
@@ -273,4 +273,4 @@ if {$black(anunthow) == "1"} {
 ##############
 #########################################################################
 ##   END                                                               ##
-#########################################################################
+#########################################################################

+ 520 - 0
BlackTools/Modules/BT.AutoUpdate.tcl

@@ -0,0 +1,520 @@
+#########################################################################
+##          BlackTools - The Ultimate Channel Control Script           ##
+##                    One TCL. One smart Eggdrop                       ##
+#########################################################################
+#########################   AutoUpdate TCL   ############################
+#########################################################################
+##						                                               ##
+##   BlackTools  : http://blacktools.tclscripts.net	                   ##
+##   Bugs report : http://www.tclscripts.net/	                       ##
+##   GitHub page : https://github.com/tclscripts/BlackToolS-TCL        ##
+##   Online Help : irc://irc.undernet.org/tcl-help 	                   ##
+##                 #TCL-HELP / UnderNet                                ##
+##                 You can ask in english or romanian                  ##
+##					                               					   ##
+#########################################################################
+
+package require tls
+
+set black(backup_dir) "$black(dirname)/BT.backup"
+set black(log_file) "$black(dirname)/BT.update.log"
+set black(actdir) "scripts"
+
+###
+proc blacktools:check_addons {hand chan} {
+    global black
+if {[catch {package require http} no_http] != 0} {
+    source $black(dirname)/BlackTools/Addons/http.tcl
+    package require http
+    }
+if {[catch {package require json} no_json] != 0} {
+    source $black(dirname)/BlackTools/Addons/json.tcl
+    package require json
+    }
+if {[catch {package require github} no_github] != 0} {
+    source $black(dirname)/BlackTools/Addons/github.tcl
+    package require github
+    }
+    return 1
+}
+
+###
+proc blacktools:update_check {nick hand host chan} {
+    global black
+    set check_addons [blacktools:check_addons $hand $chan]
+    set status [blacktools:update_verify]
+if {$status == -1} {
+    blacktools:update_put $hand $chan 31 ""
+    blacktools:tell $nick $host $hand $chan $chan autoupdate.31 ""
+    return
+    }
+    set data [split $status "\n"]
+    set new_version [lindex [lindex $data 0] 1]
+    set last_modify [lindex [lindex $data 1] 2]
+    set status [lindex [lindex $data 2] 1]
+
+if {$black(vers) != $new_version} {
+    blacktools:tell $nick $host $hand $chan $chan autoupdate.32 "$new_version"
+} elseif {$last_modify != $black(current_modif)} {
+    blacktools:tell $nick $host $hand $chan $chan autoupdate.33 [ctime $last_modify]
+} else {
+    blacktools:tell $nick $host $hand $chan $chan autoupdate.5 ""
+    return
+    }
+}
+
+###
+proc blacktools:update:timer {} {
+    global black
+if {$black(update_type) == 1} {
+if {![info exists black(update_disabled)]} {
+if {![info exists black(backup_update)]} {
+    set update [catch {blacktools:update "" "" ""} error]
+    } else {
+    blacktools:update_put "" "" 40 ""  
+    }
+} else {
+    blacktools:update_put "" "" 27 [list [ctime [unixtime]]]
+    blacktools:update_put "" "" 30 [list $black(update_disabled)]
+    }
+}
+    timer [time_return_minute $black(update_time_check)] blacktools:update:timer 
+}
+
+###
+proc blacktools:update {hand host chan} {
+    global black
+if {[info exists black(backup_update)]} {
+    blacktools:update_put $hand $chan 29 ""
+    return
+}
+    set error_b ""
+    set file [open $black(log_file) w]
+    close $file
+    blacktools:update_put $hand $chan 27 [list [ctime [unixtime]]]
+    blacktools:update_put $hand $chan 28 ""
+    set check_addons [blacktools:check_addons $hand $chan]
+if {$check_addons == 0} {
+     blacktools:update_put $hand $chan 1 ""
+     return
+}
+    set status [blacktools:update_verify]
+if {$status == -1} {
+    blacktools:update_put $hand $chan 2 ""
+    return
+}
+    set data [split $status "\n"]
+    set new_version [lindex [lindex $data 0] 1]
+    set last_modify [lindex [lindex $data 1] 2]
+    set status [lindex [lindex $data 2] 1]
+
+if {$black(vers) != $new_version} {
+    blacktools:update_put $hand $chan 3 [list $new_version]   
+} elseif {$last_modify != $black(current_modif)} {
+    blacktools:update_put $hand $chan 4 [list $black(vers)]
+} else {
+    blacktools:update_put $hand $chan 5 ""
+    return
+}
+
+if {![file isdirectory $black(backup_dir)]} {
+if {[catch {file mkdir $black(backup_dir)} error] != 0} {
+    blacktools:update_put $hand $chan 6 [list $error]
+     return
+    }
+}
+
+if {[file exists $black(backup_dir)/BlackTools.tcl]} {
+    blacktools:update_put "" "" 7 ""
+    file delete -force $black(backup_dir)/BlackTools
+    file delete -force $black(backup_dir)/BlackTools.tcl
+}
+if {[catch {file copy -force "$black(dirname)/BlackTools" $black(backup_dir)} error_b] == 0} {
+    blacktools:update_put "" "" 8 ""
+} else {
+    blacktools:update_put $hand $chan 9 [list $error_b]
+    file delete -force $black(backup_dir)
+    return
+}
+
+if {[catch {file copy -force $black(tclconfig) $black(backup_dir)} error_b] != 0} {
+    blacktools:update_put $hand $chan 10 ""
+    file delete -force $black(backup_dir)
+    return
+} else {
+    blacktools:update_put "" "" 11 ""
+}
+    set ::update_hand $hand
+    set ::update_version $new_version
+    set ::update_last_modify $last_modify
+    set ::update_chan $chan
+every 1000 {
+if {[file isdirectory "$black(backup_dir)/BlackTools"]} {
+    set after_file_num [llength [glob-r "$black(backup_dir)/BlackTools"]]
+    set current_file_num [llength [glob-r "$black(actdir)/BlackTools"]]
+if {$current_file_num == $after_file_num} {
+    blacktools:update_backup
+    break
+            }
+        }
+    }   
+}
+
+###
+proc blacktools:update_backup {} {
+    global black
+    set hand $::update_hand
+    set new_version $::update_version
+    set last_modify $::update_last_modify
+    set chan $::update_chan
+    set black(backup_update) 1
+    set black(start_update) [unixtime]
+    set black(update_file_saved) [llength [glob -nocomplain -directory "$black(dirname)/BlackTools/FILES" "*.txt"]]
+    blacktools:update_put "" "" 12 ""
+    blacktools:update_put "" "" 13 ""
+    blacktools:update_put "" "" 14 ""
+    blacktools:update_put $hand $chan 15 [list $new_version [ctime $last_modify]]
+    blacktools:backup_run
+    set black(update_old_data) [blacktools:update_data 0 ""]
+    utimer 5 [list blacktools:update_start_download $hand $chan $new_version $last_modify]
+    unset ::update_version
+    unset ::update_last_modify
+    unset ::update_hand
+    unset ::update_chan
+}
+
+###
+proc blacktools:backup_run {} {
+    global black config
+    set bt_file "$black(dirname)/BlackTools.tcl"
+    set file [open $bt_file r]
+    set data [read -nonewline $file]
+    close $file
+    set regexp_var2 "set black\\(dirname\\) \"(.*?)\""
+    regexp -nocase $regexp_var2 $data found_line
+    regexp -nocase $regexp_var2 $data -> found
+    set found_line [string map [list $black(dirname) $black(backup_dir)] $found_line]
+    regsub $regexp_var2 $data $found_line data
+    blacktools:update_data 1 $data
+
+    set file [open $config r]
+    set data [read -nonewline $file]
+    close $file
+    set reg "source $black(dirname)/BlackTools.tcl"
+    regsub $reg $data "source $black(dirname)/BlackTools.old.tcl" data
+    set file [open $config w]
+    puts $file $data
+    close $file
+    file rename -force "$black(dirname)/BlackTools.tcl" "$black(dirname)/BlackTools.old.tcl"
+}
+
+###
+proc blacktools:update_start_download {hand chan new_version last_modify} {
+    global black
+    rehash
+    set ::update_hand $hand
+    set ::update_chan $chan
+    file delete -force "$black(actdir)/BlackTools"
+    ::github::github update tclscripts BlackTools-TCL $black(actdir)
+    every 1000 {
+if {[file isdirectory $black(actdir)/BlackTools]} {
+    blacktools:update_start_restore
+    break
+        }
+    }
+}
+
+###
+#https://wiki.tcl-lang.org/page/glob
+proc glob-r {{dir .}} {
+    set res {}
+    foreach i [lsort [glob -nocomplain -dir $dir *]] {
+        if {[file type $i] eq {directory}} {
+            eval lappend res [glob-r $i]
+        } else {
+            lappend res $i
+        }
+    }
+    set res
+} ;# RS
+
+###
+proc blacktools:update_unsetflag {} {
+    global black
+if {[info exists black(backup_update)]} {
+    unset black(backup_update)
+    }
+}
+
+###
+proc blacktools:update_start_restore {} {
+    global black
+    set hand $::update_hand
+    set chan $::update_chan
+    if {![file isdirectory "$black(actdir)/BlackTools"]} {
+    blacktools:update_put $hand $chan 16 ""
+    file delete -force $black(backup_dir)
+    blacktools:update_unsetflag
+    return
+} elseif {![file exists "$black(actdir)/BlackTools.tcl"]} {
+    blacktools:update_put $hand $chan 16 ""
+    file delete -force $black(backup_dir)
+    blacktools:update_unsetflag
+    return
+}
+    set end_download [unixtime]
+    set dif [expr $end_download - $black(start_update)]
+    blacktools:update_put $hand $chan 17 [list [duration $dif]]
+    set newdata [blacktools:update_data 0 ""]
+    blacktools:update_put $hand $chan 18 ""
+    set restore_config [blacktools:update_restore $black(update_old_data) $newdata]
+    unset black(update_old_data)
+    set newdata [lindex $restore_config 0]
+    set num_var [lindex $restore_config 1]
+if {$num_var > 0} {
+    set newdata [blacktools:update_data 1 $newdata]
+    blacktools:update_put $hand $chan 19 [list $num_var]
+} else {
+    blacktools:update_put "" "" 20 ""
+}
+    blacktools:update_put $hand $chan 21 ""
+    blacktools:update_restore_files
+    set ::update_hand $::update_hand
+    set ::update_chan $::update_chan 
+every 1000 {
+    set info_files_num [llength [glob -nocomplain -directory "$black(actdir)/BlackTools/FILES" "*.txt"]]
+if {$info_files_num == $black(update_file_saved)} {
+    blacktools:update_end $info_files_num
+    break
+        }
+    }
+}
+
+###
+proc blacktools:update_end {num} {
+    global black config
+    set hand $::update_hand
+    set chan $::update_chan
+    set end_update [unixtime]
+    set dif [expr $end_update - $black(start_update)]
+    unset black(start_update)
+if {$num == 0} {
+    blacktools:update_put "" "" 22 ""
+} else {
+    blacktools:update_put $hand $chan 23 [list $num]
+}
+    set file [open $config r]
+    set data [read -nonewline $file]
+    close $file
+    set reg "source $black(actdir)/BlackTools.old.tcl"
+    regsub $reg $data "source $black(actdir)/BlackTools.tcl" data
+    set file [open $config w]
+    puts $file $data
+    close $file
+    rehash
+if {[info exists ::update_hand]} {
+    unset ::update_hand
+}
+if {[info exists ::update_chan]} {
+    unset ::update_chan
+}
+    blacktools:update_unsetflag
+    blacktools:update_put $hand $chan 24 [list [duration $dif]]
+    blacktools:update_put $hand $chan 25 [list $black(backup_dir) $black(log_file)]
+    blacktools:update_put $hand $chan 26 ""
+    unset black(update_file_saved)
+    file delete -force "$black(actdir)/BlackTools.old.tcl"
+}
+
+###
+proc blacktools:update_restore_files {} {
+    global black
+    set files ""
+    set files [glob -nocomplain -directory "$black(backup_dir)/BlackTools/FILES" "*.txt"]
+if {![file isdirectory "$black(actdir)/BlackTools/FILES"]} {
+    file mkdir "$black(actdir)/BlackTools/FILES"
+}
+    set counter 0
+foreach f $files {
+    incr counter
+    set filename [file tail $f]
+    file copy -force $f "$black(actdir)/BlackTools/FILES/$filename"
+    }
+    return $counter
+}
+
+###
+proc blacktools:update_on_off {type} {
+    global black
+    set regexp_var2 "set black\\(update_type\\) \"(.*?)\""
+    set bt_file "$black(dirname)/BlackTools.tcl"
+    set file [open $bt_file r]
+    set data [read -nonewline $file]
+    close $file
+    regexp -nocase $regexp_var2 $data found_line
+    regexp -nocase $regexp_var2 $data -> found
+if {$type == 0 && $found == 0} {
+    return 0
+}
+if {$type == 1 && $found == 1} {
+    return 1
+}
+    switch $type {
+        0 {
+    set found_line [string map {"1" "0"} $found_line]
+    regsub $regexp_var2 $data $found_line data
+    blacktools:update_data 1 $data
+    return 2
+        }
+        1 {
+    set found_line [string map {"0" "1"} $found_line]
+    regsub $regexp_var2 $data $found_line data
+    blacktools:update_data 1 $data
+    return 3    
+        }
+    }
+}
+
+###
+proc blacktools:update_restore {data newdata} {
+    global black
+    set current_data $newdata
+    set variables [regexp -all -inline  {set black\((.+?)\)} $data]
+    regsub -all {set black\((.+?)\)} $variables "" variables
+    set var_nomodif "name author vers site last_modify"
+    set var_counter 0
+foreach var $variables {
+if {$var == ""} {continue}
+if {[lsearch -nocase $var_nomodif $var] > -1} {continue}
+    set regexp_var "set black\\($var\\) \\{(.*?)\\}"
+    set regexp_var2 "set black\\($var\\) \"(.*?)\""
+    regexp -nocase $regexp_var $data found_old
+    regexp -nocase $regexp_var2 $data found_old_2
+if {[info exists found_old]} {
+    set found_old [concat $found_old]
+    regexp -nocase $regexp_var $newdata found_new
+if {[info exists found_new]} {
+if {[string equal -nocase $found_old $found_new]} {continue}
+    incr var_counter
+    regsub $regexp_var $current_data $found_old current_data
+    unset found_new
+     }
+    unset found_old
+    }
+}
+
+foreach var $variables {
+if {$var == ""} {continue}
+if {[lsearch -nocase $var_nomodif $var] > -1} {continue}
+    set regexp_var2 "set black\\($var\\) \"(.*?)\""
+    regexp -nocase $regexp_var2 $data found_old_2
+if {[info exists found_old_2]} {
+    set found_old_2 [concat $found_old_2]
+    regexp -nocase $regexp_var2 $newdata found_new_2
+if {[info exists found_new_2]} {
+if {[string equal -nocase $found_old_2 $found_new_2]} {continue}
+    incr var_counter
+    regsub $regexp_var2 $current_data $found_old_2 current_data
+    unset found_new_2
+        }
+    unset found_old_2
+     }
+}
+    return [list $current_data $var_counter]
+}
+
+###
+proc blacktools:update_data {type data} {
+    global black
+    set bt_file "$black(dirname)/BlackTools.tcl"
+if {![file exists $bt_file]} {
+    return 0
+}
+if {$type == 0} {
+    set file [open $bt_file r]
+    set data [read -nonewline $file]
+    close $file
+    return $data
+} else {
+    set file [open $bt_file w]
+    puts $file $data
+    close $file
+    }
+}
+
+###
+proc blacktools:update_verify {} {
+    global black
+    set link "https://raw.githubusercontent.com/tclscripts/BlackTools-TCL/master/VERSION"
+    set ipq [http::config -useragent "lynx"]
+	set error [catch {set ipq [::http::geturl $link -timeout 10000]} eror]
+	set status [::http::status $ipq]
+if {$status != "ok"} {
+	::http::cleanup $ipq
+	return -1
+}
+	set getipq [::http::data $ipq]
+	::http::cleanup $ipq
+	return $getipq
+}
+
+###
+proc blacktools:update_put {nick chan num var} {
+    global black
+    set counter 0
+foreach v $var {
+    incr counter
+    set replace(%msg.${counter}%) $v
+}
+if {$nick != "" && $chan != ""} {
+    set hand [nick2hand $nick]
+    set getmethod [getuser $hand XTRA OUTPUT_TYPE]
+    set userlang [string tolower [getuser $hand XTRA OUTPUT_LANG]]
+if {$userlang == ""} { set userlang "[string tolower $black(default_lang)]" }
+if {$getmethod == ""} { set getmethod "0" }
+    set text [black:color:set "" $black(say.${userlang}.autoupdate.${num})]
+    set reply [join $text]
+    set reply [string map [array get replace] $reply]
+    switch $getmethod {
+	0 {
+	putserv "NOTICE $nick :$reply"
+}
+	1 {
+	putserv "PRIVMSG $chan :$reply"	
+}
+	2 {
+	putserv "PRIVMSG $nick :$reply"
+		}
+	}
+} else {
+    set lang [string tolower $black(default_lang)]
+    set text [black:color:set "" $black(say.${lang}.autoupdate.${num})]
+    set reply [join $text]
+    set reply [string map [array get replace] $reply]
+}
+    putlog "\[BT\] $reply"
+    set file [open $black(log_file) a]
+    puts $file $reply
+    close $file
+}
+
+###
+#https://wiki.tcl-lang.org/page/every
+proc every {interval script} {
+    global everyIds
+    if {$interval eq {cancel}} {
+        after cancel $everyIds($script)
+        return
+    }
+    set everyIds($script) [after $interval [namespace code [info level 0]]]
+    set rc [catch {uplevel #0 $script} result]
+    if {$rc == [catch break]} {
+        after cancel $everyIds($script)
+        set rc 0
+    } elseif {$rc == [catch continue]} {
+        # Ignore - just consume the return code
+        set rc 0
+    }
+    # TODO: Need better handling of errorInfo etc...
+    return -code $rc $result
+}

+ 5 - 32
BlackTools/Modules/BT.BadChan.tcl

@@ -4,14 +4,14 @@
 #########################################################################
 ###########################   BADCHAN TCL   #############################
 #########################################################################
-##						                                                         ##
+##						                                               ##
 ##   BlackTools  : http://blacktools.tclscripts.net	                   ##
-##   Bugs report : http://www.tclscripts.net/	                         ##
+##   Bugs report : http://www.tclscripts.net/	                       ##
 ##   GitHub page : https://github.com/tclscripts/BlackToolS-TCL-script ##
 ##   Online Help : irc://irc.undernet.org/tcl-help 	                   ##
 ##                 #TCL-HELP / UnderNet                                ##
 ##                 You can ask in english or romanian                  ##
-##					                               														 ##
+##					                               					   ##
 #########################################################################
 
 proc badchan:getlist {nick host hand chan chan1 type next} {
@@ -301,34 +301,6 @@ if {[matchattr $hand $black(exceptflags) $chan]} {
 }
 if {[isbotnick $nick]} { return }
 if {(![botisop $chan]) && (![setting:get $chan xonly])} { return }
-	set getset [setting:get $chan badchan-floodcontrol]
-if {$getset == ""} { set getset $black(badchan:join:seconds) }
-	set num_control [scan $getset %\[^:\]]
-	set time_control [scan $getset %*\[^:\]:%s]
-if {[info exists black(floodcontrol:act:$chan)]} {
-	set current_time [unixtime]
-	set dif [expr $current_time - $black(floodcontrol:act:$chan)]
-if {$dif >= 30} {
-	badchan:joinflood:unset:act $chan
-	} else {
-	return
-	}
-}
-foreach tmr [utimers] {
-if {[string match "*badchan:joinflood:unset $chan*" [join [lindex $tmr 1]]]} {
-	killutimer [lindex $tmr 2]
-	}
-}
-if {![info exists black(badchan_floodcontrol:$chan)]} {
-	set black(badchan_floodcontrol:$chan) 0
-}
-	incr black(badchan_floodcontrol:$chan)
-	utimer $time_control [list badchan:joinflood:unset $chan]
-
-if {$black(badchan_floodcontrol:$chan) >= "$num_control"} {
-	set black(floodcontrol:act:$chan) [unixtime]
-	return
-}
 	utimer 5 [list putserv "WHOIS $nick"]
 	bind RAW - 319 badchan:execute
 	}
@@ -464,7 +436,8 @@ if {[setting:get $chan badchan-reason] != ""} {
 
 if {[info exists badchan(checkagain:$banmask:$chan)]} {
 if {[info exists badchan($banmask:$chan)]} {
-	blacktools:banner:2 $nick "BADCHAN,[encoding convertto utf-8 $badchan(channels:$banmask:$chan)]" $chan $chan1 [getchanhost $nick $chan] "0"
+	#blacktools:banner:2 $nick "BADCHAN,[encoding convertto utf-8 $badchan(channels:$banmask:$chan)]" $chan $chan1 [getchanhost $nick $chan] "0"
+	putlog "ban $nick"
 	who:chan $chan
 if {[setting:get $chan showbadchan]} {
 	set replace(%nick%) $show_nick

+ 1 - 1
BlackTools/Modules/BT.Limit.tcl

@@ -133,7 +133,7 @@ if {($dif >= $setnum) || ($dif <= $setnum)} {
 		}
 	}
 }
-	set cc [expr $counter + 1]
+		set cc [expr $counter + 1]
 if {[lindex $channels $cc] != ""} {
 	utimer 5 [list limit:act $channels $cc]
 	}

+ 5 - 5
BlackTools/Modules/BT.Seen.tcl

@@ -4,14 +4,14 @@
 #########################################################################
 #############################   SEEN TCL   ##############################
 #########################################################################
-##						                       ##
-##   BlackTools  : http://blacktools.tclscripts.net	               ##
+##						                       						   ##
+##   BlackTools  : http://blacktools.tclscripts.net	               	   ##
 ##   Bugs report : http://www.tclscripts.net/	                       ##
 ##   GitHub page : https://github.com/tclscripts/BlackToolS-TCL-script ##
-##   Online Help : irc://irc.undernet.org/tcl-help 	               ##
+##   Online Help : irc://irc.undernet.org/tcl-help 	               	   ##
 ##                 #TCL-HELP / UnderNet                                ##
 ##                 You can ask in english or romanian                  ##
-##					                               ##
+##					                               					   ##
 #########################################################################
 
 proc seen:process {nick host hand chan chan1 what type gl} {
@@ -766,4 +766,4 @@ if {$search_it > -1} {
 			}
 		}
 	}
-}
+}

+ 21 - 14
BlackTools/Modules/BT.TopWords.tcl

@@ -14,6 +14,13 @@
 ##					                               ##
 #########################################################################
 
+
+if {[info exists black(backup_update)]} {
+	set black(backdir) $black(backup_dir)
+} else {
+	set black(backdir) $black(dirname)
+}
+
 proc topwords:delexcept {user nick host hand chan chan1} {
 	global black
 	set user [join $user]
@@ -84,7 +91,7 @@ if {[matchattr $user -|w $chan]} {
 
 proc topwords:process {nick host hand chan chan1 cmd type next} {
 global botnick black username
-	set topwords_file "$black(dirname)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"
+	set topwords_file "$black(backdir)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"
 	set cmd_status [btcmd:status $chan $hand "topwords" 0]
 if {$cmd_status == "1"} { 
 	return 
@@ -103,7 +110,7 @@ if {![validchan $chan]} {
 	return
 }
 
-if {![file isdirectory "$black(dirname)/BlackTools/FILES/TOPWORDS"]} {
+if {![file isdirectory "$black(backdir)/BlackTools/FILES/TOPWORDS"]} {
 	blacktools:tell $nick $host $hand $chan $chan1 topwords.7 none
 	return
 }
@@ -242,7 +249,7 @@ proc topwords:user {nick host hand chan chan1 user mask type1} {
 	set split_user [split $user ":"]
 	set theuser [lindex $split_user 1]
 	set type [lindex $split_user 0]
-	set topwords_file "$black(dirname)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"
+	set topwords_file "$black(backdir)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"
 switch $type {
 	reset {
 	set reset [topwords:user:reset $theuser $chan]
@@ -297,7 +304,7 @@ if {$found_it == "0"} {
 
 proc topwords:user:reset {user chan} {
 	global black username
-	set topwords_file "$black(dirname)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"
+	set topwords_file "$black(backdir)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"
 	set found_it 0
 	set file [open $topwords_file r]
 	set timestamp [clock format [clock seconds] -format {%Y%m%d%H%M%S}]
@@ -360,7 +367,7 @@ user {
 
 proc getactivplace {host chan type} {
 	global black username
-	set topwords_file "$black(dirname)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"
+	set topwords_file "$black(backdir)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"
 	array set activlist [list]
 	set counter 0
 	set all_count 0
@@ -396,13 +403,13 @@ if {$place == "0"} { set place $counter }
 proc topwords:module {nick host hand chan arg} {
 	global black username
 	set arg [split $arg]
-	set topwords_file "$black(dirname)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"
+	set topwords_file "$black(backdir)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"
 	set mask [return_mask [return_host_num "topwords" $chan $host] $host $nick]
 	set handle [nick2hand $nick]
 	set topwords_run 0
 if {[setting:get $chan topwords]} {
-if {![file isdirectory "$black(dirname)/BlackTools/FILES/TOPWORDS/"]} {
-	file mkdir "$black(dirname)/BlackTools/FILES/TOPWORDS/"
+if {![file isdirectory "$black(backdir)/BlackTools/FILES/TOPWORDS/"]} {
+	file mkdir "$black(backdir)/BlackTools/FILES/TOPWORDS/"
 }
 if {![file exists $topwords_file]} {
 	set file [open $topwords_file w]
@@ -510,7 +517,7 @@ if {![info exists black(topwords:$chan:list)]} {
 if {$black(topwords:$chan:list) == ""} {
 	return
 }
-	set topwords_file "$black(dirname)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"
+	set topwords_file "$black(backdir)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"
 if {![file exists $topwords_file]} {
 	return
 }
@@ -588,9 +595,9 @@ if {[string equal -nocase $keyword "ACTION"]} {
 proc topwords:reset {chan} {
 	global black username
 	set found_entry 0
-if {[file exists "$black(dirname)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"]} {
+if {[file exists "$black(backdir)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"]} {
 	set found_entry 1
-	set file [open "$black(dirname)/BlackTools/FILES/TOPWORDS/$username.$chan.txt" w]
+	set file [open "$black(backdir)/BlackTools/FILES/TOPWORDS/$username.$chan.txt" w]
 	close $file
 }
 	return $found_entry
@@ -601,8 +608,8 @@ proc topwords:delete {chan} {
 if {$black(chanremove_all) == "0"} {
 	return
 		}
-if {[file exists "$black(dirname)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"]} {
-	file delete "$black(dirname)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"
+if {[file exists "$black(backdir)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"]} {
+	file delete "$black(backdir)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"
 	}	
 }
 
@@ -613,7 +620,7 @@ if {[clock format [clock seconds] -format "%w"] == 0} {
 	set week_reset 1
 }
 foreach chan [channels] {
-	set tpfile "$black(dirname)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"
+	set tpfile "$black(backdir)/BlackTools/FILES/TOPWORDS/$username.$chan.txt"
 if {[setting:get $chan topwords]} {
 if {![file exists $tpfile]} {
 	continue

+ 45 - 2
BlackTools/lang/BT.en.lang.tcl

@@ -14,7 +14,7 @@
 #                                                  *** The Future is Here ***                                                    #
 #                                                                                     Copyright 2008 - 2018 @ www.tclscripts.net #
 ##################################################################################################################################
-#                                                                                                                         ®      #
+#                                                                                                                         �      #
 #     ######  #          #     #####  #    # ####### ####### ####### #        #####        #          #    #     #  #####        #
 #     #     # #         # #   #     # #   #     #    #     # #     # #       #     #       #         # #   ##    # #     #       #
 #     #     # #        #   #  #       #  #      #    #     # #     # #       #             #        #   #  # #   # #             #
@@ -1311,7 +1311,7 @@ set black(say.en.omsg.1) "\005\[BT\]\005 Message sent to all @'s from: \002%msg%
 
 #################################### forward ###################################
 
-set black(say.en.forward.1) "\005\[PRIVATE MSG\]\005 from -- <\002%msg.1%\002> »»» \001%msg.8%\001"
+set black(say.en.forward.1) "\005\[PRIVATE MSG\]\005 from -- <\002%msg.1%\002> ��� \001%msg.8%\001"
 
 ##################################### mb #######################################
 
@@ -1340,6 +1340,49 @@ set black(say.en.exempt.12) "\005\[BT\]\005 Removed exempt \002%msg.1%\002 on al
 set black(say.en.exempt.15) "\005\[BT\]\005 There is not exempt that matches \002%msg.1%\002 on %chan%"
 set black(say.en.exempt.16) "\005\[BT\]\005 There is not exempt that matches \002%msg.1%\002 for all channels"
 
+###################################### AutoUpdate ################################
+
+set black(say.en.autoupdate.1) "Could not start Update : No TLS package available."
+set black(say.en.autoupdate.2) "Update failed, could not get new updates"
+set black(say.en.autoupdate.3) "Found \001NEW\001 BlackTools \002%msg.1%\002 version, begining download.."
+set black(say.en.autoupdate.4) "Found \001BUG\001 fixes for current installed version \002BlackTools %msg.1%\002, begining download.."
+set black(say.en.autoupdate.5) "No new updates found."
+set black(say.en.autoupdate.6) "Update failed : \002%msg.1%\002"
+set black(say.en.autoupdate.7) "Removing backup files from the last backup ..."
+set black(say.en.autoupdate.8) "Backing UP old \001BlackTools\001 directory ...succeded"
+set black(say.en.autoupdate.9) "Backing UP old \001BlackTools\001 directory ...failed : \002%msg.1%\002"
+set black(say.en.autoupdate.10) "Update failed, could not backup old \001BlackTools.tcl\001 file."
+set black(say.en.autoupdate.11) "Backing UP old \001BlackTools.tcl\001 ...succeded"
+set black(say.en.autoupdate.12) "Backup finished."
+set black(say.en.autoupdate.13) "Saving information from old \001BlackTools.tcl\001 ..."
+set black(say.en.autoupdate.14) "Removing old version of \001BlackTools\001 ..."
+set black(say.en.autoupdate.15) "Downloading BlackTools \001%msg.1%\001. Last bugfix: \002%msg.2%\002"
+set black(say.en.autoupdate.16) "Update failed, could not download \001BlackTools\001."
+set black(say.en.autoupdate.17) "\001BlackTools\001 downloaded in \002%msg.1%\002"
+set black(say.en.autoupdate.18) "Restoring information from old \001BlackTools.tcl\001 ..."
+set black(say.en.autoupdate.19) "Restored \002%msg.1%\002 changed variables from old \001BlackTools\001 config."
+set black(say.en.autoupdate.20) "No variables restored from old \001BlackTools\001 config."
+set black(say.en.autoupdate.21) "Restoring settings, bans and other old information ..."
+set black(say.en.autoupdate.22) "No settings, bans and other information found ..."
+set black(say.en.autoupdate.23) "Restored (\002%msg.1%\002) files that contain settings, bans and other information."
+set black(say.en.autoupdate.24) "\005\[BT\]\005 Update succeded for \001BlackTools\001 in \002%msg.1%\002"
+set black(say.en.autoupdate.25) "If something is wrong the backup FILES are stil available in \001\"%msg.1%\"\001 until next Update. Also you can check the UPDATE LOG in \001\"%msg.2%\"\001"
+set black(say.en.autoupdate.26) "Remember, for information or bug issues visit the official site of \002BT\002 --- \001WwW.TclScripts.Net\001"
+set black(say.en.autoupdate.27) "\005\[BT\]\005 Update started at \001%msg.1%\001"
+set black(say.en.autoupdate.28) "Verifying for new updates.."
+set black(say.en.autoupdate.29) "Update is already runing.."
+set black(say.en.autoupdate.30) "Can't start update. Reason: \002%msg%\002"
+set black(say.en.autoupdate.31) "Can't verify for new update. Please try again later."
+set black(say.en.autoupdate.32) "New version of \001BlackTools\001 found: \002%msg%\002 . Use \001%char%update start\002 to start update"
+set black(say.en.autoupdate.33) "No new version of \001BlackTools\001 found but found a bugfix (\001%msg%\001) for the current one. Use \001%char%update start\002 to start update"
+set black(say.en.autoupdate.34) "\001AutoUpdate\001 is disabled. Reason: \002%msg%\002"
+set black(say.en.autoupdate.35) "\001AutoUpdate\001 is already turned \001on\001 .."
+set black(say.en.autoupdate.36) "\001AutoUpdate\001 module is turned \001ON\001."
+set black(say.en.autoupdate.37) "\001AutoUpdate\001 is already turned \001off\001 .."
+set black(say.en.autoupdate.38) "\001AutoUpdate\001 module is turned \001OFF\001."
+set black(say.en.autoupdate.39) "\001AutoUpdate\001 is running at the moment .."
+set black(say.en.autoupdate.40) "\001AutoUpdate\001 skipped for the moment. Reason: \002Manual update started\002."
+
 ##############################
 ############################################################################################################
 #   END                                                                                                    #

+ 2 - 2
BlackTools/lang/BT.man-en.lang.tcl

@@ -15,7 +15,7 @@
 #                                                                                            Copyright 2008 - 2018 @ www.tclscripts.net #
 #########################################################################################################################################
 #                                                                                                                                       #
-#   ENGLISH LANGUAGE                                                                                                            ®       #
+#   ENGLISH LANGUAGE                                                                                                                   #
 #   ######  #          #     #####  #    # ####### ####### ####### #        #####     #     #    #    #     # #     #    #    #         #
 #   #     # #         # #   #     # #   #     #    #     # #     # #       #     #    ##   ##   # #   ##    # #     #   # #   #         #
 #   #     # #        #   #  #       #  #      #    #     # #     # #       #          # # # #  #   #  # #   # #     #  #   #  #         #
@@ -1753,4 +1753,4 @@ set black(say.en.man.2205) "View options settings: \002%char%show\002 <setting>
 ##############################
 ############################################################################################################
 #   END                                                                                                    #
-############################################################################################################
+############################################################################################################

+ 1 - 1
BlackTools/lang/BT.man-ro.lang.tcl

@@ -1754,4 +1754,4 @@ set black(say.ro.man.2205) "Vizualizare setari optiuni: \002%char%show\002 <seta
 ##############################
 ############################################################################################################
 #   SFARSIT                                                                                                #
-############################################################################################################
+############################################################################################################

+ 46 - 3
BlackTools/lang/BT.ro.lang.tcl

@@ -14,7 +14,7 @@
 #                                                   *** The Future is Here ***                                                   #
 #                                                                                     Copyright 2008 - 2018 @ www.tclscripts.net #
 ##################################################################################################################################
-#                                                                                                                         Ž      #
+#                                                                                                                         ďż˝      #
 #     ######  #          #     #####  #    # ####### ####### ####### #        #####        #          #    #     #  #####        #
 #     #     # #         # #   #     # #   #     #    #     # #     # #       #     #       #         # #   ##    # #     #       #
 #     #     # #        #   #  #       #  #      #    #     # #     # #       #             #        #   #  # #   # #             #
@@ -601,7 +601,7 @@ set black(say.ro.next.4) "\002%current%\002 acum ca ai fost ajutat te rog sa dai
 set black(say.ro.next.5) "Nu ai voie sa faci idle aici! Te rog sa revii pe %chan% atunci cand ai nevoie de ajutor"
 set black(say.ro.next.6) "\005\[BT\]\005 ATENTIE: %nick% are nevoie de ajutor pe %chan%. Acesta este numarul \002%counter%\002 la rand."
 set black(say.ro.next.7) "\005\[BT\]\005 Lista celor care asteapta ajutor este:"
-set black(say.ro.next.8) "\005\[BT\]\005 Nimeni nu are nevoie de ajutor în acest moment."
+set black(say.ro.next.8) "\005\[BT\]\005 Nimeni nu are nevoie de ajutor �n acest moment."
 set black(say.ro.next.9) "%msg%"
 set black(say.ro.next.11) "\005\[BT\]\005 Atentie: \002%current%\002 a fost preluat de \002%nick%\002 (\001%hand%\001)."
 set black(say.ro.next.13) "\005\[BT\]\005 Eroare! \002%msg.1%\002 este in lista de help, dar nu a fost ajutat inca."
@@ -1310,7 +1310,7 @@ set black(say.ro.omsg.1) "\005\[BT\]\005 Mesaj trimis catre toti @ de pe: \002%m
 
 #################################### forward ###################################
 
-set black(say.ro.forward.1) "\005\[BT\]\005 \004\[MESAJ PRIVAT\]\004 de la -- <\002%msg.1%\002> ťťť \001%msg.8%\001"
+set black(say.ro.forward.1) "\005\[BT\]\005 \004\[MESAJ PRIVAT\]\004 de la -- <\002%msg.1%\002> ��� \001%msg.8%\001"
 
 ##################################### mb #######################################
 
@@ -1339,6 +1339,49 @@ set black(say.ro.exempt.12) "\005\[BT\]\005 Am sters exceptia la ban pentru host
 set black(say.ro.exempt.15) "\005\[BT\]\005 Nu exista exceptie la ban pentru host \002%msg.1%\002 pe %chan%"
 set black(say.ro.exempt.16) "\005\[BT\]\005 Nu exista exceptie la ban pentru host \002%msg.1%\002 pentru toate canalele"
 
+###################################### AutoUpdate ################################
+
+set black(say.ro.autoupdate.1) "Nu am putut porni \001UPDATE\001 : Pachetul TLS nu este instalat."
+set black(say.ro.autoupdate.2) "Update-ul a esuat, nu am putut verifica daca exista noi update-uri."
+set black(say.ro.autoupdate.3) "Am gasit versiune \001NOUA\001 de BlackTools \002%msg.1%\002, pornesc descarcarea.."
+set black(say.ro.autoupdate.4) "Am gasit noi bugfix-uri pentru versiunea de \002BlackTools %msg.1%\002 instalata, pornesc descarcarea.."
+set black(say.ro.autoupdate.5) "Nu am gasit noi update-uri."
+set black(say.ro.autoupdate.6) "Update-ul a esuat : \002%msg.1%\002"
+set black(say.ro.autoupdate.7) "Sterg backup facut de la ultimul update realizat..."
+set black(say.ro.autoupdate.8) "Salvez copie de rezerva pentru director \001BlackTools\001 .."
+set black(say.ro.autoupdate.9) "Salvare copie de rezerva la \001BlackTools\001 esuata : \002%msg.1%\002"
+set black(say.ro.autoupdate.10) "Update esuat, nu am putut face copie de rezerva la \001BlackTools.tcl\001."
+set black(say.ro.autoupdate.11) "Salvare copie de rezerva la \001BlackTools.tcl\001 .. realizata"
+set black(say.ro.autoupdate.12) "Copie de rezerva finalizata."
+set black(say.ro.autoupdate.13) "Salvez informatii din vechiul \001BlackTools.tcl\001 ..."
+set black(say.ro.autoupdate.14) "Sterg vechiul \001BlackTools\001 in totalitate ..."
+set black(say.ro.autoupdate.15) "Descarcare BlackTools \002%msg.1%\002. Ultimul bugfix realizat: \002%msg.2%\002"
+set black(say.ro.autoupdate.16) "Update esuat, nu am putut descarca \001BlackTools\001."
+set black(say.ro.autoupdate.17) "\001BlackTools\001 descarcat in \002%msg.1%\002"
+set black(say.ro.autoupdate.18) "Readuc informatiile din vechiul \001BlackTools.tcl\001 ..."
+set black(say.ro.autoupdate.19) "Restaurat \002%msg.1%\002 variabile din vechiul \001BlackTools.tcl\001."
+set black(say.ro.autoupdate.20) "Nicio variabila restaurata din vechiul \001BlackTools.tcl\001."
+set black(say.ro.autoupdate.21) "Readuc setari, banuri si alte informatii ..."
+set black(say.ro.autoupdate.22) "Nu am gasit niciun fisier care sa contina setari, banuri sau alte informatii ..."
+set black(say.ro.autoupdate.23) "Restaurat (\002%msg.1%\002) fisiere care contin setari, banuri si alte informatii."
+set black(say.ro.autoupdate.24) "\005\[BT\]\005 Update pentru \001BlackTools\001 finalizat in \002%msg.1%\002"
+set black(say.ro.autoupdate.25) "Daca ceva nu a mers cum trebuie, copia de rezerva o gasiti in \001\"%msg.1%\"\001 pana la urmatorul update. Puteti vizualiza si LOG-ul de de update in \001\"%msg.2%\"\001"
+set black(say.ro.autoupdate.26) "Tineti minte, pentru informatii si anuntare bug-uri pentru BT --- \002WwW.TclScripts.Net\002"
+set black(say.ro.autoupdate.27) "\005\[BT\]\005 Update pornit la \001%msg.1%\001"
+set black(say.ro.autoupdate.28) "Verific de noi update-uri .."
+set black(say.ro.autoupdate.29) "Este deja pornit.."
+set black(say.ro.autoupdate.30) "Nu am putut porni update. Motiv: \002%msg%\002"
+set black(say.ro.autoupdate.31) "Nu am putut verifica daca exista update-uri noi. Te rog incearca mai tarziu."
+set black(say.ro.autoupdate.32) "Am gasit versiune noua de \001BlackTools\001 : \002%msg%\002. Foloseste \001%char%update start\001 pentru a porni update."
+set black(say.ro.autoupdate.33) "Nu am gasit versiune noua de \001BlackTools\001 dar in schimb am gasit un bugfix (\002%msg%\002) pentru versiunea curenta. Foloseste \001%char%update start\001 pentru a porni update."
+set black(say.ro.autoupdate.34) "\001AutoUpdate\001 este dezactivat. Motiv: \002%msg%\002"
+set black(say.ro.autoupdate.35) "\001AutoUpdate\001 este deja \002pornit\002.."
+set black(say.ro.autoupdate.36) "Ai \002pornit\002 modulul de \001AutoUpdate\001."
+set black(say.ro.autoupdate.37) "\001AutoUpdate\001 este deja \002oprit\002.."
+set black(say.ro.autoupdate.38) "Ai \002oprit\002 modulul de \001AutoUpdate\001."
+set black(say.ro.autoupdate.39) "\001AutoUpdate\001 ruleaza in acest moment.."
+set black(say.ro.autoupdate.40) "\001AutoUpdate\001 sarit momentan. Motiv: \002Update manual activat\002."
+
 ##############################
 ############################################################################################################
 #   SFARSIT                                                                                                #

+ 8 - 2
BlackTools/lang/loader.tcl

@@ -21,9 +21,15 @@
 #                                                 ###############
 #################################################################
 
+if {[info exists black(backup_update)]} {
+	set black(backdir) $black(backup_dir)
+} else {
+	set black(backdir) $black(dirname)
+}
+
 #load language
 
-	set get_lang_files [glob -directory "$black(dirname)/BlackTools/lang" "*.??.lang.tcl"]
+	set get_lang_files [glob -directory "$black(backdir)/BlackTools/lang" "*.??.lang.tcl"]
 foreach lang $get_lang_files {
 	set black(lang_error_$lang) [catch {source $lang} black(lang_error_stats_$lang)]
 if {$black(lang_error_$lang) == "1"} {
@@ -40,7 +46,7 @@ if {![info exists black(current_lang) ]} {set black(current_lang) "N/A"}
 
 #load manual
 
-set get_man_files [glob -directory "$black(dirname)/BlackTools/lang" "*.???-??.lang.tcl"]
+set get_man_files [glob -directory "$black(backdir)/BlackTools/lang" "*.???-??.lang.tcl"]
 foreach lang $get_man_files {
 	set black(man_error_$lang) [catch {source $lang} black(man_error_stats_$lang)]
 if {$black(man_error_$lang) == "1"} {

+ 1 - 0
BlackTools/temp/anunt_temp.20200404000405.txt

@@ -0,0 +1 @@
+űáúzúúőűá7