This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

weird issue with chattr inside of switch

Help for those learning Tcl or writing their own scripts.
Post Reply
L
Luminous
Op
Posts: 146
Joined: Fri Feb 12, 2010 1:00 pm

weird issue with chattr inside of switch

Post by Luminous »

I am building a user script to add, modify and delete userfiles. Right now, I am having a weird issue involving changing flags. I have one section, for instance, that gives channel flag f. However, in addition to the f channel flag, they get pretty much all global flags as well, including m and n. :x I cannot for the life of me figure out why either, because I have an "!voice NICK" script that gives them voice and my autovoice flag, and it doesn't mess with any other flags. other similar scripts are the same way. Also, in this script, if someone uses "!users del NICK", $nick is also awarding a plethora of global flags, despite not having any chattr in that area of the switch. Please help?

Code: Select all

bind pub nfo|nfo !users user
proc user {nick uhost hand chan text} {
	set option1 [lindex [split $text] 0]
	set whom [lindex [split $text] 1]
	set option2 [lindex [split $text] 2]
	if {$option1 == ""} {
		putserv "NOTICE $nick :Option1 includes\: add, del or mod."
		return 0
	}
	set host "$whom![getchanhost $whom $chan]"
	set split(host) [lindex [split $host !@] 2]
	set user [string range [regsub -nocase -all -- {[^a-z\-]} $whom ""] 0 8]
	switch -- $option1 {
		add {
			if {$whom == ""} {
				putserv "NOTICE $nick :Syntax is\: \"!users add <nick> \[voice/friend\](optional)\"."
				return 0
			} elseif {![onchan $whom $chan]} {
				putserv "NOTICE $nick :$whom is not here."
				return 0
			}
			if {$option2 == ""} {
				if {[validuser [nick2hand $whom $chan]]} {
					putserv "NOTICE $nick :User file for $whom already exists, please use \"!hosts add $whom\" to add a host."
					return 0
				} else {
					if {[regexp -nocase -- {@([:0-9A-Fa-f]+$)} $host a b]} {
						adduser $user "$user!*@$b"
						save
					} elseif {[regexp -nocase -- {@(.*)?(\d+(.|-)){4}} $host]} {
						adduser $user "$user!*@*.[lrange [split $host .] 1 end]"
						save
					} elseif {[regexp -nocase -- {@.*([-./][[:alnum:]]+[-./][[:alnum:]]{2,4})$} $host a]} {
						adduser $user "$user!*$a"
						save
					} else {
						putnotc $nick "Host match error!"
						return
					}
					putserv "NOTICE $nick :Userfile created for $whom."
				}
			} else {
				if {![validuser [nick2hand $whom $chan]]} {
					adduser $user $option2
					save
				}
			}
		}
		del {
			if {[matchattr [nick2hand $nick $chan] |o $chan]} {
				if {$option2 != ""} {
					putserv "NOTICE $nick :Syntax is\: \"!users del <nick>\"."
					return 0
				} elseif {$whom == ""} {
					putserv "NOTICE $nick :You must specify who to delete."
					return 0
				} elseif {![validuser [nick2hand $whom $chan]]} {
					putserv "NOTICE $nick :I have no user info for $whom."
					return 0
				}
				deluser [nick2hand $whom $chan]
				putserv "NOTICE $nick :Userfile for $whom has been deleted."
				save
			} else {
				putserv "NOTICE $nick :You don't have access to this command."
				return 0
			}
		}
		mod {
			if {$whom == "" || $option2 == ""} {
				putserv "NOTICE $nick :Syntax is\: \"!users mod <nick> <voice/devoice/friend/unfriend/bop>\"."
				return 0
			} elseif {![onchan $whom $chan]} {
				putserv "NOTICE $nick :$whom is not here."
				return 0
			} elseif {![validuser [nick2hand $whom $chan]]} {
				putserv "NOTICE $nick :I have no user info for $whom, please add them with \"!users add $whom\"."
				return 0
			}
			chattr [nick2hand $whom $chan] $option2
			save
		}
	}
	switch -- $option2  {
		friend {
			if {![onchan $whom $chan]} {
				putserv "NOTICE $nick :$whom is not here."
				return 0
			} else {
				chattr [nick2hand $whom $chan] |+f $chan
				save
				putserv "NOTICE $nick :$whom is now a friend of mine! <3"
			}
		}
		unfriend {
			if {![matchattr [nick2hand $nick $chan] |o $chan] && $option1 == "mod" || $option1 == "add"} {
				putserv "NOTICE $nick :You don't have access to this command."
				return 0
			} elseif {![onchan $whom $chan]} {
				putserv "NOTICE $nick :$whom is not here."
				return 0
			}
			chattr [nick2hand $whom $chan] |-f $chan
			save
			putserv "NOTICE $nick :$whom is no longer a friend of mine! </3"
		}

		voice {
			if {![onchan $whom $chan]} {
				putserv "NOTICE $nick :$whom is not here."
				return 0
			}
			pushmode $chan +v $whom
			if {![validuser [nick2hand $whom $chan]]} {
				if {[regexp -nocase -- {@([:0-9A-Fa-f]+$)} $host a b]} {
					adduser $user "$user!*@$b"
					save
				} elseif {[regexp -nocase -- {@(.*)?(\d+(.|-)){4}} $host]} {
					adduser $user "$user!*@*.[lrange [split $host .] 1 end]"
					save
				} elseif {[regexp -nocase -- {@.*([-./][[:alnum:]]+[-./][[:alnum:]]{2,4})$} $host a]} {
					adduser $user "$user!*$a"
					save
				}
				chattr $user |+A $chan
				save
				putserv "NOTICE $nick :$whom will now be voiced on join."
			} else {
				set check [nick2hand $whom $chan]
				if {![matchattr $check A|A $chan]} {
					chattr $check |+A $chan
					save
					putserv "NOTICE $nick :$whom was successfully added to the autovoice list."
				} else {
					return 0
				}
			}
		}
		devoice {
			if {![matchattr [nick2hand $nick $chan] |o $chan] && $option1 == "mod" || $option1 == "add"} {
				putserv "NOTICE $nick :You don't have access to this command."
				return
			} elseif {![onchan $whom $chan]} {
				putserv "NOTICE $nick :$whom is not here."
				return 0
			}
			pushmode $chan -v $whom
			if {![validuser [nick2hand $whom $chan]] || ![matchattr [nick2hand $whom $chan] |A $chan]} {
				return 0
			} else {
				chattr [nick2hand $whom $chan] |-A $chan
				save
				putserv "NOTICE $nick :$whom will no longer de voiced on join"
			}
		}
		bop {
			if {![matchattr $nick |oO $chan]} {
				putserv "NOTICE $nick :You do not have permission to use this command."
				return 0
			}
			chattr [nick2hand $whom $chan] |+ol $chan
			save
			putserv "NOTICE $nick :$whom can now use my op comands on $chan."
		}
	}
}
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

I'd suspect this line:

Code: Select all

         chattr [nick2hand $whom $chan] $option2
Assuming the case "!users mod nml375 friend" that would let $option1 be mod and $option2 "friend". Since the above command is included in the "mod" case of the first switch, we'd effectively grant me n (owner) privileges, which would add pretty much any and all (except dk) other flags.
NML_375
L
Luminous
Op
Posts: 146
Joined: Fri Feb 12, 2010 1:00 pm

Post by Luminous »

I still don't understand why that does that... or how to avoid it...
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Well, in that scenario; $option2 would be the string "friend".
So in essence, you do this:

Code: Select all

chattr [nick2hand $whom $chan] friend
Aka, grant $whom Friend, dehalfop, unknown flag i, nethack-exempt, Owner (overrules the dehalfop and deop, and adds op, halfop, master, botnet master, etc), deop.
Thus, since $option2 contains the letter n, the user is granted owner privileges.
NML_375
L
Luminous
Op
Posts: 146
Joined: Fri Feb 12, 2010 1:00 pm

Post by Luminous »

Lol :lol:

So I am guessing I cannot use words then? That seems really, really silly...
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Not directly with chattr..
You could very well use a piece of code like your second switch-construct, where you map the different words to the corresponding flags, but that won't make you much good if you also use that word directly with chattr...
NML_375
L
Luminous
Op
Posts: 146
Joined: Fri Feb 12, 2010 1:00 pm

Post by Luminous »

Hm, okay.. um.... hm... I'm going to have to think about this one.. :S The only work-around I see right off the bat is to do another chattr immediately after the first to cancel out unwanted global flags. This will be ugly, but probably effective...

Can I put a switch within a switch? If so, then make I can use switch to swtich what $option2 add/removes based on user input... gah.. neither way sounds ideal...
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Stacking switch-constructs isn't much harder than stacking if-conditionals.

Personally, I'd either drop the whole "word" approach, and only use flags; or take out that very line I mentioned earlier, and only use words to alter flags..

I would strongly recommend against trying to reverse unwanted modes once they've been done. Do it right in the first place instead.
NML_375
L
Luminous
Op
Posts: 146
Joined: Fri Feb 12, 2010 1:00 pm

Post by Luminous »

I've decided to do away with "switch -- $option2 {" alltogether. I'm going to try to make mod do what I want, using if/elseif to track the word input that is option2. "Friend" will give |+f, etc... it should clear up that conflict, at least. And, yes, I was not all happy about the whole counter-acting chattr idea...
L
Luminous
Op
Posts: 146
Joined: Fri Feb 12, 2010 1:00 pm

Post by Luminous »

Okay, I don't think I can do switch within switch, its saying that I have a switch without a body. :\ And using if/elseif doesn't render errors, but doesn't do anything. Here's the new version:

Code: Select all

bind pub nfo|nfo !users user
proc user {nick uhost hand chan text} {
	set option1 [lindex [split $text] 0]
	set whom [lindex [split $text] 1]
	set option2 [lindex [split $text] 2]
	if {$option1 == ""} {
		putserv "NOTICE $nick :Option1 includes\: add, del or mod."
		return 0
	}
	set host "$whom![getchanhost $whom $chan]"
	set split(host) [lindex [split $host !@] 2]
	set user [string range [regsub -nocase -all -- {[^a-z\-]} $whom ""] 0 8]
	switch -- $option1 {
		add {
			if {$whom == ""} {
				putserv "NOTICE $nick :Syntax is\: \"!users add <nick> \[voice/friend\](optional)\"."
				return 0
			} elseif {![onchan $whom $chan]} {
				putserv "NOTICE $nick :$whom is not here."
				return 0
			}
			if {$option2 == ""} {
				if {[validuser [nick2hand $whom $chan]]} {
					putserv "NOTICE $nick :User file for $whom already exists, please use \"!hosts add $whom\" to add a host."
					return 0
				} else {
					if {[regexp -nocase -- {@([:0-9A-Fa-f]+$)} $host a b]} {
						adduser $user "$user!*@$b"
						save
					} elseif {[regexp -nocase -- {@(.*)?(\d+(.|-)){4}} $host]} {
						adduser $user "$user!*@*.[lrange [split $host .] 1 end]"
						save
					} elseif {[regexp -nocase -- {@.*([-./][[:alnum:]]+[-./][[:alnum:]]{2,4})$} $host a]} {
						adduser $user "$user!*$a"
						save
					} else {
						putnotc $nick "Host match error!"
						return
					}
					putserv "NOTICE $nick :Userfile created for $whom."
				}
			} else {
				if {![validuser [nick2hand $whom $chan]]} {
					adduser $user $option2
					save
				}
			}
		}
		del {
			if {[matchattr [nick2hand $nick $chan] |o $chan]} {
				if {$option2 != ""} {
					putserv "NOTICE $nick :Syntax is\: \"!users del <nick>\"."
					return 0
				} elseif {$whom == ""} {
					putserv "NOTICE $nick :You must specify who to delete."
					return 0
				} elseif {![validuser [nick2hand $whom $chan]]} {
					putserv "NOTICE $nick :I have no user info for $whom."
					return 0
				}
				deluser [nick2hand $whom $chan]
				putserv "NOTICE $nick :Userfile for $whom has been deleted."
				save
			} else {
				putserv "NOTICE $nick :You don't have access to this command."
				return 0
			}
		}
		mod {
			if {$whom == ""} {
				putserv "NOTICE $nick :Syntax is\: \"!user mod <nick> <voice/devoice/exempt/unexem\
					pt>\"."
				return 0
			} elseif {$option2 == ""} {
				putserv "NOTICE $nick :Syntax is\: \"!user mod <nick> <voice/devoice/exempt/unexempt>\"."
				return 0
			}
			if {![validuser [nick2hand $whom $chan]]} {
				putserv "NOTICE $nick :I have no user info for $whom, please add them with
				\"!users add $whom\"."
				return 0
			}
			switch -- $option2 {
				friend {
					chattr [nick2hand $whom $chan] |+f $chan
					putserv "NOTICE $nick :$whom is now a friend of mine! <3"
					save
				}
				unfriend {
					if {![matchattr [nick2hand $whom $chan] |+o $chan]} {
						putnotc $nick "You don't access to this command."
						return
					}
					chattr [nick2hand $whom $chan] |-f $chan
					save
					putserv "NOTICE $nick :$whom is no longer a friend of mine! </3"
				}
				voice {
					pushmode $chan +v $whom
					if {![validuser [nick2hand $whom $chan]]} {
						if {[regexp -nocase -- {@([:0-9A-Fa-f]+$)} $host a b]} {
							adduser $user "$user!*@$b"
							save
						} elseif {[regexp -nocase -- {@(.*)?(\d+(.|-)){4}} $host]} {
							adduser $user "$user!*@*.[lrange [split $host .] 1 end]"
							save
						} elseif {[regexp -nocase -- {@.*([-./][[:alnum:]]+[-./][[:alnum:]]{2,4})$} $host a]\
							} {
							adduser $user "$user!*$a"
							save
						}
						chattr $user |+A $chan
						save
						putserv "NOTICE $nick :$whom will now be voiced on join."
					} else {
						set check [nick2hand $whom $chan]
						if {![matchattr $check A|A $chan]} {
							chattr $check |+A $chan
							save
							putserv "NOTICE $nick :$whom was successfully added to the autovoice list."
						} else {
							return 0
						}
					}
				}
				devoice {
					if {![matchattr [nick2hand $nick $chan] |o $chan]} {
						putserv "NOTICE $nick :You don't have access to this command."
						return
					} elseif {![onchan $whom $chan]} {
						putserv "NOTICE $nick :$whom is not here."
						return 0
					}
					if {![validuser [nick2hand $whom $chan]] || ![matchattr [nick2hand $whom $chan] |A $chan]} {
						return 0
					} else {
						pushmode -v $whom
						chattr [nick2hand $whom $chan] |-A $chan
						save
						putserv "NOTICE $nick :$whom will no longer de voiced on join"
					}
				}
				bop {
					if {![matchattr [nick2hand $nick $chan] |oO $chan]} {
						putserv "NOTICE $nick :You do not have permission to use this command."
						return 0
					}
					chattr [nick2hand $whom $chan] |+ol $chan
					save
					putserv "NOTICE $nick :$whom can now use my op comands on $chan."
				}
			}
		}
	}
}
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

The actual error message would help.. though I'm guessing you've got this?

Code: Select all

extra switch pattern with no body
That means there's one case that has no piece of code associated with it. A simple example would be this:

Code: Select all

switch $somevar {
  "foo" {
    putlog "bar!"
  }
  "bar"
}
"foo" is correct, as it has a "body" (code to execute). "bar" is not however.
All this is actually a tcl-list, where the odd indices are cases/pattern, and even indices are bodies/pieces of code. If there's an un-even number of list items, you get this error.

I've noticed that you put linebreaks in the middle of commands and conditionals. In some cases escaping them with \, in other cases not at all. Please avoid this, as it only makes it harder to read the code, and follow your logics.

All this said, the most likely cause for the error is a stray } somewhere in there, or mis-aligned lines of code and }'s.
NML_375
L
Luminous
Op
Posts: 146
Joined: Fri Feb 12, 2010 1:00 pm

Post by Luminous »

Sorry about the linebreaks, I tried to fix them. :\ its just how my editor wraps long lines, I don't actually do that intentionally...

Yes, that is the error message I got. I had gone through it heavily before, including putting it on paste.tclhelp.net, and I found no errors related with braces. However, I went through it by hand and finally did find the problem: it was in add. I have accidentally exited the switch prematurely, thus messing up the whole script. :oops:

But.. seems to be working now, thanks for the assist. :) I learned something new.
Post Reply