zackrspv Posted October 26, 2009 Share Posted October 26, 2009 (edited) Well, i found a wonderful COM object type system to allow quick access to jabber, and do what is necessary; wodXMPP from: http://www.weonlydo.com/index.asp?showform=XMPP There is a 30 day demo: http://www.weonlydo.com/Samples/wodXMPP.exe You will need to download/install that, so that you can help me, i hope, with my code here: expandcollapse popup#include <Inet.au3> #include<String.au3> $xmpp = ObjCreate("WeOnlyDo.wodXMPPCom.1") If IsObj($xmpp) Then ConsoleWrite("Object created" & @CRLF) $oMyError = ObjEvent("AutoIt.Error","MyErrFunc") ; Initialize a COM error handler Else ConsoleWrite("Object Failed" & @CRLF) Exit EndIf $gui = GUICreate("XMPP", 100, 100, -1, -1) GUISetState() $xmpp.Login = "testautoit@jabber.org/techchat" $xmpp.Password = "testing" $xmpp.Authentication = 0 $xmpp.Security = 2 $xmpp.Connect ConsoleWrite("Connecting to: " & $xmpp.Login & @CRLF) $tst = getStatus($xmpp.State) ConsoleWrite($tst & @CRLF) While $xmpp.State <> 5 $tst = getStatus($xmpp.State) ConsoleWrite(@HOUR & ":" & @MIN & ":" & @SEC & ": " & $tst & @CRLF) Sleep(100) WEnd $tst = getStatus($xmpp.State) ConsoleWrite($tst & @CRLF) If $tst <> "Connected!" Then MsgBox(0, "ERROR", "Not connected to server: " & getStatus($xmpp.State)) Exit EndIf $message = ObjCreate("WeOnlyDo.XMPPMessage") $message.Text = "This is a test" $xmpp.SendMessage("testautoit@jabber.org", $message) While 1 $nmsg = GUIGetMsg() Switch $nmsg Case - 3 Exit EndSwitch WEnd Func getStatus($code) Switch $xmpp.State Case 0 Return "Disconnected" Case 1 Return "Connecting" Case 2 Return "Registering user" Case 3 Return "Init Secure Connection" Case 4 Return "Sending Auth Data" Case 5 Return "Connected!" Case 6 Return "RX data" Case 7 Return "TX data" Case 8 Return "Execute Command" Case 9 Return "Disconnecting" Case 10 Return "Resolving" EndSwitch EndFunc ;==>getStatus Func MyErrFunc() Msgbox(0,"AutoItCOM Test","We intercepted a COM Error !" & @CRLF & @CRLF & _ "err.description is: " & @TAB & $oMyError.description & @CRLF & _ "err.windescription:" & @TAB & $oMyError.windescription & @CRLF & _ "err.number is: " & @TAB & hex($oMyError.number,8) & @CRLF & _ "err.lastdllerror is: " & @TAB & $oMyError.lastdllerror & @CRLF & _ "err.scriptline is: " & @TAB & $oMyError.scriptline & @CRLF & _ "err.source is: " & @TAB & $oMyError.source & @CRLF & _ "err.helpfile is: " & @TAB & $oMyError.helpfile & @CRLF & _ "err.helpcontext is: " & @TAB & $oMyError.helpcontext _ ) Local $err = $oMyError.number If $err = 0 Then $err = -1 $g_eventerror = $err ; to check for after this function returns Endfunc When looking at the SendMessage information in the wodXMPP help file, i get: Description Sends message to some JID. Return Type None Syntax object.SendMessage JID, Message The SendMessage Method syntax has these parts: Part Description object An expression evaluating to an object of type wodXMPP. JID Required. A String value. Determines which JID will message be sent to. Message Required. A XMPPMessage object. A reference to wodXMPPMessage object which will be sent. Remarks Sends message (through wodXMPPMessage object) to the user specified by JID parameter. Message parameter in this case isn't a String value containing the text you wish to send, but a reference to wodXMPPMessage object. If you wish wodXMPP to create wodXMPPMessage object automatically, you should use SendText method. But, whenever I call it that way, i get a type mismatch, I did try to look it up via the OLEview: void SendMessage( BSTR JID, IXMPPMessage* Message); Which to me, means u use the format: $xmpp.SendMessage("testautoit@jabber.org/techchat", $message) But that gives me a type mismatch error. This is rather frustrating, can someone help? Edited October 26, 2009 by zackrspv -_-------__--_-_-____---_-_--_-__-__-_ ^^€ñ†®øÞÿ ë×阮§ wï†høµ† ƒë@®, wï†høµ† †ïmë, @ñd wï†høµ† @ †ïmïdï†ÿ ƒø® !ïƒë. €×阮 ñø†, bµ† ïñ§†ë@d wï†hïñ, ñ@ÿ, †h®øµghøµ† †hë 맧ëñ§ë øƒ !ïƒë. Link to comment Share on other sites More sharing options...
zackrspv Posted October 28, 2009 Author Share Posted October 28, 2009 Getting closer, but not by much. I'm able to connect to the server, and actually listen for some events, but many of the events dont parse right. I could REALLLLY use some help with this :/ I need to be able to join chat rooms, send messages, *sighs* expandcollapse popup#include <Inet.au3> #include<String.au3> $xmpp = ObjCreate("WeOnlyDo.wodXMPP.1") If IsObj($xmpp) Then ConsoleWrite("Object created" & @CRLF) $SinkObject = ObjEvent($xmpp, "IwodXMPPNotify_") ; Assign events to UDFs starting with IEEvent_ $oMyError = ObjEvent("AutoIt.Error", "MyErrFunc") ; Initialize a COM error handler Else ConsoleWrite("Object Failed" & @CRLF) Exit EndIf $Form1 = GUICreate("Form1", 625, 445, 192, 124) GUISetState() $xmpp.Login = "testautoit@jabber.org/techchat" $xmpp.Password = "testing" $xmpp.Authentication = 0 $xmpp.Security = 2 $xmpp.Connect ConsoleWrite("Connecting to: " & $xmpp.Login & @CRLF) While $xmpp.State <> 5 Sleep(100) WEnd If $xmpp.State <> 5 Then MsgBox(0, "ERROR", "Not connected to server: " & getStatus($xmpp.State)) Exit EndIf $message = ObjCreate("WeOnlyDo.XMPPMessage") If Not IsObj($message) Then ConsoleWrite("Nope" & @CRLF) $message.Text = "This is a test: " $message.Type = 1 $xmpp.SendMessage("testautoit@jabber.org/techchat", $message) While 1 $nmsg = GUIGetMsg() Switch $nmsg Case - 3 Exit EndSwitch WEnd Func getStatus($code) Switch $xmpp.State Case 0 Return "Disconnected" Case 1 Return "Connecting" Case 2 Return "Registering user" Case 3 Return "Init Secure Connection" Case 4 Return "Sending Auth Data" Case 5 Return "Connected!" Case 6 Return "RX data" Case 7 Return "TX data" Case 8 Return "Execute Command" Case 9 Return "Disconnecting" Case 10 Return "Resolving" EndSwitch EndFunc ;==>getStatus Func IwodXMPPNotify_IncomingMessage($contact, $message) If IsObj($contact) Then ConsoleWrite("Contact object" & @CRLF) If IsObj($message) Then ConsoleWrite("Message object" & @CRLF) ConsoleWrite("------- MESSAGE ---------" & @CRLF) EndFunc ;==>IwodXMPPNotify_IncomingMessage Func IwodXMPPNotify_IncomingNotification() ConsoleWrite("------- notify ---------" & @CRLF) EndFunc ;==>IwodXMPPNotify_IncomingNotification Func IwodXMPPNotify_Pong() ConsoleWrite("------- Pong ---------" & @CRLF) EndFunc ;==>IwodXMPPNotify_Pong Func IwodXMPPNotify_StateChange() ConsoleWrite("[" & @HOUR & ":" & @MIN & ":" & @SEC & "] " & getStatus($xmpp.State) & @CRLF) EndFunc ;==>IwodXMPPNotify_StateChange Func IwodXMPPNotify_VCardDetails() ConsoleWrite("------- vcardDetails ---------" & @CRLF) EndFunc ;==>IwodXMPPNotify_VCardDetails Func IwodXMPPNotify_Connected() ConsoleWrite("------- IwodXMPPNotify_Connected ---------" & @CRLF) EndFunc ;==>IwodXMPPNotify_Connected Func IwodXMPPNotify_Disconnected() ConsoleWrite("------- IwodXMPPNotify_Disconnected ---------" & @CRLF) EndFunc ;==>IwodXMPPNotify_Disconnected Func IwodXMPPNotify_FileTransferStart() ConsoleWrite("------- IwodXMPPNotify_FileTransferStart ---------" & @CRLF) EndFunc ;==>IwodXMPPNotify_FileTransferStart Func IwodXMPPNotify_HostCertificate() ConsoleWrite("------- IwodXMPPNotify_HostCertificate ---------" & @CRLF) EndFunc ;==>IwodXMPPNotify_HostCertificate Func IwodXMPPNotify_PreTranslateCommand($owner, $command) ConsoleWrite("------- IwodXMPPNotify_PreTranslateCommand: " & $command & " ---------" & @CRLF) EndFunc ;==>IwodXMPPNotify_PreTranslateCommand Func IwodXMPPNotify_PreTranslateReply($owner, $val) ConsoleWrite("------- IwodXMPPNotify_PreTranslateReply: " & $val & " ---------" & @CRLF) EndFunc ;==>IwodXMPPNotify_PreTranslateReply Func IwodXMPPNotify_PrivateData() ConsoleWrite("------- IwodXMPPNotify_PrivateData ---------" & @CRLF) EndFunc ;==>IwodXMPPNotify_PrivateData Func IwodXMPPNotify_ServiceRegister() ConsoleWrite("------- IwodXMPPNotify_ServiceRegister ---------" & @CRLF) EndFunc ;==>IwodXMPPNotify_ServiceRegister Func IwodXMPPNotify_ServiceStatusChange() ConsoleWrite("------- IwodXMPPNotify_ServiceStatusChange ---------" & @CRLF) EndFunc ;==>IwodXMPPNotify_ServiceStatusChange Func IwodXMPPNotify_ContactList() ConsoleWrite("------- IwodXMPPNotify_ContactList ---------" & @CRLF) EndFunc ;==>IwodXMPPNotify_ContactList Func IwodXMPPNotify_ChatRooMData() ConsoleWrite("------- IwodXMPPNotify_ChatRooMData ---------" & @CRLF) EndFunc ;==>IwodXMPPNotify_ChatRooMData Func IwodXMPPNotify_ChatRooMListDone() ConsoleWrite("------- IwodXMPPNotify_ChatRooMListDone ---------" & @CRLF) EndFunc ;==>IwodXMPPNotify_ChatRooMListDone Func IwodXMPPNotify_ContactStatusChange() ConsoleWrite("------- IwodXMPPNotify_ContactStatusChange ---------" & @CRLF) EndFunc ;==>IwodXMPPNotify_ContactStatusChange ; This is my custom defined error handler Func MyErrFunc() MsgBox(0, "AutoItCOM Test", "We intercepted a COM Error !" & @CRLF & @CRLF & _ "err.description is: " & @TAB & $oMyError.description & @CRLF & _ "err.windescription:" & @TAB & $oMyError.windescription & @CRLF & _ "err.number is: " & @TAB & Hex($oMyError.number, 8) & @CRLF & _ "err.lastdllerror is: " & @TAB & $oMyError.lastdllerror & @CRLF & _ "err.scriptline is: " & @TAB & $oMyError.scriptline & @CRLF & _ "err.source is: " & @TAB & $oMyError.source & @CRLF & _ "err.helpfile is: " & @TAB & $oMyError.helpfile & @CRLF & _ "err.helpcontext is: " & @TAB & $oMyError.helpcontext _ ) Local $err = $oMyError.number If $err = 0 Then $err = -1 $g_eventerror = $err ; to check for after this function returns EndFunc ;==>MyErrFunc -_-------__--_-_-____---_-_--_-__-__-_ ^^€ñ†®øÞÿ ë×阮§ wï†høµ† ƒë@®, wï†høµ† †ïmë, @ñd wï†høµ† @ †ïmïdï†ÿ ƒø® !ïƒë. €×阮 ñø†, bµ† ïñ§†ë@d wï†hïñ, ñ@ÿ, †h®øµghøµ† †hë 맧ëñ§ë øƒ !ïƒë. Link to comment Share on other sites More sharing options...
enaiman Posted October 28, 2009 Share Posted October 28, 2009 If your only purpose is to join chat rooms and send messages, why don't you use "SendText" method instead of SendMessage? It will work about the same if you are instrrested to send text messages; its big advantage is that you don't need to pass an object as a parameter but a string. I'm using their wodTelnet for quite a long time and I am really happy. If you have any problems you could open a thread on their support forum - they are nice guys and the chances are that you'll get help. Apart from that what can I say? Your code looks fine and it's obvious that you're doing your work; I really doubt I can improve anything. It is a matter of trial and error; that would be my approach. SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script wannabe "Unbeatable" Tic-Tac-Toe Paper-Scissor-Rock ... try to beat it anyway :) Link to comment Share on other sites More sharing options...
zackrspv Posted October 30, 2009 Author Share Posted October 30, 2009 (edited) If your only purpose is to join chat rooms and send messages, why don't you use "SendText" method instead of SendMessage?It will work about the same if you are instrrested to send text messages; its big advantage is that you don't need to pass an object as a parameter but a string.I'm using their wodTelnet for quite a long time and I am really happy. If you have any problems you could open a thread on their support forum - they are nice guys and the chances are that you'll get help.Apart from that what can I say? Your code looks fine and it's obvious that you're doing your work; I really doubt I can improve anything.It is a matter of trial and error; that would be my approach.Due to the time constraints on my project, i decided to forgo using wodXMPP. Instead, i'm going to handle the XML handling myself, and all the commands myself. I'm currently using ChilkatSocket, from ChilKat software, to connect to the server, encrypt using SASL and TLS, and then send/receive information.I even threaded it, using async connection/read/send commands, it's working great. Took my origional autoit script for XMPP (using openssl.exe) from 10-15% CPU usage to 0% cpu usage and 8mb for a full ui and XMPP compliant chat.Loving their addon. MULTITHREAD chat, muahahaha, man i'm happy. (chat handled in separate thread, and command/polling/gui commands handled in primary) Edited October 30, 2009 by zackrspv -_-------__--_-_-____---_-_--_-__-__-_ ^^€ñ†®øÞÿ ë×阮§ wï†høµ† ƒë@®, wï†høµ† †ïmë, @ñd wï†høµ† @ †ïmïdï†ÿ ƒø® !ïƒë. €×阮 ñø†, bµ† ïñ§†ë@d wï†hïñ, ñ@ÿ, †h®øµghøµ† †hë 맧ëñ§ë øƒ !ïƒë. Link to comment Share on other sites More sharing options...
Apzo Posted October 30, 2009 Share Posted October 30, 2009 Hello !Could you please give us the necessary .au3 code to connect to Jabber and send/receive some messages ?I'm very interested, but the COM part is still hard for me Thx ! Apzo.Due to the time constraints on my project, i decided to forgo using wodXMPP. Instead, i'm going to handle the XML handling myself, and all the commands myself. I'm currently using ChilkatSocket, from ChilKat software, to connect to the server, encrypt using SASL and TLS, and then send/receive information.I even threaded it, using async connection/read/send commands, it's working great. Took my origional autoit script for XMPP (using openssl.exe) from 10-15% CPU usage to 0% cpu usage and 8mb for a full ui and XMPP compliant chat.Loving their addon. MULTITHREAD chat, muahahaha, man i'm happy. (chat handled in separate thread, and command/polling/gui commands handled in primary) All the pop3 functions.Rsync your files on your USB key (or anywhere else) Link to comment Share on other sites More sharing options...
zackrspv Posted December 6, 2009 Author Share Posted December 6, 2009 Hello !Could you please give us the necessary .au3 code to connect to Jabber and send/receive some messages ?I'm very interested, but the COM part is still hard for me Thx ! Apzo.Heya, you will need to have the trial version of the ChilkatSocket dll in order to actually use this, as well as the _Base64() UDF. You will need the DLL so that you can send commands out, create the socket, and use a separate thread. You will need the _Base64() UDF so that you can create a proper random CODE ID to use with the server in the ID fields.There are a few issues, which you have to code around:* If your jabber server doesn't support ANON, then you will need a custom auth handler. ANON SASL is the easiest method to connect to the server, because you dont have to parse MD5 hashes. If you do need to use PLAIN or DIGEST-MD5 then you will have to have some method to calculate the HA1, HA2 and Z formats in this article: MD5 Digeset XMPP Of which, the MD5 hash UDF for Autoit wont do that properly for you. So you will need a different method.* You will need to code your own send/receive message handlers, so that you know what is going on, but i'll include some examples here.Global Variables, used throughout the client$codeID_tmp = StringReplace(_base64Encode(Int(Random(0, 99393))), "=", Int(Random(0, 99))) ;- Generate CodeID $codeid_tmp_len = StringLen($codeID_tmp) ;- Grab it's length Global $codeID = StringStripWS(StringTrimLeft($codeID_tmp, $codeid_tmp_len - Int(Random(6, 9))), 8) ;- Format the code properly Global $count = 0 Global $username = "USERNAME" ;- Your username Global $Password = "PASSWORD" ;- Your password Global $host = "SERVER" ;- The Jabber Host Global $ssl = 1 ;- Encrypt using SSL? If $ssl = 0 Then Global $port = 5222 Else Global $port = 5223 EndIf Global $maxWait = 150000 ;- max wait time for the Socket Global $resourceID = "RESOURCEID" Global $codeID, $count, $objXMPPThe CODE TEMPS etc can be disposed of, as only the $codeID is important, but the rest is required to connect. As to SSL, you need to decide if that is what your server will support. If not, then set it to 0, else set it to 1, so that the socket knows to encrypt or not.Best to store your username/password in the registry or a file component or at least encrypted. What i do, for my client, is store them with a Base64 HASH and SALT ID and then decode those at runtime, so taht none of that information is encoded in the script.Connection Callexpandcollapse popup$tmp = _Connect() ;- initiates connection to server If $tmp = -1 Then ;- Process code to re-register all the chilkat DLL's ;- Then just call $tmp = _Connect() again ;- then check if $tmp = -1 ;- If it does, then the system failed to register the COM objects ;- Usually, if you #RequireAdmin, you dont have to worry about that. ConsoleWrite("NO COM OBJECTS" & @CRLF) Exit EndIf Func _Connect() ;- Connection Protocol $objXMPP = connectCOM() ;- Create the COM connection ConsoleWrite($objXMPP & @CRLF) If $objXMPP = -1 Then Return -1 EndIf ;- Start the stream asend($objXMPP, "<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='" & $host & "' version='1.0'>") $data = waitars($objXMPP) If $data = -1 Then Return 1 ConsoleWrite($data & @CRLF) ;//// YOU CAN USE CUSTOM ERROR HANDLING OR THE XML DOM FOR STRIPPING OUT THE XMPP XML THAT IS RETURNED, FOR THE MOST PART ;//// YOU CAN USE THE STRINGINSTR() FUNCTION TO LOOK FOR ERRORS, FAILURES, AUTH ISSUES, ETC, AND THEN MAKE YOUR DECISIONS ;//// ON WHAT TO DO FROM THERE. ;//// ;//// ;//// SEE THE XMPP RFC's for proper message handling and selecting your own AUTH method to the server. For the most part ;//// You can use SASL ANON if your server accepts it, and the entire process can be scripted via autoit. For other ;//// METHODS, such as PLAIN or DIGEST-MD5, you have to be able to calculate the MD5 16 byte Octet and MD5 32 HEX ;//// of all the responses. Which, iirc, autoit cannot do. ;//// ;//// The following code will disconnect you from the server. asend($objXMPP, "</stream:stream>") $data = waitars($objXMPP) ConsoleWrite($data & @CRLF) ;- Logged into the server, have fun! Return 0 EndFunc ;==>_ConnectThe purpose of the connect function is to allow you to process all of the basic XML commands to connect to the server, pass auth, and then grab your roster (which you should store to a global array. Once you are done with that, you can continue on in your client's mani loop.ChilkatSocket COM Creation and ConnectionFunc connectCOM() Local $objXMPP = ObjCreate("Chilkat.Socket") ;- create the COM connection object If Not IsObj($objXMPP) Then ;- If it's not an object, quit Return -1 EndIf $objXMPP.UnlockComponent("YOURUNLOCKCODE") ;- unlock for use If $objXMPP.IsUnlocked = 0 Then Return -1 EndIf With $objXMPP ;- While there IS an object .VerboseLogging = 1 ;- log everything .SslProtocol = "default" ;- auto netgotiate ssl/tls .HeartbeatMs = 50 ;- pretty much instant returns .KeepSessionLog = True ;- log all events .SessionLogEncoding = "esc" ;- set to esc (readable) instead of hex .MaxSendIdlems = $maxWait ;- Max wait for sending messages EndWith $objXMPP.AsyncConnectStart($host, $port, $ssl, $maxWait) ;- Create secondary thread to connect to server While $objXMPP.AsyncConnectFinished = 0 ;- While the connection is connecting Sleep(100) ;- do nothing WEnd $objXMPP.MaxReadIdlems = $maxWait ;- Set the Read idle to the same as $maxWait If $objXMPP.ConnectFailReason <> 0 Then ;- If the connection fails MsgBox(0, "Error", $objXMPP.AsyncConnectLog) ;- Print out why with the full connection log Exit EndIf If Not $objXMPP.IsConnected = 1 Then Return -1 ;- If it connected, but it kills connection instantly, then return -1 Return $objXMPP ;- Return the object EndFunc ;==>connectCOMAssuming this function goes as planned, you will be connected to the server, on the port, address, and ssl type that you specified. One of the key things to note here is that: if you have EVER had a registered version of chilkatSocket on your system, this code will not work. You will need to use the same registered code to gain access to it. It's a protection scheme of the DLL, to prevent people from running unregistered sockets on their machine. As i assume that you have never had one running (which is most likely the case), then you wont have to worry about the 'UNLOCK' sequence, and should have no issue connecting out.When returning this returns a global Object $objXMPP for you to use against all of your commands.Sending FunctionFunc asend($object, $message) ;- Send messages via 2nd thread If $message = "" Then Return -1 ;- Ignore blank messages $object.AsyncSendString($message) ;- Send the actual message While $object.AsyncSendFinished <> 1 ;- While the send action isn't finished Sleep(100) ;- Do nothing WEnd If $object.AsyncSendSuccess <> 1 Then ;- If the send was not successful, return -1 Return -1 EndIf EndFunc ;==>asendHaving the asend in it's own function allows you to simply call it with the OBject and Message, and then continue on. Helps in threaded environments where you want to process other commands while the system has already sent the command to the server.Receive FunctionFunc waitARS($object) ;- Wait for data $data = "" ;- Clear the data just in case If Not IsObj($object) Then ;- If it's not an object, return -1 Return -1 EndIf $object.AsyncReceiveString() ;- Begin to Receive the entire string from the socket While $object.AsyncReceiveFinished <> 1 ;- If it's not finished Sleep(100) ;- Do nothing WEnd If $object.AsyncReceiveSuccess = 1 Then ;- If receive was successful $data = $object.AsyncReceivedString ;- Set the $data varaible to the data received Return $data ;- Return the data EndIf Return -1 ;- Only if data fails to return, return -1 EndFunc ;==>waitARSThis function is a BLOCKING receive function, not useful for anything but the connection routine, or any XML command to the server where you MUST wait on specific codes. It will return the data that was on the stream after the receive has finished.Main Loop RX Check$ars = 0 $connAttempt = 0 while 1 If Not $objXMPP.CheckWriteable(1) = 1 Then ;- ensure the socket is writeable $connAttempt += 1 If $connAttempt = 3 Then ;- if 3 connect attempts exist, then exit Exit EndIf _Connect() ;- if not writeable try to connect ElseIf $objXMPP.ISConnected = 1 Then ;- but if it connects $connAttempt = 0 ;- set back to 0 EndIf If $ars = 0 Then ;- if we are not receving $objXMPP.AsyncReceiveString() ;- send the command to receive $ars = 1 ;- set that we are receving EndIf If $objXMPP.AsyncReceiveFinished = 1 Then ;- keep processing main loop commands until we have finished with the RX function If $objXMPP.AsyncReceiveSuccess = 1 Then ;- if RX was successful $data = $objXMPP.AsyncReceivedString ;- set $data to the data that was received off the socket If $data <> "" Then read($data) ;- call your custom read handler to figure out what to do $ars = 0 ;- set back that we are no longer receving Else $connAttempt += 1 ;- problem w/ the connection, receive failed If $connAttempt = 3 Then ;- same as above, if 3 attempts, exit Exit EndIf _Connect() ;- try to connect again EndIf EndIf sleep(100) ;- only used if you have no other code to run in the main loop (such as a blind message handler) WEndThe above handler would go in your main loop, and all other case/select functions under it. So that it is the first thing your app processes. The custom read handler would be where your XML DOM or XML handling would exist, so that, when it receives the data from read($data), it knows what to do. What I do, in that situation, is parse the data for the prpoer codes, and then send it to the proper function (RX message, RX presence, etc).Example of sending a group chat message (via jabber conference rooms)$outMESSAGE = '<message id="' & $codeID & '-' & $count & '" to="' & $active_Chat & '@' & $cserver & '" type="groupchat"><body>' & $msg & '</body><x xmlns="jabber:x:event"><offline/><delivered/><displayed/><composing/></x></message>' asend($objXMPP, $outMESSAGE & @CRLF)In this case, there are a few items here that need to be filled out, prior to calling this command, of which you will determine client side (such as what chat the cilent is looking at, if multiple chats):* $active_chat = the chat window that the client is looking at (if you have multiple rooms), you will want to make sure that this is set to the proper name of the chat room to send the message too. Such as: 'my_chat_room'* $cserver = the same thing as $host, for the most part, but if you have enhanced security like our system, the host and the chat server are different entities, so if that's the case (where your jabber conference server is not the same as the im server you connect too), then you will want to specificy the global variable $cserver so that it knows where to send the messages too.* $msg = obviously the message you would like to send. Can be most anything, really, as the system processes commands across the board. For special characters like the & sign, it's best you replace them with something else. I'll include a quick replace function for that here later.That's how you send a message to the server. Note, there is no RX command here, we dont care if there is one or not. We only want to SEND the command to the server. In the main loop, the command will check if we are receving. If we are, then it will post the response back stating that the message either was or was not delievered. in which case, your read($data) function would parse for the RESULT and FAILURE messages and take proper action.Receive a MessageFunc read($data) ;- read the data stream and take apprporiate measures based on type of message recieved If $data = "" Then Return -1 If StringLeft($data, 11) = "<message id" And StringRight($data, 10) = "</message>" Then ;- this is a normal XML message handle $array = StringRegExp($data, '(?i)(?s)(?i)(?s)(.*?</message>)', 3, 1) If IsArray($array) Then For $i = 0 To UBound($array) - 1 $ret = $array[$i] chkMessage($ret) ;- Prase the XML for data Next EndIf EndIfNow, as we can see many things are going on here. I chose not to use the XML DOM here only cuz i'm processing only a very limited # of messages from the server for jabber conferences, personal IM's, etc not really what i'm looking for, such as vcards, etc, not what i'm going to be handling. So, i look at the XML data, and look for the <message id and </message> in the stream, at the proper places, if it's there, then i call my checkMessage routine to parse whats in the <body>(.*?)</body> section via regex and then put that into the client's window so they can see what's going on.What I did here, however, was take into account multiple messages bound on the stream. For example if you had:<message id=BLAH from="someone@somewhere.com/NICKNAME" to="me@somewhere.com/MYNICK"><body>SOME MESSAGE</body></message>It would parse just 1 message (as the array had only 1 message). But, if it had multiple:<message id=BLAH from="someone@somewhere.com/NICKNAME" to="me@somewhere.com/MYNICK"><body>SOME MESSAGE</body></message><message id=BLAH from="someone@somewhere.com/NICKNAME" to="me@somewhere.com/MYNICK"><body>SOME MESSAGE</body></message>Then it would parse both messages and send them in series to the proper function (in this case chkmessage()), makes it to where you dont miss many messages coming through You can look for <presence> and <iq> types in the same manner, and prase them out as necessary as well. The point is, once you get a message, you have to know what to do for it, or skip it, so that the communications can continue to go on w/o much issue.Replace special characters that can mess up some XMPP installationsFunc repLines($data) ;- Has several redundant checks, true, but doesn't fail at replacing :) $data = StringRegExpReplace($data, "<", "::LL2T::") $data = StringRegExpReplace($data, ">", "::LG2T::") $data = StringRegExpReplace($data, "\v", "::LBK::") ;- replace all vertical white space $data = StringRegExpReplace($data, "\n", "::LNB::") ;- replace all new lines $data = StringRegExpReplace($data, "\l", "::LNR::") ;- replace all line feeds $data = StringRegExpReplace($data, "<", "::LLT::") ;- replace all < $data = StringRegExpReplace($data, ">", "::LGT::") ;- replace all > $data = StringRegExpReplace($data, "&", "::LAP::") ;- replace all & $data = StringRegExpReplace($data, "<br>", "::CBR::") ;- replace all breaks HTML $data = StringRegExpReplace($data, "/", "::LST::") ;- replace all / Return $data EndFunc ;==>repLinesAbove, are the codes that I found to cause some havoc depending on the server you connect too. So i find it useful to replace them first, and then recombine them before i show the message to the client. Good rule of thumb: Get your messages out to the server all on one line, so that from <message.....> to </message> is all a single line. It speeds up handling and reduces server lag and load times.Recombine the Codes aboveFunc _Recombine($data) ;- recombined the actual message before displaying it $data = StringRegExpReplace($data, "::LL2T::", "<") $data = StringRegExpReplace($data, "::LG2T::", ">") $data = StringRegExpReplace($data, "::LBK::", @LF) ;- restore line breaks with new lines $data = StringRegExpReplace($data, "::LGT::", ">") ;- restore > $data = StringRegExpReplace($data, "::LLT::", "<") ;- restore < $data = StringRegExpReplace($data, "::LST::", "/") ;- restore / $data = StringRegExpReplace($data, "::LAP::", "&") ;- restore & $data = StringRegExpReplace($data, "::LNB::", @LF) ;- restore new line $data = StringRegExpReplace($data, "::LNR::", @CR) ;- restore carrige return $data = StringRegExpReplace($data, "::CBR::", "<br>") ;- restore html breaks Return $data EndFunc ;==>_RecombineThe above will take those special codes and put them back to how they belong, so that the origional message is no longer messed up. Logging into rooms and checking their topics (subjects)expandcollapse popupFunc loginROOM($count) ;- Log into the defined rooms Global $topics[4][2] $topics[0][0] = "my_room_1" $topics[0][1] = "" $topics[1][0] = "my_room_2" $topics[1][1] = "" Global $rooms[7][2] ;- Array containing the rooms list $rooms[0][0] = "my_room_1" $rooms[0][1] = "" $rooms[1][0] = "my_room_2" $rooms[1][1] = "myPassword" $count += 1 $msg = repLines($WelcomeMessage) For $i = 0 To UBound($rooms) - 1 ;- process each command below for each room If $rooms[$i][0] = "" Then Else ;- set presence as active in the room $count += 1 $send = '<presence id="' & $codeID & '-' & $count + $i & '" to="' & $rooms[$i][0] & '@' & $cserver & '/' & $myjid & '"><x xmlns="http://jabber.org/protocol/muc"><password>' & $rooms[$i][1] & '</password></x></presence>' asend($objXMPP, $send & @CRLF) $data = waitars($objXMPP) If $data = -1 Then return -3 If Not StringInStr($data, "presence") Then $data = waitars($objXMPP) If Not StringInStr($data, "presence") Then ContinueLoop EndIf $outMESSAGE = '<message id="' & $codeID & '-' & $count + 1 & '" to="'&$rooms[$i][0]&'@' & $cserver & '" type="groupchat"><body>' & $msg & '</body><x xmlns="jabber:x:event"><offline/><delivered/><displayed/><composing/></x></message>' asend($objXMPP, $outMESSAGE & @CRLF) EndIf Next For $i = 0 To UBound($topics) - 1 If $topics[$i][0] = "" Then Else $count += 1 $query = "<iq id='" & $codeID & "-" & $count + $i & "' to='" & $topics[$i][0] & "@" & $cserver & "' type='get'><query xmlns='http://jabber.org/protocol/disco#info'/></iq>" asend($objXMPP, $query) $data = waitars($objXMPP) If Not StringInStr($data, "result") Then $data = waitars($objXMPP) If Not StringInStr($data, "result") Then ContinueLoop EndIf $tmp = StringRegExp($data, '(?i)(?s)muc#roominfo_subject\"\>\<value\>(.*?)\</value\>', 3, 1) If IsArray($tmp) Then $topics[$i][1] = $tmp[0] ConsoleWrite($topics[$i][1] & @CRLF) EndIf EndIf Next Return 1 EndFunc ;==>loginROOMIf you have Jabber conferences on your server, and you want to be able to JOIN their rooms, and then join them on startup so they are already visible to your clients, you can use somewhat like the above function. There are a few items in there that need to be specified:* Rooms: What rooms you want, added to the array (these are hard coded in the app)* Passwords: What is the password for the room* MyJID: This is what your Jabber Nickname will be, can be most anything, unelss you have registered with the chatroom/server, in which case it should be the bare JID that you have registered with (not your username).While it's not necessary to always code for the $topics array, i decided i'd like a separate array to handle them, so just matching the $rooms array with a blank 2nd element allows me to parse the room topics, and add them to the array.The calls on this function are BLOCKING, so you should do this as part of your CONNECTION routine, so that the client doesn't have a chance to send/receive messages yet.* Welcome Message: You can set your message to whatever you want, as soon as the room is joined, it will send a message to the room stating you are there, or whatever. It does do the replines thing, so if you are doing this to connect to a PUBLIC room, probably best to leave that replines() command out. But for custom client to custom client, you can leave it in.Again, you can use the XML DOM to get all the data here, but i find it more useful to code it for yourself, and just parse out using regex Disconnecting from the Server asend($objXMPP, "</stream:stream>"&@crlf)You will want to clear out all of your object connections (if you need to, chilkat doesn't need too), or any other commands you want to do during close at this point, and then send that above command to the Jabber server, so that you are disconnected from the stream. Find out who is in the room Func getRoomList() $msg = '<iq id="' & $codeID & '-' & $count + 1 & '" to="MY_ROOM_NAME@' & $cserver & '" type="get"><query xmlns="http://jabber.org/protocol/disco#items"></query></iq>' asend($objXMPP, $msg & @CRLF) $data = waitars($objXMPP) If Not StringInStr($data, "<") Then ;- if features WERE not recieved Return -1 ;- send back error EndIf read($data) Return 1 EndFunc ;==>getRoomListYou can process that command in the login to room function, if you wish, but if you are like me, you'll just do that whenever a <presence> message is Received from the jabber conference server. This will allow you to find out who all is part of a room, and in your read() function, you can parse that out by looking at <iq result> commands and ITEM ID's to find out who they are and add them to a global array (i use listviews for this).Connecting via SASL ANON ExmpleYou can connect to the server using SASL ANON, if your server supports it, here's an example login routine to do just that:expandcollapse popupFunc _Connect() ;- Connection Protocol Global $objXMPP = connectCOM() If $objXMPP = -1 Then Return -1 EndIf asend($objXMPP, "<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='" & $host & "' version='1.0'>") $data = waitars($objXMPP) If $data = -1 Then Return 1 ;- couldn't create stream to server asend($objXMPP, "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='ANONYMOUS'/>") $data = waitars($objXMPP) If $data = -1 Then Return 2 ;- couldn't initiate sasl anon asend($objXMPP, "<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='" & $host & "' version='1.0'>") $data = waitars($objXMPP) If $data = -1 Then Return 3 ;- couldn't create second stream to server asend($objXMPP, "<iq type='get' id='" & $codeID & "'><query xmlns='jabber:iq:auth'><username>" & $username & "</username></query></iq>") $data = waitars($objXMPP) If $data = -1 Then Return 4 ;- couldn't query credentials asend($objXMPP, "<iq type='set' id='" & $codeID & "'><query xmlns='jabber:iq:auth'><username>" & $username & "</username><resource>" & $resourceID & "</resource><password>" & $Password & "</password></query></iq>" & @CRLF) $data = waitars($objXMPP) If $data = -1 Then Return 5 ;- couldn't log into the server If StringInStr($data, '<error code=') Then Return -5 asend($objXMPP, "<iq type='get' id='" & $codeID & "'><query xmlns='jabber:iq:roster'/></iq>") $data = waitars($objXMPP) If $data = -1 Then Return 6 ;- couldn't pull the roster If Not StringInStr($data, "item") Then $data = waitars($objXMPP) If Not StringInStr($data, "item") Then Return 6 ;- couldn't pull the roster on retry EndIf $cnt = StringRegExp($data, "(?i)(?s)ROSTER_PREFIX_THAT_YOU_WANT", 3, 1) If IsArray($cnt) Then Global $ContactLIst[UBound($cnt) + 1][2] $tmp = StringRegExp($data, "(?s)(?i)<item(.*?)</item>", 3, 1) If IsArray($tmp) Then $c = -1 For $i = 0 To UBound($tmp) - 1 If StringInStr($tmp[$i], "BT_Tech") Then $dta = StringRegExp($tmp[$i], '(?s)(?i)jid="(.*?)(?:\@.*?)"', 3, 1) If IsArray($dta) Then $tjid = $dta[0] Else $tjid = "" EndIf $dta = StringRegExp($tmp[$i], '(?s)(?i)name="(.*?)"', 3, 1) If IsArray($dta) Then $tname = $dta[0] Else $tname = "" EndIf If $tjid <> "" And $tname <> "" Then $c += 1 $ContactLIst[$c][0] = $tjid $ContactLIst[$c][1] = $tname EndIf EndIf Next Else Return 7 ;- couldn't parse the roster items EndIf Else Return 6 ;- couldn't parse the roster EndIf Return 0 ;- everything went fine, we are connected, encrypted, and logged in. EndFunc ;==>_ConnectThat connects to most any ANON SASL server out there (i have tried about 4 lol) The point is to set the auth to ANON so that you can send your commands, encrypted via SSL and then username/password via SASL to the server. It's quite nice. If you look at the stream's RAW data via a sniffer, it's all jibberish Of course, you'll want to make sure $SSL = 1 and you are connecting to the proper port, or things will just fry -_-------__--_-_-____---_-_--_-__-__-_ ^^€ñ†®øÞÿ ë×阮§ wï†høµ† ƒë@®, wï†høµ† †ïmë, @ñd wï†høµ† @ †ïmïdï†ÿ ƒø® !ïƒë. €×阮 ñø†, bµ† ïñ§†ë@d wï†hïñ, ñ@ÿ, †h®øµghøµ† †hë 맧ëñ§ë øƒ !ïƒë. Link to comment Share on other sites More sharing options...
ynbIpb Posted August 10, 2010 Share Posted August 10, 2010 zackrspv, Please show me an example of how to receive messages using the library wodXMPPThank you. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now