IRC include + example

Share your advanced PureBasic knowledge/code with the community.
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

IRC include + example

Post by dracflamloc »

Heres the include:

Code: Select all

;DracIRC
;Copyright 2006 DracSoft
;If you use this file in a project it would be appreciated if you 
;send me a friendly e-mail or perhaps paypal donate to: cyberneticwraith@phreaker.net
;Do not change this header!
;
;   Licensed under the LGPL (www.gnu.org) with an exception: May be statically linked and 
;   included into a program, code must maintain the above header. Be sure to release any
;   optimizations to the language ASAP!
;
;   Only this file or files it includes must have code released under LGPL,
;   so this CAN be used in commercial projects!

Global MaxIRCBuffer.l
Global CurrentIRCMessage.l

Procedure SendIRCCommand(cid,msg.s)
  SendNetworkString(cid,msg+Chr(13)+Chr(10))
EndProcedure  

Procedure SendIRCMessage(cid,target.s,msg.s)
  SendIRCCommand(cid,"PRIVMSG "+target+" "+msg)
EndProcedure  

Procedure JoinIRCChannel(cid,channel.s)
  SendIRCCommand(cid,"JOIN "+channel)
EndProcedure

Declare ReceiveIRCThread(cid.l)
Procedure.l ConnectToIRC(server.s,port.l,nickname.s,maxbuffer.l)
  cid=OpenNetworkConnection(server,port)
  If cid>0
    Global Dim IRCBuffer.s(maxbuffer)
    MaxIRCBuffer=maxbuffer
    SendIRCCommand(cid,"USER "+nickname+" 0 * :"+nickname)
    SendIRCCommand(cid,"NICK "+nickname)
    CreateThread(@ReceiveIRCThread(),cid)
    ProcedureReturn cid
  Else
    ProcedureReturn 0
  EndIf 
EndProcedure

Procedure.s ParseIRCCommand(msg.s)
  If Left(msg,1)=":"
    ProcedureReturn StringField(msg,2," ")
  Else
    ProcedureReturn StringField(msg,1," ")
  EndIf    
EndProcedure

Procedure.s ParseIRCParameter(msg.s,index.l)
  If Left(msg,1)=":"
    index+2
  Else
    index+1
  EndIf  
  
  param.s=StringField(msg,index," ")
  If Left(param,1)=":"
    pos=FindString(msg," :",1) 
    param = Right(msg,Len(msg)-pos-1)
  EndIf 
  
  ProcedureReturn param.s
EndProcedure

Procedure.s ParseIRCPrefix(msg.s)
  If Left(msg,1)=":"
    ProcedureReturn StringField(msg,1," ")
  Else
    ProcedureReturn ""
  EndIf    
EndProcedure

Procedure ReceiveIRCThread(cid.l)
  *buf=AllocateMemory(1024)
  str.s=""
  Repeat 
  
    If NetworkClientEvent(cid)=#PB_NetworkEvent_Data
      
      Repeat 
        amt=ReceiveNetworkData(cid,*buf,1024)
        str = str + PeekS(*buf,amt)
      Until amt<1024    
      
      str=ReplaceString(str,Chr(13),"")
      c=CountString(str,Chr(10))
      
      For i = 1 To c
        tmp.s=StringField(str,i,Chr(10))
        ;ping check
        If ParseIRCCommand(tmp)="PING"
          SendIRCCommand(cid,ReplaceString(tmp,"PING ","PONG "))
        EndIf         
        
        If Trim(tmp)<>""
          
          For j=CurrentIRCMessage To MaxIRCBuffer-1
            If ircbuffer(j)=""
              ircbuffer(j)=tmp
              Break 
            EndIf 
          Next 
          
        EndIf 
      Next 
      
      str = StringField(str,c+1,Chr(10))
      
    EndIf 
    
    Delay(1)
  ForEver 
  
  FreeMemory(*buf)
EndProcedure

Procedure.s NextIRCMessage()
  If CurrentIRCMessage>=MaxIRCBuffer
    For i = 0 To MaxIRCBuffer-1
      IRCBuffer(i)=""
    Next 
    CurrentIRCMessage=0
    ProcedureReturn ""
  Else
    mesg.s=IRCBuffer(CurrentIRCMessage)
    IRCBuffer(CurrentIRCMessage)=""
    If mesg=""
      CurrentIRCMessage=0
    Else
      CurrentIRCMessage + 1
    EndIf 
    
    ProcedureReturn mesg
  EndIf 
EndProcedure
Heres a little test app:

Code: Select all

;DracIRCTester
;Copyright 2006 DracSoft
;If you use this file in a project it would be appreciated if you 
;send me a friendly e-mail or perhaps paypal donate to: cyberneticwraith@phreaker.net
;Do not change this header!
;
;   Licensed under the LGPL (www.gnu.org) with an exception: May be statically linked and 
;   included into a program, code must maintain the above header. Be sure to release any
;   optimizations to the language ASAP!
;
;   Only this file or files it includes must have code released under LGPL,
;   so this CAN be used in commercial projects!


#VERSION="1.2.2"
InitNetwork()

Structure IRCLINE
  channel.s
  message.s
EndStructure


Global NewList ChatLog.IRCLINE()


IncludeFile "DracIRC.pb"
;IncludeFile "./dracscript.pb"

Global currChan.s
Global server.s=ProgramParameter()
Global port.l=Val(ProgramParameter())
Global nick.s=ProgramParameter()
Global channels.s=ProgramParameter()
Global bufferwidth.l=Val(ProgramParameter())
If bufferwidth=0
  bufferwidth=80
EndIf 

Procedure PrintStringN(st.s)
  CompilerIf #PB_Compiler_OS=#PB_OS_Windows
    If bufferwidth<>-1
      While st<>""
        PrintN(Left(st,bufferwidth))
        st=Right(st,Len(st)-bufferwidth)
      Wend 
    Else
      PrintN(st)
    EndIf 
  CompilerElse
    PrintN(st)
  CompilerEndIf
EndProcedure

Procedure PrintMessage(msg.s)
  tmpn.s=Right(ParseIRCPrefix(msg),Len(ParseIRCPrefix(msg))-1)
  tmpn.s=StringField(tmpn,1,"!")
  PrintStringN("*** "+ParseIRCParameter(msg,1) + " | <"+tmpn+"> "+ParseIRCParameter(msg,2))
EndProcedure  

Procedure PrintJoin(msg.s)
  tmpn.s=Right(ParseIRCPrefix(msg),Len(ParseIRCPrefix(msg))-1)
  tmpn.s=StringField(tmpn,1,"!")
  PrintN(msg) 
  PrintStringN("*** "+ParseIRCParameter(msg,1) + " | "+tmpn+" has joined the channel.")
EndProcedure

Procedure PrintMsg(msg.s)
  Select ParseIRCCommand(msg)
  
    Case "PRIVMSG"
      CompilerIf #PB_Compiler_OS=#PB_OS_Windows
        If bufferwidth<>-1
          ConsoleColor(10, 0)
        EndIf 
      CompilerEndIf            
                  
      If Left(ParseIRCParameter(msg,1),1)<>"#" Or ParseIRCParameter(msg,1)=currChan Or currChan=""
        PrintMessage(msg)
      Else 
        AddElement(chatlog())
        chatlog()\channel=ParseIRCParameter(msg,1)
        chatlog()\message=msg
        CompilerIf #PB_Compiler_OS=#PB_OS_Windows
          If bufferwidth<>-1
            ConsoleColor(1, 0)
          EndIf 
        CompilerEndIf
        PrintN("New message(s) in "+chatlog()\channel)
      EndIf 
      
      CompilerIf #PB_Compiler_OS=#PB_OS_Windows
        If bufferwidth<>-1
          ConsoleColor(7, 0)
        EndIf 
      CompilerEndIf
    
    Case "JOIN"
      CompilerIf #PB_Compiler_OS=#PB_OS_Windows
        If bufferwidth<>-1
          ConsoleColor(4, 0)
        EndIf 
      CompilerEndIf    
                  
      If Left(ParseIRCParameter(msg,1),1)<>"#" Or ParseIRCParameter(msg,1)=currChan Or currChan=""
        PrintJoin(msg)
      Else 
        AddElement(chatlog())
        chatlog()\channel=ParseIRCParameter(msg,1)
        chatlog()\message=msg
      EndIf 
      
      CompilerIf #PB_Compiler_OS=#PB_OS_Windows
        If bufferwidth<>-1
          ConsoleColor(7, 0)
        EndIf 
      CompilerEndIf
                
    Default 
      PrintStringN(msg)    
      
  EndSelect        
EndProcedure

Procedure DumpChannel(chan.s)
  ForEach ChatLog()
    If chatlog()\channel=Chan Or chan=""
      PrintMsg(chatlog()\message)
    EndIf 
  Next 
  
  ForEach ChatLog()
    If chatlog()\channel=Chan Or chan="" 
      DeleteElement(chatlog())
    EndIf 
  Next 
EndProcedure

;--------------------------------------
If server=""
  ReadFile(0,"./dracirc.ini")
  If IsFile(0)
    server=ReadString(0)
    port=Val(ReadString(0))
    nick=ReadString(0)
    channels=ReadString(0)
    bufferwidth=Val(ReadString(0))
    If bufferwidth=0
      bufferwidth=80
    EndIf
    CloseFile(0)
  EndIf 
EndIf 

con=ConnectToIrc(server,port,nick,1024)
OpenConsole()
PrintN("DracIRC "+#VERSION+" - "+server+" - "+nick)

CompilerIf #PB_Compiler_OS=#PB_OS_Windows
  ConsoleTitle("DracIRC "+#VERSION+" - "+server+" - "+nick)
  If bufferwidth<>-1
    EnableGraphicalConsole(1)
  EndIf 
CompilerEndIf

If con>0
    
  SendIRCCommand(con,"JOIN "+channels) 
  currChan=StringField(channels,1,",") 
  
  Repeat 
    Repeat
      msg.s=NextIRCMessage()
      
      If msg<>""
        PrintMsg(msg)
      EndIf 
      
    Until msg=""
    
    k.s=Inkey()
    If k<>""
      
      Select k
      
        Case Chr(9) ;tab
          c=CountList(ChatLog())
          If c>0
            SelectElement(chatlog(),c-1)
            PrintN("Auto switched to channel "+chatlog()\channel)
            currChan=chatlog()\channel
            DumpChannel(currChan)
          Else 
            PrintN("Auto switch: No new messages have been received in another channel.")
          EndIf 
        
        Case "#"
          Print("Switch Channel - Enter channel: #")
          CompilerIf #PB_Compiler_OS=#PB_OS_Windows
            If bufferwidth<>-1
              EnableGraphicalConsole(0)
            EndIf 
          CompilerEndIf              
          currChan="#"+Input()          
          CompilerIf #PB_Compiler_OS=#PB_OS_Windows
            If bufferwidth<>-1
              EnableGraphicalConsole(1)
            EndIf 
          CompilerEndIf    
          
          If currchan="#"
            currchan=""
          EndIf 
          DumpChannel(currChan)
          
        Case " "
          Print("Raw Input: ")
          CompilerIf #PB_Compiler_OS=#PB_OS_Windows
            If bufferwidth<>-1
              EnableGraphicalConsole(0)
            EndIf 
          CompilerEndIf    
          si.s=Input()
          CompilerIf #PB_Compiler_OS=#PB_OS_Windows
            If bufferwidth<>-1
              EnableGraphicalConsole(1)
            EndIf 
          CompilerEndIf    
          ;If si<>""
            SendIRCCommand(con,si) 
          ;Else 
          ;  PrintN("Send cancelled.")
          ;EndIf 
          
        Default 
          CompilerIf #PB_Compiler_OS=#PB_OS_Windows
            If bufferwidth<>-1
              ConsoleColor(10, 0)
            EndIf 
          CompilerEndIf       
          Print("PRIVMSG "+currChan+" :"+k)
          CompilerIf #PB_Compiler_OS=#PB_OS_Windows
            If bufferwidth<>-1
              EnableGraphicalConsole(0)
            EndIf 
          CompilerEndIf    
          si.s=Input()
          CompilerIf #PB_Compiler_OS=#PB_OS_Windows
            If bufferwidth<>-1
              EnableGraphicalConsole(1)
            EndIf 
          CompilerEndIf    
          ;If si<>""
            SendIRCCommand(con,"PRIVMSG "+currChan+" :"+k+si) 
          ;Else 
          ;  PrintN("Send cancelled.")
          ;EndIf 
          CompilerIf #PB_Compiler_OS=#PB_OS_Windows
            If bufferwidth<>-1
              ConsoleColor(7, 0)
            EndIf 
          CompilerEndIf       
          
      EndSelect
      
    EndIf 
    
    Delay(1)
  ForEver   
    
EndIf 

I will probably use this to create an scriptable IRC-based adventure game bot or something along those lines. If anyone is interested in helping let me know. It will be completely open source if i do it.
Last edited by dracflamloc on Wed Oct 18, 2006 2:22 pm, edited 5 times in total.
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post by dracflamloc »

dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post by dracflamloc »

updated a little. fixed the input trucation with graphical console
Intrigued
Enthusiast
Enthusiast
Posts: 501
Joined: Thu Jun 02, 2005 3:55 am
Location: U.S.A.

Post by Intrigued »

I'm concerned about sercurity and using IRC. How does your applicaiton, source stack up against other offerings out there. Is it fairly safe to use or can some "zombie" the system using this, or?

TIA
Intrigued - Registered PureBasic, lifetime updates user
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post by dracflamloc »

Well what do you mean by security?

This framework is only for the most basic of IRC functionality, which is chatting. It doesn't handle CTCP requests at all unless you do it in the tester. Its just a framework for receiving the messages the server sends out. Can't get much more secure than it is!

I guess if a irc server screwed up and relayed a huge message you could theoretically overflow the client. But it'd just crash out. IRC messages are limited to 512 characters in length, so i doubt that'd happen.

Security issues with IRC tend to be inherent more in the scripting languages that get integrated into the clients and with the way they handle binary file transfers. I leave that to you =)
Intrigued
Enthusiast
Enthusiast
Posts: 501
Joined: Thu Jun 02, 2005 3:55 am
Location: U.S.A.

Post by Intrigued »

dracflamloc wrote:Well what do you mean by security?

This framework is only for the most basic of IRC functionality, which is chatting. It doesn't handle CTCP requests at all unless you do it in the tester. Its just a framework for receiving the messages the server sends out. Can't get much more secure than it is!

I guess if a irc server screwed up and relayed a huge message you could theoretically overflow the client. But it'd just crash out. IRC messages are limited to 512 characters in length, so i doubt that'd happen.

Security issues with IRC tend to be inherent more in the scripting languages that get integrated into the clients and with the way they handle binary file transfers. I leave that to you =)
Thanks for the walkthru. I had remember reading several articles once upon a time a few years ago about IRC and the purposed security issues surrounding it (or it may have been particular clients, as you have seemingly eluded too).

Thanks again for the explanation.
Intrigued - Registered PureBasic, lifetime updates user
Post Reply