Scanning For Clones

Contributed by dohcan
This tutorial attempts to show an easy but effective way to scan for clones. There are several different ways to scan for clones, so this is not only way or the fastest way. This tutorial assumes basic knowledge of mIRC scripting, and focuses on using @windows, $address, and $nick. The IAL is required to be enabled and updated. Full source code of the clone scan will be provided at the end of this tutorial.
What Are Clones?
When you have several clients from the same IP address, it is called "cloning." This is usually considered harmful by channel operators because people use clones to flood channels and otherwise cause trouble. What we will be calling clones are multiple clients from the exact same IP address:
[email protected]
[email protected]
Since their IP addresses are the same, they would be considered clones. Other people may consider multiple clients from the same host (*.host.com) to be clones. Depending on your situation, you can easily scan for whatever type of hostmask you are looking for.
How Do We Do It?
For this example, we will be using two custom @windows along with $nick(#, 0) and $address(nick, 2) to do our scanning. Using "2" as the hostmask type, we get the result *!*@ip.host.com. This can be modified by changing the "2" to whatever suits you. A full list of masks is available in the mIRC help file.

The first window that we will use will be a a hidden, sorted listbox. We will use this to store the addresses and nicknames of the users in the channel in the format of:

<address><tab character><nicknames separated by spaces>

...where each address will represent one line. This window will not be a tabbed listbox, but just a standard one. The tab character will come into play when we output the addresses into the second window, which will be a tabbed listbox. This is solely personal preference and is not required. However, the tab character makes a good token separator between the nicknames and the addresses.

NOTE: You can use variables to store nicknames too, but then you would want to clean them up, etc.. again, it is personal preference. You can possibly avoid the "/set: line too long" error, however, by using @windows.

The first thing we need to do is setup our variables and create our hidden window:
window -hsl @c.s.a
var %i = 1
var %num = $nick(#, 0)
var %address, %nick, %tmp
var %s = $ticks
We have created the hidden window and called it @c.s.a, initialized our loop control variable %i, found the number of nicknames in the channel with %num. I have also declared %address, %nick, and %tmp which will be used later. The %s variable is optional, and will be used in timing the clonescan, since scanning large channels can take a bit.

The way we'll be checking for clones is adding lines to the @c.s.a window, but first checking to see if the line already exists. If it does, that means we have found a clone. To do this, we need to iterate through the addresses with a while loop. This is easily accomplished with the following code:
while (%i <= %num) {
  %nick = $nick(#, %i)
  %address = $address(%nick, 2)
  %tmp = %address $+ $chr(9) $+ *
  if ($fline(@c.s.a, %tmp, 1)) rline @c.s.a $ifmatch $line(@c.s.a, $ifmatch) %nick
  else aline @c.s.a %address $+ $chr(9) $+ %nick
  inc %i
}
The while (%i <= %num) makes sure the while loop runs through each nick. We set %nick to the current nickname, then we set %address to the current address of the nickname. Now, we set %tmp to <address><tab char>*. That will be used in our $fline() statement. $fline means "find line", and we will use it to search the @c.s.a window for the address. If we find the address, that means we have already encountered this address, and therefore, we have a clone. If we have found a clone, we use /rline to replace that line, and the new line will simply add the current nickname to the end, so now we have a line that is:

<address><tab char><nick1 nick2>

If we weren't able to find the line, then we add a new line, which is:

<address><tab char><nick1>

Then we inc %i and go on to the next nickname. Of course, if there are more than 2 clones, it will keep adding, nick1, nick2, nick3, etc..

Now that we have run through all the addresses, we have a window filled, and each line represents a unique address followed by a tab char, followed by all of the nicknames which share the address. Now all we have to do is create our output window and run through the lines, finding the ones with more than one nickname per address. Luckily, we used a tab char to separate nicknames and addresses, so we can simply add the entire line to the output window to achieve a nice look. This is done with a tabbed listbox, so everything on the left hand side of the tab character will be in the first column and everything on the right hand side of the tab character will be in the second column.
window -al -t20 @CloneScan 50 50 600 300 Arial -8
aline @CloneScan Address $+ $chr(9) $+ Nicknames
%i = 1
var %nicks
while ($line(@c.s.a, %i)) {
  %tmp = $ifmatch
  %nicks = $gettok(%tmp, 2, 9)
  if ($numtok(%nicks, 32) > 1) aline @CloneScan %tmp
  inc %i
}
aline @CloneScan Elapsed time: $calc($ticks - %s) $+ ms
window -c @c.s.a
We create the output window @CloneScan. Notice the the second parameter, "-t20". That means make a second column after 20 spaces. The spaces depend on the size and type of font, so if you choose a different font, you may have to experiment with the number to get the right output. So now we have our two-column window in which to output the clones. We now need to run through the addresses in the @c.s.a window and find out which have multiple nicks for a single address.

We set %i to 1 again. The next line, while ($line(@c.s.a, %i)) basically means "while the line is not null", so whenever %i is increased to one more than the number of lines, that statement will return $null and the while loop will end. Inside the while loop we do %tmp = $ifmatch. This sets %tmp to the value of the current line. Then we do %nicks = $gettok(%tmp, 2, 9), which grabs the second part of the line, which is equal to the nicknames for the address. We check to see how many nicknames, using $numtok, and if it is more than 1, then we add our result to the output window. We then increase %i and go on to the next address stored in the @c.s.a. We finish it by calculating the elapsed time and closing the hidden window, since it is no longer needed.
Extra Tips
We used $chr(9) or referenced 9 several times, that is because 9 is the ordinal value of the tab character. The tab character played an important role in this clone scanner, because it provided a unique, convenient token separator at the beginning and then allowed easy formatting at the end.

As said earlier, this is not the fastest way to make a clone scanner. One thing that could improve this one is making it so the clones are added to the output window as they are found rather than making it run through the list again.
Source Code
This alias is called by "/scan-lesson". I have added a check at the beginning, to make sure the IAL is enabled and updated. You can enable it by going to the remote section (ALT+R) and clicking Options -> Internal Address List. You can update your IAL by doing a /who on the channel you to update, for example, "/who #channel".
scan-lesson {
  if ($chan(#).ial == $false) {
    .ial on
    echo -a You must have your IAL updated for this to work
    echo -a Type '12 $+ /who # $+ ' and try again
    return
  }
  window -hsl @c.s.a
  var %i = 1
  var %num = $nick(#, 0)
  var %address, %nick, %tmp
  var %s = $ticks
  while (%i <= %num) {
    %nick = $nick(#, %i)
    %address = $address(%nick, 2)
    %tmp = %address $+ $chr(9) $+ *
    if ($fline(@c.s.a, %tmp, 1)) rline @c.s.a $ifmatch $line(@c.s.a, $ifmatch) %nick
    else aline @c.s.a %address $+ $chr(9) $+ %nick
    inc %i
  }
  window -al -t20 @CloneScan 50 50 600 300 Arial -8
  aline @CloneScan Address $+ $chr(9) $+ Nicknames
  %i = 1
  var %nicks
  while ($line(@c.s.a, %i)) {
    %tmp = $ifmatch
    %nicks = $gettok(%tmp, 2, 9)
    if ($numtok(%nicks, 32) > 1) aline @CloneScan %tmp
    inc %i
  }
  aline @CloneScan Elapsed time: $calc($ticks - %s) $+ ms
  window -c @c.s.a
}
All content is copyright by mircscripts.org and cannot be used without permission. For more details, click here.