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.

Deleting a line from a file - problem with special chars

Help for those learning Tcl or writing their own scripts.
Post Reply
User avatar
awyeah
Revered One
Posts: 1580
Joined: Mon Apr 26, 2004 2:37 am
Location: Switzerland
Contact:

Deleting a line from a file - problem with special chars

Post by awyeah »

Here is a script I coded recently, but I'm having problems for nicks with special characters. When I delete a nick with a special character:

1) It says nick not found in the database (text file)
2) The database file containing all the nicks becomes empty.

I need these two errors to be fixed if possible, for the script to work fine. Can anyone help me to rectify these errors if possible?

Here is the testing I did:
<awyeah> .aovadd AhB
<adapter> AhB has been successfully added to the AOv list.
* adapter sets mode: +v-k AhB Added.to.AOv.list

<awyeah> .aovdel AhB
<adapter> AhB has been successfully removed from the AOv list.
* adapter sets mode: -vk AhB Removed.from.AOv.list
<awyeah> .aovadd [Nadia]
* adapter sets mode: +v-k [Nadia] Added.to.AOv.list

<awyeah> .aovdel [Nadia]
<adapter> [Nadia] was not found in the AOv list.

<awyeah> .aovlist
-adapter- AOv list for #pak
-adapter- 1 - \[Nadia\] (aov@pak.dal.net)
-adapter- End of list.

Text file contains this entry:
[Nadia]:#pak
adapter- AOv list for #pak
-adapter- 1 - \[Nadia\] (aov@klsex.dal.net)
-adapter- 2 - \[DeV-Kl\] (aov@klsex.dal.net)
-adapter- End of list.

<awyeah> .delaov [Nadia]
<adapter> [Nadia] was not found in the AOv list of #pak.

<awyeah> .listaov
-adapter- AOv list for #pak
-adapter- End of list.
Is my code okay and proper for deleting a specified nick from the database file? Also and suggestions on how to fix the script, so it deletes nicks with special characters from the database file??

Here is my code:

Code: Select all

proc aov:add {nick uhost hand chan arg} {
 global aov sov
 set arg [string map {\\ \\\\ [ \\\[ ] \\\] \{ \\\{ \} \\\}} $arg]
 if {$arg != ""} {
  set fp [open $sov r+]
  set data [read -nonewline $fp]
  close $fp
  set list [split [string map {\\ \\\\ [ \\\[ ] \\\] \{ \\\{ \} \\\}} $data]]
  if {[lsearch -exact [string tolower $list] [string tolower [lindex $arg 0]]:[string tolower $chan]] != -1} {
   putserv "PRIVMSG $chan :You are already a SOv on [string tolower $chan]. You cannot add yourself to the AOv list of [string tolower $chan]."
   return 0
  }
  if {([lsearch -exact [string tolower $list] [string tolower $nick]:[string tolower $chan]] != -1) || [matchattr $hand mn|mn $chan]} {
   set user [lindex $arg 0]:[string tolower $chan]
   set fp [open $aov r+]
   set data [read -nonewline $fp]
   close $fp
   set list2 [split [string map {\\ \\\\ [ \\\[ ] \\\] \{ \\\{ \} \\\}} $data]]
   if {[lsearch -exact [string tolower $list2] [string tolower $user]] == -1} {
    set file [open $aov a+]
    puts $file $user
    close $file
    putserv "PRIVMSG $chan :[lindex $arg 0] has been successfully added to the AOv list of [string tolower $chan]."
    utimer 3 [list aov:on:add [lindex $arg 0] $chan]
    return 0
   } else {
     putserv "PRIVMSG $chan :[lindex $arg 0] already exists on the AOv list of [string tolower $chan]."
     return 0
     }
   } else {
      putserv "PRIVMSG $chan :You do not have access to modify the AOv list of [string tolower $chan]."; return 0
      }
   }
}

proc aov:delete {nick uhost hand chan arg} {
 global aov sov
 set arg [string map {\\ \\\\ [ \\\[ ] \\\] \{ \\\{ \} \\\}} $arg]
 if {[info exists list3]} { unset list3 }
 if {$arg != ""} {
  set fp [open $sov r+]
  set data [read -nonewline $fp]
  close $fp
  set list [split [string map {\\ \\\\ [ \\\[ ] \\\] \{ \\\{ \} \\\}} $data]]
  set fp [open $aov r+]
  set data [read -nonewline $fp]
  close $fp
  set list2 [split [string map {\\ \\\\ [ \\\[ ] \\\] \{ \\\{ \} \\\}} $data]]
  if {([lsearch -exact [string tolower $list] [string tolower $nick]:[string tolower $chan]] != -1) || ([lsearch -exact [string tolower $list2] [string tolower $nick]:[string tolower $chan]] != -1) || [matchattr $hand mn|mn $chan]} {
   set user [lindex $arg 0]:[string tolower $chan]
   set fp [open $aov r+]
   set data [read -nonewline $fp]
   close $fp
   set list3 [split [string map {\\ \\\\ [ \\\[ ] \\\] \{ \\\{ \} \\\}} $data]]
   set fd [open $aov w+]
   if {[set i [lsearch -exact [string tolower $list3] [string tolower $user]]] != -1} {
     set fd [open $aov w+]
     puts -nonewline $fd [join [lreplace $list3 $i $i] \n]
     close $fd
     putserv "PRIVMSG $chan :[lindex $arg 0] has been successfully removed from the AOv list of [string tolower $chan]."
     utimer 3 [list aov:on:del [lindex $arg 0] $chan]
   } else {
     putserv "PRIVMSG $chan :[lindex $arg 0] was not found in the AOv list of [string tolower $chan]."
     return 0
     }
   } else {
     putserv "PRIVMSG $chan :You do not have access to modify the AOv list of [string tolower $chan]."
    }
   if {[info exists list3]} { close $fd; unset list3; return 0 }
  }
}
Also a similar problem here, when I try to delete more than 1 line from the text file, the whole file gets erased. This is the code for deleting more than 1 line from the database:

Code: Select all

proc sov:wipe {nick uhost hand chan arg} {
 global aov sov
  set fp [open $sov r+]
  set data [read -nonewline $fp]
  close $fp
  set list [split [string map {\\ \\\\ [ \\\[ ] \\\] \{ \\\{ \} \\\}} $data]]
  if {[matchattr $hand mn|mn $chan]} {
  set fd [open $sov w+]
  set list3 [list]
   foreach user $list {
    if {[set i [lsearch -exact [string tolower $list] [string tolower $user]]] != -1} {
     set list3 [lreplace $list3 $i $i]
     }
   }
   puts -nonewline $fd [join $list3 "\n"]
   putserv "PRIVMSG $chan :The SOv list of [string tolower $chan] has been wiped successfully."
   close $fd
  }
  set fp [open $aov r+]
  set data [read -nonewline $fp]
  close $fp
  set list2 [split [string map {\\ \\\\ [ \\\[ ] \\\] \{ \\\{ \} \\\}} $data]]
  if {([lsearch -exact [string tolower $list] [string tolower $nick]:[string tolower $chan]] != -1) || ([lsearch -exact [string tolower $list2] [string tolower $nick]:[string tolower $chan]] != -1)} {
   putserv "PRIVMSG $chan :You do not have access to wipe the SOv list of [string tolower $chan]."
   return 0
   }
}
·­awyeah·

==================================
Facebook: jawad@idsia.ch (Jay Dee)
PS: Guys, I don't accept script helps or requests personally anymore.
==================================
User avatar
rosc2112
Revered One
Posts: 1454
Joined: Sun Feb 19, 2006 8:36 pm
Location: Northeast Pennsylvania

Post by rosc2112 »

Get rid of the string map kludge stuff and use [split] and [join] properly like you should. There is a file that explains how to make scripts tcl-special-char safe, check around the forum or google it.
User avatar
awyeah
Revered One
Posts: 1580
Joined: Mon Apr 26, 2004 2:37 am
Location: Switzerland
Contact:

Post by awyeah »

So all the elements in the database are deleted due to the special character thing? It's not cause of a faulty coding in the delete proc? Hmm okay, i'll look about split and join, thanks!
·­awyeah·

==================================
Facebook: jawad@idsia.ch (Jay Dee)
PS: Guys, I don't accept script helps or requests personally anymore.
==================================
User avatar
awyeah
Revered One
Posts: 1580
Joined: Mon Apr 26, 2004 2:37 am
Location: Switzerland
Contact:

Post by awyeah »

1) First I used split on $arg to convert it into a list.
2) Then and the user i want to add, delete or even match in the database (list), i convert that into a string either by using split or just even by string tolower (when im using lsearch with the option -exact to match the element in the list -- so should be in the same case).

But it still doesn't seem to work. When I try to delete a nick with a special character, say [, ] etc it will just delete all the users in the database and generate and empty text file.

I think maybe there is a problem maybe with my proc which is deleting the users from the database then maybe (aov:del). Can anyone have a look and tell me where the problem might be maybe, or is it still the special characters? I've used join and split as instructed and even user a filter before for special characters (string map, regsub). Thanks!

Here is the code:

Code: Select all

proc aov:add {nick uhost hand chan arg} {
 global aov sov
 set arg [split $arg]
 if {$arg != ""} {
  set fp [open $sov r+]
  set data [read -nonewline $fp]
  close $fp
  set list [split $data "\n"]
  if {[lsearch -exact [split [string tolower $list]] [string tolower [lindex $arg 0]:$chan]] != -1} {
   putserv "PRIVMSG $chan :You are already a SOv on \002[string tolower $chan]\002. You cannot add yourself to the AOv list of \002[string tolower $chan]\002."
   return 0
  }
  if {([lsearch -exact [split [string tolower $list]] [string tolower $nick:$chan]] != -1) || [matchattr $hand mn|mn $chan]} {
   set user [string tolower [lindex $arg 0]:$chan]
   set fp [open $aov r+]
   set data [read -nonewline $fp]
   close $fp
   set list2 [split $data "\n"]
   if {[lsearch -exact [split [string tolower $list2]] $user] == -1} {
    set file [open $aov a+]
    puts $file $user
    close $file
    putserv "PRIVMSG $chan :\002[lindex [split $arg] 0]\002 has been successfully added to the AOv list of \002[string tolower $chan]\002."
    utimer 3 [list aov:on:add [lindex [split $arg] 0] $chan]
    return 0
   } else {
     putserv "PRIVMSG $chan :\002[lindex [split $arg] 0]\002 already exists on the AOv list of \002[string tolower $chan]\002."
     return 0
     }
   } else {
      putserv "PRIVMSG $chan :You do not have access to modify the AOv list of \002[string tolower $chan]\002."; return 0
      }
   }
}

proc aov:delete {nick uhost hand chan arg} {
 global aov sov
 set arg [split $arg]
 if {$arg != ""} {
  set fp [open $sov r+]
  set data [read -nonewline $fp]
  close $fp
  set list [split $data "\n"]
  set fp [open $aov r+]
  set data [read -nonewline $fp]
  close $fp
  set list2 [split $data "\n"]
  if {([lsearch -exact [split [string tolower $list]] [string tolower $nick:$chan]] != -1) || ([lsearch -exact [split [string tolower $list2]] [string tolower $nick:$chan]] != -1) || [matchattr $hand mn|mn $chan]} {
   set user [string tolower [lindex $arg 0]:$chan]
   set fd [open $aov w+]
   if {[set i [lsearch -exact [split [string tolower $list2]] $user]] != -1} {
     set fd [open $aov w+]
     puts -nonewline $fd [join [lreplace $list2 $i $i] \n]
     close $fd
     putserv "PRIVMSG $chan :\002[lindex [split $arg] 0]\002 has been successfully removed from the AOv list of \002[string tolower $chan]\002."
     utimer 3 [list aov:on:del [lindex $arg 0] $chan]
   } else {
     putserv "PRIVMSG $chan :\002[lindex [split $arg] 0]\002 was not found in the AOv list of \002[string tolower $chan]\002."
     return 0
     }
   } else {
     putserv "PRIVMSG $chan :You do not have access to modify the AOv list of \002[string tolower $chan]\002."
    }
  }
}
Tried this also:

Code: Select all

set arg [split $arg]
set user [join [string tolower [lindex $arg 0]:$chan]]
###OR###
set user [join [lindex $arg 0]:$chan]

Since I think when using lsearch $list should be split, but the *pattern* can be a string, as I checked in the tcl manual, hence [join] and [string tolower] both produce a string.
·­awyeah·

==================================
Facebook: jawad@idsia.ch (Jay Dee)
PS: Guys, I don't accept script helps or requests personally anymore.
==================================
User avatar
Sir_Fz
Revered One
Posts: 3794
Joined: Sun Apr 27, 2003 3:10 pm
Location: Lebanon
Contact:

Post by Sir_Fz »

You have problem with using strings and lists. You're creating a list called $list and then you apply [string tolower] over it - bad idea. How about:

Code: Select all

set list [split [string map {\\ \\\\ [ \\\[ ] \\\] \{ \\\{ \} \\\}} [string tolower $data]]]
and now you have a list of lower-case elements.

Hint: Apply the string match over the elements you want to use in the <match> and not over the string that you're matching from. (i.e. string match <match> <match-string>) apply the string map on <match>.
User avatar
awyeah
Revered One
Posts: 1580
Joined: Mon Apr 26, 2004 2:37 am
Location: Switzerland
Contact:

Post by awyeah »

But here I am not using string match, I am using lsearch. So u mean instead of lsearch I should use string match/equal with a foreach loop?

Something like this is it?

Code: Select all

set arg [split $arg]
set fp [open $sov r+] 
set data [read -nonewline $fp] 
close $fp 
set list [split [string map {\\ \\\\ [ \\\[ ] \\\] \{ \\\{ \} \\\}} [string tolower $data]]]
foreach person $list {
if {[string match -nocase *$person* [lindex $arg 0]:$chan]} {
 set matchfound 1; break
 }
}

###OR###

set arg [split $arg]
set fp [open $sov r+] 
set data [read -nonewline $fp] 
close $fp 
set list [split [string map {\\ \\\\ [ \\\[ ] \\\] \{ \\\{ \} \\\}} [string tolower $data]]]
if {[string match -nocase *[lindex $arg 0]:$chan* $list]} {
 #do stuff
}
Okay, I'll give it a go, thanks!
·­awyeah·

==================================
Facebook: jawad@idsia.ch (Jay Dee)
PS: Guys, I don't accept script helps or requests personally anymore.
==================================
User avatar
awyeah
Revered One
Posts: 1580
Joined: Mon Apr 26, 2004 2:37 am
Location: Switzerland
Contact:

Post by awyeah »

Thanks for the help. I was able to solve the problem, using string match instead of lsearch.

The only thing to be done was to split the input argument and to use lindex for string equal with the nick:chan variable.

For the second part to delete a line, lists have to be used. So I converted the match into a string, and then split the list and also split the match when using lsearch.

Basically the filter was causing the problem, which I was able to solve using the split, join and string tolower commands.

The code to one of the working procs:

Code: Select all

proc aov:delete {nick uhost hand chan arg} {
 global aov sov
 set arg [split $arg]
 set chan [string tolower $chan]
 if {$arg == ""} { putserv "PRIVMSG $chan :Usage: !delaov <nick>"; return 0 }
  set fp [open $sov r+]
  set data [read -nonewline $fp]
  close $fp
  set sovlist [split $data "\n"]
  set fp [open $aov r+]
  set data [read -nonewline $fp]
  close $fp
  set aovlist [split $data "\n"]

  #check if user has access level sov or founder
  if {[matchattr $hand mn|mn $chan]} { set founder:ok 1 }
  foreach person $sovlist {
   if {[string equal -nocase "$nick:$chan" $person]} {
    set sov:ok 1; break
    }
  }
  foreach person $aovlist {
   if {[string equal -nocase "$nick:$chan" $person]} {
    set aov:ok 1; break
    }
  }
  #if access level not sov or founder stop
  if {![info exists founder:ok] || ![info exists sov:ok] || ![info exists aov:ok]} {
   putserv "NOTICE $nick :You do not have access to modify the AOv list of $chan."
   return 0
  }

  #check if access level is aov
  foreach person $aovlist {
   if {[string equal -nocase "$nick:$chan" $person]} {
    set aov:user 1; break
    }
  }
  #user has aov access
  if {[info exists aov:user]} {
   #if argument contains same nick as user
   if {[string equal -nocase "[lindex $arg 0]:$chan" $nick:$chan]} {
    #del nick from aov list
    set user [string tolower [lindex $arg 0]]:$chan
    set i [lsearch -exact [split [string tolower $aovlist]] [split $user]]
    set fd [open $aov w+]
    puts -nonewline $fd [join [lreplace $aovlist $i $i] "\n"]
    close $fd
    putserv "PRIVMSG $chan :[lindex $arg 0] has been successfully removed from the AOv list of $chan."
    utimer 2 [list aov:on:del [lindex $arg 0] $chan]
    return 0
   } else {
    putserv "NOTICE $nick :You do not have access to modify the AOv list of $chan."
    return 0
    }
  }

  #check if user is in sov or founder
  foreach person $sovlist {
   if {[string equal -nocase "$nick:$chan" $person]} {
    set sov:found 1; break
    }
  }
  #if user has sov or founder access level
  if {[info exists sov:found] || [matchattr $hand mn|mn $chan]} {
  #check if aov is in list or not
   foreach person $aovlist {
    if {[string equal -nocase "[lindex $arg 0]:$chan" $person]} {
    set aov:found 1; break
    }
   }
  #if aov is not in list stop
  if {![info exists aov:found]} {
   putserv "PRIVMSG $chan :[lindex $arg 0] was not found in the AOv list of $chan."
   return 0
  #if aov is in list then delete
  } else {
   set user [string tolower [lindex $arg 0]]:$chan
   set i [lsearch -exact [split [string tolower $aovlist]] [split $user]]
   set fd [open $aov w+]
   puts -nonewline $fd [join [lreplace $aovlist $i $i] "\n"]
   close $fd
   putserv "PRIVMSG $chan :[lindex $arg 0] has been successfully removed from the AOv list of $chan."
   utimer 2 [list aov:on:del [lindex $arg 0] $chan]
   return 0
  }
 }
}
·­awyeah·

==================================
Facebook: jawad@idsia.ch (Jay Dee)
PS: Guys, I don't accept script helps or requests personally anymore.
==================================
Post Reply