Personal tools
From wiki.swiftlytilting.com
Jump to: navigation, search

User:M3nt0r/Simple IRC Client

Contents

Description

I wrote this WinBinder Application because of this thread:
http://www.winbinder.com/forum/viewtopic.php?t=293

r0swell asked if it would be possible to run applications which have an infinite loop for projects like an IRC-Client. I gave him a quick answer, but to be honest: without knowing if it was really all that simple.

I had to find out so here you go.


Requirements

  1. Winbinder Version 0.43 (alpha) - build 164
  2. PHP 5.0.5 with Sockets Extension


Sockets Extension

You need the Sockets Extension to use the real Sockets which PHP can provide. They are far better. The WinBinder Installation package i downloaded contained PHP 5.0.5. You have to download the Win32 Binaries from php.net with the same Version Number.


Install Extension

Go to the "ext" folder of your php zip-file and find the "php_sockets.dll". Put it into your WinBinder installation folder and add an "extension" line to your php.ini.

; PHP extensions

extension_dir = "ext/"			; Directory in which the loadable extensions (modules) reside.
extension=php_winbinder.dll
extension=php_sockets.dll		; PHP_SOCKETS.DLL


Download Extension

Binary Package 5.0.5 from php.net
http://www.php.net/get/php-5.0.5-Win32.zip/from/a/mirror

Note: check you current PHP version. If it's different then 5.0.5 you have to adjust the version numbers within the download URL.

\binaries\php5\php.exe -version


References

Link to the PHP Sockets Refrence
http://de.php.net/manual/de/ref.sockets.php

Link to the IRC RFC.
http://www.irchelp.org/irchelp/rfc/rfc.html


The Sourcecode


 <?php
 
########################################################################
 #    Simple IRC Client with real Sockets
 #    by Kjell Bublitz ( www.m3nt0r.de )
 #    written: 18.03.2006
 ########################################################################
 
error_reporting(E_ALL E_NOTICE);
 
 
// Winbinder
 //--------------------------------------------------------------------   
 
     
define("PATH_INC",  "../include/"); 
     include 
PATH_INC "winbinder.php";
 
 
//--------- CONSTANTS
 
     
define("APPNAME",            "Simple IRC Client");
     
     
define("ID_TIMER",        100);
     
     
define("ID_CHAT",        101);
     
define("ID_CHATWIN",        102);
     
define("ID_CHATTXT",        106);
     
     
define("ID_SERVER",        103);
     
define("ID_CONNECT",        104);
     
define("ID_CHANNEL",        105);
     
define("ID_JOIN",        107);
     
define("ID_STATUS",        108);
     
define("ID_QUIT",        109);    
 
 
//-------- DEFAULT VARS
 
     
$connected false;    // general status check
     
$joined false;    // i just wanted to avoid any output until user is in a channel.
     
     
$_socket NULL;     // just a placeholder
     
$server NULL;     // just a placeholder
     
     
$nickname "Testing1";    // you might want to make editboxes out of this.
     
$username "test";
     
$realname "test";
     
$usermode 0;        // = 8 means invisible. read RFC..
 
 //-------- WINDOW LAYOUT
 
     
$mainwin wb_create_window(NULLAppWindowAPPNAMEWBC_CENTERWBC_CENTER620440WBC_TOP);
     
wb_create_control($mainwinStatusBarAPPNAMEnull,null,null,nullID_STATUS);
     
     
// Options-------------------------------
     
wb_create_control($mainwinFrame,     "IRC Options",     5559045,     0);
     
wb_create_control($mainwinEditBox,    "irc.freenode.de:6667"102012020ID_SERVER);
     
wb_create_control($mainwinPushButton"Connect",     140209020,     ID_CONNECT); 
      
     
wb_create_control($mainwinEditBox,     "#test",     2502012020,     ID_CHANNEL); 
     
wb_create_control($mainwinPushButton"Join",     380209020,     ID_JOIN); 
     
     
wb_create_control($mainwinPushButton"Quit",     490209020,     ID_QUIT);
     
     
// Chat----------------------------------
     
wb_create_control($mainwinEditBox,     "",        555490290,     ID_CHATWINWBC_MULTILINE |  WBC_READONLY);
     
wb_create_control($mainwinEditBox,     "",         535039020,     ID_CHATTXT); 
     
wb_create_control($mainwinPushButton"Say it",     4003509020,     ID_CHAT); 
     
     
// Run-----------------------------------
     
wb_create_timer($mainwinID_TIMER500);
     
wb_set_handler($mainwin"process_main");
     
wb_main_loop();  
 
 
 
//--------------------------------------------------------------------
 // PROCESS HANDLER: process_main
 //--------------------------------------------------------------------
 
     
function process_main($window$id$ctrl
     {
         global 
$_socket$connected$server$joined;
         global 
$nickname$username$realname$usermode;
         
         switch(
$id
         {
             case 
ID_TIMER:            
                 if(
$connected == true
                 {
                         
$sread = array($_socket);
                         
$result = @socket_select($sread$w null$e null02000);
                         
                         
wb_set_text(wb_get_control($window,ID_STATUS),  APPNAME." - Connected to ".$server."!");
                         
                         
// If new Data
                         
if ($result == 1)
                         {        
                             
// Read Old Window and New String from Socket
                     
$old_text wb_get_text(wb_get_control($window,ID_CHATWIN));
                     
$new_text socket_read($_socket10240);
                     
                     
// JOIN
                     
if(preg_match('/join/i',$new_text)) 
                      {
                         
$new_text convert_joinmsg($new_text);
                         
$joined true;
                     }
                         
                     if(
$joined != false// do nothing until we joined.
                     
{                        
                         
// PRIVMSG        
                         
if(preg_match('/privmsg/i',$new_text)) 
                         {
                             
$new_text convert_privmsg($new_text$channel);
                         }
     
                         
// MODE
                         
if(preg_match('/mode/i',$new_text)) 
                         {
                             
$new_text convert_modemsg($new_text);    
                         }
         
                         
// Combine Text and Output
                         
$text $new_text.$old_text;
                         
wb_set_text(wb_get_control($window,ID_CHATWIN), $text);
                     }
                     }
                 } else {
                     
wb_set_text(wb_get_control($window,ID_STATUS), APPNAME." - Not connected...");
                 }
             break;
             
             case 
ID_CONNECT:
                 
$server wb_get_text(wb_get_control($window,ID_SERVER));
                 
$serv_port explode(":",$server);
             
                 
wb_set_text(wb_get_control($window,ID_STATUS),  APPNAME." - Connecting to ".$server." ...");
                 
                     
$_socket socket_create(AF_INETSOCK_STREAMSOL_TCP);
                        
$result = @socket_connect($_socket$serv_port[0], $serv_port[1]);
                                    
                     if(
$result === false// couldn't connect
                     
{
                         
$connected false;
                     
wb_set_text($statusbarsocket_strerror(socket_last_error($_socket)));
                 } 
                 else 
// connected
                 
{
                     
$connected true;
                                     
                     
// login user
                     
send($_socket"NICK ".$nickname);
                     
send($_socket"USER ".$username." ".$username." ".$usermode." :".$realname);                 
                 }            
             break;
             
             case 
ID_JOIN:
                 
$channel wb_get_text(wb_get_control($window,ID_CHANNEL));
                 if(!empty(
$channel))
                 {                        
                     
send($_socket"JOIN ".$channel);
                 }
             break;
     
             case 
ID_CHAT:
                 
$channel wb_get_text(wb_get_control($window,ID_CHANNEL));
                 
$text wb_get_text(wb_get_control($window,ID_CHATTXT));
                 if(!empty(
$channel) && !empty($text))
                 {            
                     
send($_socket"PRIVMSG ".$channel." :".$text);
                     
                     
// write own chat to window.
                     
$old_text wb_get_text(wb_get_control($window,ID_CHATWIN));
                     
$new_text "<".$nickname."> ".$text."\n";
                     
wb_set_text(wb_get_control($window,ID_CHATWIN), $new_text.$old_text);                
                 }
             break;
              
             case 
ID_QUIT:
                 
$connected false;
                 @
send($_socket"QUIT");
                         @
socket_shutdown($_socket);
                         @
socket_close($_socket);
             break;
             
             case 
IDCLOSE:
                 @
send($_socket"QUIT");
                         @
socket_shutdown($_socket);
                         @
socket_close($_socket);
                 
wb_destroy_window($window);
             break;
         }
     }
     
     
 
// -------------- CUSTOM STUFF --------------
     
     
function send($_socket$msg
     {
         
$msgbuffer $msg."\n";
         
$bufferlen strlen($msgbuffer);
         @
socket_write($_socket$msgbuffer$bufferlen);
         return;
     }
     
     function 
convert_privmsg($string$channel
     {
         
$server_msg1 explode($channel." :"$string);
         
$server_msg2 explode("!"$server_msg1[0]);
         
$chat_nick substr($server_msg2[0], 1);
         
$chat_msg $server_msg1[1];
         
$return "<".$chat_nick."> ".$chat_msg;
     
         return 
$return;
     }
     
     function 
convert_joinmsg($string
     {
         
$server_msg1 explode("JOIN :"$string);
         
$server_msg2 explode(" "$server_msg1[1]);
         
$server_msg3 explode(":"$server_msg2[0]);
         
         
$return "**** Now talking in ".str_replace("\n","",$server_msg3[0])." ****\n\n\n\n";
         
         return 
$return;
     }
     
     function 
convert_modemsg($string)
     {
         
$server_msg1 explode(" ",$string);
         
$server_msg2 explode("!"$server_msg1[0]);
         
$chat_nick substr($server_msg2[0], 1);
         
         
$return "** User ".$chat_nick." sets mode '".$server_msg1[3]."' ".$server_msg1[4]." in ".$server_msg1[2]." **\n";
         
         return 
$return;
     }
 
?>


Functions

The custom functions are just simple helpers.


send()

With this function you can write IRC commands (according to RFC) to the current socket.
Use this functions for any client-server communication like MODE, WHOIS, NOTICE, LIST, etc..

send (resource socket, string message)
  • resource socket - the socket variable
  • string message - everything you want to send.

This function returns: nothing


convert_privmsg()

The convert functions are pretty dirty but working. ;)
Note: This function needs the channel to be given for fetching the correct line. If you translate the script to work with multiple channels you need to work this function over maybe.

convert_privmsg (string text, string channel)
  • string text - the matching text from socket
  • string channel - the name of the channel

This function returns: formatted text


convert_joinmsg()

Beautifies the JOIN #channel message sent by the server.

convert_joinmsg (string text)
  • string text - the matching text from socket

This function returns: formatted text


convert_modemsg()

Beautifies the MODE messages sent by the server.
Note: the MOTD (message of the day) contains MODE alot! Needs a fix.

convert_modemsg (string text)
  • string text - the matching text from socket

This function returns: formatted text

Winbinder Projects