mIRC Scripting
mIRC: Sockets
Contents
A socket, in networking terms, is simply a combination of an IP address and a port number. For our purposes we can go with a one end-point of a two-way communication link between two processes running on the network.
An IP address is the numerical identification that is assigned to devices that utilize the Internet Protocol. A port number is a process-specific identifier that serves an end point.
For example, look at the following socket: 74.125.91.104:80. The first part is the IP address (in this example we used www.google.com). The number that follows the colon (:) is the port number. In this case it's port number 80, which happens to be the default HTTP port.
Ports:
A port number is a 16-bit unsigned integer, thus ranging from 0 to 65535. (216-1), giving you a total of 65,536 ports. Ports 1-1023 are called well known ports, ports 1024-49151 are registered ports, and ports in the rage of 49152–65535 are dynamic and/or private they cannot be registered.
Be careful not to be confused between the client and server ports. The server port is the port in which the client (you) will attempt to establish a connection; the server listens to incoming connection on this port. The client port is the port at the client’s end, which are an incremental number and a much higher port number.
Here are a few commonly used ports:
| FTP data/command | 20/21 |
| TELNET | 23 |
| HTTP | 80 |
| SMTP | 25 |
| POP3 (email) | 110 |
| Authentication Service (like IRC Idents) | 113 |
| HTTP over TLS/SSL (HTTPS) | 443 |
| IRC | 6665-6669 |
mIRC Sockets:
mIRC gives you the ability to create a raw socket connections with an end point. This gives you the ability to do anything from getting information from a website (like the weather or games stats) to uploading or downloading files and posting on a forum.
mIRC lets you create two types of sockets: TCP and UDP. Both are core members of the Internet Protocol Suite (TCP/IP).
Here are a few basic points regarding TCP and UDP:
Transmission Control Protocol (TCP):
- Connection-Oriented Protocols (Virtual Circuit Approach)
- Reliable - guarantees data will be delivered in the same order as transmitted
- Used when reliable transport required and speed is secondary
User Datagram Protocol (UDP):
- Connectionless Service
- No logical connection established between End Systems
- Unreliable - "best effort" delivery
- Used when speed is required and guaranteed delivery is secondary
mIRC TCP Sockets:
TCP is by large the major core member of the Internet Protocol Suite.
Creating A Connection
Since we are using the TCP protocol, we must first establish a connection with the server before any data can be transmitted.
The basic syntax for opening a TCP socket is:
;-d tells mIRC that the ip you specified is a bind address
; -e creates an SSL connection. (we will talk about this later)
;For simplicity sake we will go with the more basic syntax:
/sockopen <name> <address> <port>
For the purpose of this tutorial, we will create 3 different sockets to the following locations: Our own demo page, Wikipedia, and YouTube.
In example 3 I introduced another command. The /sockMark command. I suggest you take a note to its existence.
| Example 1: Demo Page | Examples 2: Wikipedia | Examples 3: YouTube |
Demo Page Since we want to socket to our silly demo page, http://www.zigwap.com/mirc/socket-demo.php, our sockopen command will look something like this:
Alias Demo {
sockOpen demo www.zigwap.com 80 } Creating a socket connection by the name "demo" As a precaution, in order to not attempt to open an already opened socket, we will close it. If the socket is not open, mIRC will do nothing. Later on in the article I will explain how to dynamically name sockets which will give you the ability create as many sockets as you want.
Alias Demo {
sockClose demo sockOpen demo www.zigwap.com 80 }
|
||
Sending Request
Once connection has been made the on SockOpen event will get triggered. This is where all our requests for pages or files go. The information we send is known as the request header.
There are two ways of sending data to the server: POST and GET. When requesting a normal page, you will most likely be using the GET method, when submitting a form, it depends. When dealing with forms, by simply looking at the source code you can tell if it’s a POST or a GET method:
The most basic GET request will follow this basic syntax:
Host: www.example.com
<BLANK LINE>
Let’s take a look at the header a little closer:
This line is made up of three parts: method, path and version. The "GET", which SHOULD be always in uppercase letters, is the method. We will talk about the POST method later on. The next part is the path, relative to the root folder of the website. If our website is www.example.com/pub/foo/bar.html, our path would be /pub/foo/bar.html. Lastly, the final part of this line is the HTTP version, for all practical reasons, you will probably using version 1.1.
Next is the Host header
The Host header is required in HTTP version 1.1. Please note: it should be "Host:", not "host:" or "HOST:". If you forget to include this line, the server will send you an error 400 (Bad Request) status code.
The basic on sockopen event is as followed:
;Your header goes here
}
To send data to the server we use the /sockWrite command. The sockwrite command has the following syntax:
;-t switch force mIRC to treat text that looks like
&binary variables as plain text
;-n switch appends $crlf to the end if it’s not a binary
string or if it doesn’t have a $crlf at the end.
Let’s continue with our examples:
| Example 1: Demo Page | Examples 2: Wikipedia | Examples 3: YouTube |
Demo Page Remember that the page we want to socket to is http://www.zigwap.com/mirc/socket-demo.php. Our sockopen event will look something like this: (In this example I will be using version 1.0) on *:SockOpen:demo: {
sockwrite -nt demo GET /mirc/socket-demo.php HTTP/1.0 sockwrite -nt demo Host: www.zigwap.com sockwrite -nt demo $crlf } Until this point, our combined script should look something like this: Alias Demo {
sockClose demo sockOpen demo www.zigwap.com 80 } on *:SockOpen:demo: { sockwrite -nt demo GET /mirc/socket-demo.php HTTP/1.0 sockwrite -nt demo Host: www.zigwap.com sockwrite -nt demo $crlf }
|
||
Coding style:
I would like to point out a few more things before we continue. Coding style is a personal thing and different people code things differently. For example:
sockwrite -nt YouTube GET /watch?v= $+ $sock($sockName).mark HTTP/1.1
sockwrite -nt YouTube Host: www.youtube.com
sockwrite -nt YouTube $crlf
}
A lot of scripters would prefer to write it like this:
var %<< sockwrite -nt YouTube
%<< GET /watch?v= $+ $sock($sockName).mark HTTP/1.1
%<< Host: www.youtube.com
%<< $crlf
}
It’s up to you to decide which one you like most.
URL Encoding
Specified by the RFC 1738:
Usually a URL has the same interpretation when an octet is represented by a character and when it encoded. However, this is not true for reserved characters: encoding a character reserved for a particular scheme may change the semantics of a URL.
Thus, only alphanumerics, the special characters "$-_.+!*'(),", and reserved characters used for their reserved purposes may be used unencoded within a URL.
On the other hand, characters that are not required to be encoded (including alphanumerics) may be encoded within the scheme-specific part of a URL, as long as they are not being used for a reserved purpose.
We can go with this alias:
To decode:
When sending data in the header, ALL the value MUST be encoded. Their names should not. For example, if the URL is www.example.com/foo/bar.php?foo=<VALUE>
sockwrite -nt example GET /foo/bar.php?foo= $+ $urlEncode(<VALUE>) HTTP/1.1
sockwrite -nt example Host: www.example.com
sockwrite -nt example $crlf
}
Reading Incoming Data
Once the server receives your request, it will send the response back to you. This will trigger the on SockRead event. The basic syntax of the on sockread event is:
;Your code goes here
}
It is important to remember that each time the server replies with a line, the sockread event will trigger.
For debugging purposes I will echo all the information to a window (@ $+ $sockName). This makes it easier to find the section of html we want to retrieve and parse.
window -de @ $+ $sockName -1 -1 500 500
var %read
sockread %read
aline -p @ $+ $sockName : $+ %read
}
Let’s go back to our examples: (I would point out the User-Agent header in examples 2, Wikipedia.)
| Example 1: Demo Page | Examples 2: Wikipedia | Examples 3: YouTube |
Demo Page When I printed out the entire source the server sent us. The first part is the header, follows by a blank space, and follows by the actual page data. It should look something like this: :HTTP/1.1 200 OK
:Date: Thu, 16 Apr 2009 04:47:40 GMT :Server: Apache :X-Powered-By: PHP/4.4.9 :Connection: close :Content-Type: text/html : :<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> :<html xmlns="http://www.w3.org/1999/xhtml"> :<head> :<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> :<meta name="robots" content="noindex,follow" /> :<title>ZigWap - Demo Page</title> :</head> : <body> : <div align="center"> : <p>This is an example page!</p> : <p>This webpage is dedicated for the socket tutorial purpose. </p> : </div> : <p align="center">Your random color is: Blue</p> : </body> :</html> In this example we will be trying to retrieve the random color line. A simple if statement to check for *Your random colors is* should be sufficient enough. Alias Demo {
sockClose demo sockOpen demo www.zigwap.com 80 } on *:SockOpen:demo: { sockwrite -nt demo GET /mirc/socket-demo.php HTTP/1.0 sockwrite -nt demo Host: www.zigwap.com sockwrite -nt demo $crlf } on *:SockRead:demo: { var %read sockRead %read if (*Your random color is: * iswm %read) { tokenize 32 %read echo $color(info) -ae Random Color: $remove($6-,</p>) } } When we located the line we wanted, I tokenized it by spaces (char 32). The 6th token will be COLOR</p>. At this point I simply removed the "</p>" part. |
||
$noHTML Alias:
The noHTML alias is a very handy alias that strips html tags from a string:
For example:
Will output:
Error Handling
Errors can occur. It is your responsibility to check for them. The $sockerr identifier must be checked every on sockread event and after every /sockread command.
if ($sockerr) {
echo $color(info) -sef Socket Error: $sock($sockName).wsmsg
echo $color(info) -sef Socket Error Number: $sock($sockName).wserr Socket: $sockName
return
}
else {
;my code goes here...
}
}
Connection Terminated
It is possible for the remote end to terminate a connection, the same way you can /sockclose a connection early. When this happens the on sockClose event will trigger. The syntax is
;Your code goes here
}
The sockclose event will not trigger by you closing the connection, but ONLY by the remote end.
Secured Socket
I am sure you have visited websites with the padlock icon next to the URL in your browser. That icon indicated that website uses secure http (also known as HTTPS). The default port for HTTPS is 443.
SSL:
mIRC lets you create an SSL socket as well using the following syntax:
The on sockopen and on sockread events are exactly the same as the regular http.
TLS:
mIRC does not yet support TLS sockets natively.
Multi-Sockets
When you create a script for a channel, for example a !google script. Using the method above you will only be able to initiate one socket at a time. If you recall, we actually /sockclose the socket to make sure it’s closed. Muti-Sockets is a method that will lets you open as many sockets as needed, not limiting it for one person to use at a time.
The basic idea of muti-socket is that every time the script initiates a new socket, it uses a unique name. This is usually done by appending a random sequence of numbers/letters to the end of the socket name.
For example, instead of using:
sockClose google
sockOpen google www.google.com 80
sockMark google $EscapeURL($2-)
set %google.chan $chan
}
on *:SockRead:Google: {
...
The problem with the example above is that only one person is able to use this google script at a time. If a second person types !google while another google socket is open, this script will close the socket of the first person and only reply to the second person.
An easy way to fix something like this is to add 6 number to the end of the socket way. For example we can do Google.###### where ###### are the 6 random. In the example below we use $ticks, which will ensure these 6 numbers will not show up for quite a while.
var %sock google. $+ $right($ticks,6)
sockClose %sock
sockOpen %sock www.google.com 80
sockMark %sock $EscapeURL($2-)
set %google. $+ %sock $chan
}
on *:SockRead:Google.*: {
...
If you look closely at the sockread event, you will notice I have a google.* as the socket name, the * wildcard can be sued to represent "anything".
You now have to remember that because we are dealing with a dynamic socket name, all the variables will have to be dynamic as well. For example:
set %varName. $+ $sockname $noHTML(%x)
;to retrieve it
echo –s %varName. [ $+ [ $sockName ] ]
;or
echo -s $($+(%,varName,$sockname),2)
Making a dynamic variable called %varName.sockName.######
POST Method
PLease see the Advanced sockets tutorial.
mIRC UDP Sockets:
Please see the UDP socket tutorial.

