diff --git a/htdocs/lib/jabber/LICENSE_GPL b/htdocs/lib/jabber/LICENSE_GPL new file mode 100644 index 00000000000..5b6e7c66c27 --- /dev/null +++ b/htdocs/lib/jabber/LICENSE_GPL @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/htdocs/lib/jabber/README b/htdocs/lib/jabber/README new file mode 100644 index 00000000000..4710b8fa6e9 --- /dev/null +++ b/htdocs/lib/jabber/README @@ -0,0 +1,59 @@ +Class.Jabber.PHP v0.4 +April 27th, 2003 + +The Jabber Instant Messaging project is an Open Source project seeking +to provide a complete cross protocol messaging solution. The problem +with current IM solutions is that they are all proprietary and cannot +talk to each other. Jabber seeks to get rid of those barriers by +allowing a Jabber client to talk with an AOL user, or an IRC chat room, +or any number of other programs. + +For more information about the Jabber project visit http://www.jabber.org. + +Class.Jabber.PHP a PHP class that provides a PHP Developer access to the +Jabber protocol. Using this OOP class, I provide a clean interface to +writing anything from a full client to a simple protocol tester. + +NOTE: +The documentation in this archive is basically not existing. For docs and +examples please visit the Class.Jabber.PHP wiki @ http://phpjabber.g-blog.net + +Carlo Zottmann +Class.Jabber.PHP developer +http://phpjabber.g-blog.net +gossip@jabber.g-blog.net + + + + +THIS SOFTWARE IS RELEASED UNDER THE GNU GENERAL PUBLIC LICENSE. +http://www.gnu.org/licenses/licenses.html#GPL + + + +REQUIREMENTS + - PHP 4.1.0+ with XML support, mhash support optional (if you want to use + digest or 0k authentication) + + +DOCUMENTATION + +The documentation in this archive is basically not existing. For docs and +examples please visit the Class.Jabber.PHP wiki @ http://phpjabber.g-blog.net + + +STATUS + +For the most part things are stable, but if you see a newer version, you +should switch to it immediatly and read the ChangeLog at +http://phpjabber.g-blog.net/ChangeLog to find out what has changed. + + +For questions, bug reports etc, please visit the official site +http://phpjabber.g-blog.net and the dev board at http://forum.glue.g-blog.net + + + +PS: Thanks to Ryan Eatmon for 80% of the text above... found it in his +Net::Jabber README. ;) + diff --git a/htdocs/lib/jabber/class.jabber.php b/htdocs/lib/jabber/class.jabber.php new file mode 100644 index 00000000000..16a776f8eae --- /dev/null +++ b/htdocs/lib/jabber/class.jabber.php @@ -0,0 +1,1876 @@ +server = "localhost"; + $this->port = "5222"; + + $this->username = "larry"; + $this->password = "curly"; + $this->resource = NULL; + + $this->enable_logging = FALSE; + $this->log_array = array(); + $this->log_filename = ''; + $this->log_filehandler = FALSE; + + $this->packet_queue = array(); + $this->subscription_queue = array(); + + $this->iq_sleep_timer = 1; + $this->delay_disconnect = 1; + + $this->returned_keep_alive = TRUE; + $this->txnid = 0; + + $this->iq_version_name = "Class.Jabber.PHP -- http://phpjabber.g-blog.net -- by Carlo 'Gossip' Zottmann, gossip@jabber.g-blog.net"; + $this->iq_version_version = "0.4"; + $this->iq_version_os = $_SERVER['SERVER_SOFTWARE']; + + $this->connection_class = "CJP_StandardConnector"; + + $this->error_codes = array(400 => "Bad Request", + 401 => "Unauthorized", + 402 => "Payment Required", + 403 => "Forbidden", + 404 => "Not Found", + 405 => "Not Allowed", + 406 => "Not Acceptable", + 407 => "Registration Required", + 408 => "Request Timeout", + 409 => "Conflict", + 500 => "Internal Server Error", + 501 => "Not Implemented", + 502 => "Remove Server Error", + 503 => "Service Unavailable", + 504 => "Remove Server Timeout", + 510 => "Disconnected"); + } + + + + function Connect() + { + $this->_create_logfile(); + + $this->CONNECTOR = new $this->connection_class; + + if ($this->CONNECTOR->OpenSocket($this->server, $this->port)) + { + $this->SendPacket("\n"); + $this->SendPacket("\n"); + + sleep(2); + + if ($this->_check_connected()) + { + $this->connected = TRUE; // Nathan Fritz + return TRUE; + } + else + { + $this->AddToLog("ERROR: Connect() #1"); + return FALSE; + } + } + else + { + $this->AddToLog("ERROR: Connect() #2"); + return FALSE; + } + } + + + + function Disconnect() + { + if (is_int($this->delay_disconnect)) + { + sleep($this->delay_disconnect); + } + + $this->SendPacket(""); + $this->CONNECTOR->CloseSocket(); + + $this->_close_logfile(); + $this->PrintLog(); + } + + + + function SendAuth() + { + $this->auth_id = "auth_" . md5(time() . $_SERVER['REMOTE_ADDR']); + + $this->resource = ($this->resource != NULL) ? $this->resource : ("Class.Jabber.PHP " . md5($this->auth_id)); + $this->jid = "{$this->username}@{$this->server}/{$this->resource}"; + + // request available authentication methods + $payload = "{$this->username}"; + $packet = $this->SendIq(NULL, 'get', $this->auth_id, "jabber:iq:auth", $payload); + + // was a result returned? + if ($this->GetInfoFromIqType($packet) == 'result' && $this->GetInfoFromIqId($packet) == $this->auth_id) + { + // yes, now check for auth method availability in descending order (best to worst) + + if (!function_exists(mhash)) + { + $this->AddToLog("ATTENTION: SendAuth() - mhash() is not available; screw 0k and digest method, we need to go with plaintext auth"); + } + + // auth_0k + if (function_exists(mhash) && isset($packet['iq']['#']['query'][0]['#']['sequence'][0]["#"]) && isset($packet['iq']['#']['query'][0]['#']['token'][0]["#"])) + { + return $this->_sendauth_0k($packet['iq']['#']['query'][0]['#']['token'][0]["#"], $packet['iq']['#']['query'][0]['#']['sequence'][0]["#"]); + } + // digest + elseif (function_exists(mhash) && isset($packet['iq']['#']['query'][0]['#']['digest'])) + { + return $this->_sendauth_digest(); + } + // plain text + elseif ($packet['iq']['#']['query'][0]['#']['password']) + { + return $this->_sendauth_plaintext(); + } + // dude, you're fucked + { + $this->AddToLog("ERROR: SendAuth() #2 - No auth method available!"); + return FALSE; + } + } + else + { + // no result returned + $this->AddToLog("ERROR: SendAuth() #1"); + return FALSE; + } + } + + + + function AccountRegistration($reg_email = NULL, $reg_name = NULL) + { + $packet = $this->SendIq($this->server, 'get', 'reg_01', 'jabber:iq:register'); + + if ($packet) + { + $key = $this->GetInfoFromIqKey($packet); // just in case a key was passed back from the server + unset($packet); + + $payload = "{$this->username} + {$this->password} + $reg_email + $reg_name\n"; + + $payload .= ($key) ? "$key\n" : ''; + + $packet = $this->SendIq($this->server, 'set', "reg_01", "jabber:iq:register", $payload); + + if ($this->GetInfoFromIqType($packet) == 'result') + { + if (isset($packet['iq']['#']['query'][0]['#']['registered'][0]['#'])) + { + $return_code = 1; + } + else + { + $return_code = 2; + } + + if ($this->resource) + { + $this->jid = "{$this->username}@{$this->server}/{$this->resource}"; + } + else + { + $this->jid = "{$this->username}@{$this->server}"; + } + + } + elseif ($this->GetInfoFromIqType($packet) == 'error' && isset($packet['iq']['#']['error'][0]['#'])) + { + // "conflict" error, i.e. already registered + if ($packet['iq']['#']['error'][0]['@']['code'] == '409') + { + $return_code = 1; + } + else + { + $return_code = "Error " . $packet['iq']['#']['error'][0]['@']['code'] . ": " . $packet['iq']['#']['error'][0]['#']; + } + } + + return $return_code; + + } + else + { + return 3; + } + } + + + + function SendPacket($xml) + { + $xml = trim($xml); + + if ($this->CONNECTOR->WriteToSocket($xml)) + { + $this->AddToLog("SEND: $xml"); + return TRUE; + } + else + { + $this->AddToLog('ERROR: SendPacket() #1'); + return FALSE; + } + } + + + + function Listen() + { + unset($incoming); + + while ($line = $this->CONNECTOR->ReadFromSocket(4096)) + { + $incoming .= $line; + } + + $incoming = trim($incoming); + + if ($incoming != "") + { + $this->AddToLog("RECV: $incoming"); + } + + if ($incoming != "") + { + $temp = $this->_split_incoming($incoming); + + for ($a = 0; $a < count($temp); $a++) + { + $this->packet_queue[] = $this->xmlize($temp[$a]); + } + } + + return TRUE; + } + + + + function StripJID($jid = NULL) + { + preg_match("/(.*)\/(.*)/Ui", $jid, $temp); + return ($temp[1] != "") ? $temp[1] : $jid; + } + + + + function SendMessage($to, $type = "normal", $id = NULL, $content = NULL, $payload = NULL) + { + if ($to && is_array($content)) + { + if (!$id) + { + $id = $type . "_" . time(); + } + + $content = $this->_array_htmlspecialchars($content); + + $xml = "\n"; + + if ($content['subject']) + { + $xml .= "" . $content['subject'] . "\n"; + } + + if ($content['thread']) + { + $xml .= "" . $content['thread'] . "\n"; + } + + $xml .= "" . $content['body'] . "\n"; + $xml .= $payload; + $xml .= "\n"; + + + if ($this->SendPacket($xml)) + { + return TRUE; + } + else + { + $this->AddToLog("ERROR: SendMessage() #1"); + return FALSE; + } + } + else + { + $this->AddToLog("ERROR: SendMessage() #2"); + return FALSE; + } + } + + + + function SendPresence($type = NULL, $to = NULL, $status = NULL, $show = NULL, $priority = NULL) + { + $xml = "\n" : " />\n"; + + $xml .= ($status) ? " $status\n" : ''; + $xml .= ($show) ? " $show\n" : ''; + $xml .= ($priority) ? " $priority\n" : ''; + + $xml .= ($status || $show || $priority) ? "\n" : ''; + + if ($this->SendPacket($xml)) + { + return TRUE; + } + else + { + $this->AddToLog("ERROR: SendPresence() #1"); + return FALSE; + } + } + + + + function SendError($to, $id = NULL, $error_number, $error_message = NULL) + { + $xml = "error_codes[$error_number]; + $xml .= "\n"; + $xml .= ""; + + $this->SendPacket($xml); + } + + + + function RosterUpdate() + { + $roster_request_id = "roster_" . time(); + + $incoming_array = $this->SendIq(NULL, 'get', $roster_request_id, "jabber:iq:roster"); + + if (is_array($incoming_array)) + { + if ($incoming_array['iq']['@']['type'] == 'result' + && $incoming_array['iq']['@']['id'] == $roster_request_id + && $incoming_array['iq']['#']['query']['0']['@']['xmlns'] == "jabber:iq:roster") + { + $number_of_contacts = count($incoming_array['iq']['#']['query'][0]['#']['item']); + $this->roster = array(); + + for ($a = 0; $a < $number_of_contacts; $a++) + { + $this->roster[$a] = array( "jid" => strtolower($incoming_array['iq']['#']['query'][0]['#']['item'][$a]['@']['jid']), + "name" => $incoming_array['iq']['#']['query'][0]['#']['item'][$a]['@']['name'], + "subscription" => $incoming_array['iq']['#']['query'][0]['#']['item'][$a]['@']['subscription'], + "group" => $incoming_array['iq']['#']['query'][0]['#']['item'][$a]['#']['group'][0]['#'] + ); + } + + return TRUE; + } + else + { + $this->AddToLog("ERROR: RosterUpdate() #1"); + return FALSE; + } + } + else + { + $this->AddToLog("ERROR: RosterUpdate() #2"); + return FALSE; + } + } + + + + function RosterAddUser($jid = NULL, $id = NULL, $name = NULL) + { + $id = ($id) ? $id : "adduser_" . time(); + + if ($jid) + { + $payload = " SendIq(NULL, 'set', $id, "jabber:iq:roster", $payload); + + if ($this->GetInfoFromIqType($packet) == 'result') + { + $this->RosterUpdate(); + return TRUE; + } + else + { + $this->AddToLog("ERROR: RosterAddUser() #2"); + return FALSE; + } + } + else + { + $this->AddToLog("ERROR: RosterAddUser() #1"); + return FALSE; + } + } + + + + function RosterRemoveUser($jid = NULL, $id = NULL) + { + $id = ($id) ? $id : 'deluser_' . time(); + + if ($jid && $id) + { + $packet = $this->SendIq(NULL, 'set', $id, "jabber:iq:roster", ""); + + if ($this->GetInfoFromIqType($packet) == 'result') + { + $this->RosterUpdate(); + return TRUE; + } + else + { + $this->AddToLog("ERROR: RosterRemoveUser() #2"); + return FALSE; + } + } + else + { + $this->AddToLog("ERROR: RosterRemoveUser() #1"); + return FALSE; + } + } + + + + function RosterExistsJID($jid = NULL) + { + if ($jid) + { + if ($this->roster) + { + for ($a = 0; $a < count($this->roster); $a++) + { + if ($this->roster[$a]['jid'] == strtolower($jid)) + { + return $a; + } + } + } + else + { + $this->AddToLog("ERROR: RosterExistsJID() #2"); + return FALSE; + } + } + else + { + $this->AddToLog("ERROR: RosterExistsJID() #1"); + return FALSE; + } + } + + + + function GetFirstFromQueue() + { + return array_shift($this->packet_queue); + } + + + + function GetFromQueueById($packet_type, $id) + { + $found_message = FALSE; + + foreach ($this->packet_queue as $key => $value) + { + if ($value[$packet_type]['@']['id'] == $id) + { + $found_message = $value; + unset($this->packet_queue[$key]); + + break; + } + } + + return (is_array($found_message)) ? $found_message : FALSE; + } + + + + function CallHandler($packet = NULL) + { + $packet_type = $this->_get_packet_type($packet); + + if ($packet_type == "message") + { + $type = $packet['message']['@']['type']; + $type = ($type != "") ? $type : "normal"; + $funcmeth = "Handler_message_$type"; + } + elseif ($packet_type == "iq") + { + $namespace = $packet['iq']['#']['query'][0]['@']['xmlns']; + $namespace = str_replace(":", "_", $namespace); + $funcmeth = "Handler_iq_$namespace"; + } + elseif ($packet_type == "presence") + { + $type = $packet['presence']['@']['type']; + $type = ($type != "") ? $type : "available"; + $funcmeth = "Handler_presence_$type"; + } + + + if ($funcmeth != '') + { + if (function_exists($funcmeth)) + { + call_user_func($funcmeth, $packet); + } + elseif (method_exists($this, $funcmeth)) + { + call_user_func(array(&$this, $funcmeth), $packet); + } + else + { + $this->Handler_NOT_IMPLEMENTED($packet); + $this->AddToLog("ERROR: CallHandler() #1 - neither method nor function $funcmeth() available"); + } + } + } + + + + function CruiseControl($seconds = -1) + { + $count = 0; + + while ($count != $seconds) + { + $this->Listen(); + + do { + $packet = $this->GetFirstFromQueue(); + + if ($packet) { + $this->CallHandler($packet); + } + + } while (count($this->packet_queue) > 1); + + $count += 0.25; + usleep(250000); + + if ($this->last_ping_time != date('H:i')) + { + // Modified by Nathan Fritz + if ($this->returned_keep_alive == FALSE) + { + $this->connected = FALSE; + $this->AddToLog('EVENT: Disconnected'); + } + + $this->returned_keep_alive = FALSE; + $this->keep_alive_id = 'keep_alive_' . time(); + $this->SendPacket("", 'CruiseControl'); + // ** + + $this->last_ping_time = date("H:i"); + } + } + + return TRUE; + } + + + + function SubscriptionAcceptRequest($to = NULL) + { + return ($to) ? $this->SendPresence("subscribed", $to) : FALSE; + } + + + + function SubscriptionDenyRequest($to = NULL) + { + return ($to) ? $this->SendPresence("unsubscribed", $to) : FALSE; + } + + + + function Subscribe($to = NULL) + { + return ($to) ? $this->SendPresence("subscribe", $to) : FALSE; + } + + + + function Unsubscribe($to = NULL) + { + return ($to) ? $this->SendPresence("unsubscribe", $to) : FALSE; + } + + + + function SendIq($to = NULL, $type = 'get', $id = NULL, $xmlns = NULL, $payload = NULL, $from = NULL) + { + if (!preg_match("/^(get|set|result|error)$/", $type)) + { + unset($type); + + $this->AddToLog("ERROR: SendIq() #2 - type must be 'get', 'set', 'result' or 'error'"); + return FALSE; + } + elseif ($id && $xmlns) + { + $xml = "SendPacket($xml); + sleep($this->iq_sleep_timer); + $this->Listen(); + + return (preg_match("/^(get|set)$/", $type)) ? $this->GetFromQueueById("iq", $id) : TRUE; + } + else + { + $this->AddToLog("ERROR: SendIq() #1 - to, id and xmlns are mandatory"); + return FALSE; + } + } + + + + // get the transport registration fields + // method written by Steve Blinch, http://www.blitzaffe.com + function TransportRegistrationDetails($transport) + { + $this->txnid++; + $packet = $this->SendIq($transport, 'get', "reg_{$this->txnid}", "jabber:iq:register", NULL, $this->jid); + + if ($packet) + { + $res = array(); + + foreach ($packet['iq']['#']['query'][0]['#'] as $element => $data) + { + if ($element != 'instructions' && $element != 'key') + { + $res[] = $element; + } + } + + return $res; + } + else + { + return 3; + } + } + + + + // register with the transport + // method written by Steve Blinch, http://www.blitzaffe.com + function TransportRegistration($transport, $details) + { + $this->txnid++; + $packet = $this->SendIq($transport, 'get', "reg_{$this->txnid}", "jabber:iq:register", NULL, $this->jid); + + if ($packet) + { + $key = $this->GetInfoFromIqKey($packet); // just in case a key was passed back from the server + unset($packet); + + $payload = ($key) ? "$key\n" : ''; + foreach ($details as $element => $value) + { + $payload .= "<$element>$value\n"; + } + + $packet = $this->SendIq($transport, 'set', "reg_{$this->txnid}", "jabber:iq:register", $payload); + + if ($this->GetInfoFromIqType($packet) == 'result') + { + if (isset($packet['iq']['#']['query'][0]['#']['registered'][0]['#'])) + { + $return_code = 1; + } + else + { + $return_code = 2; + } + } + elseif ($this->GetInfoFromIqType($packet) == 'error') + { + if (isset($packet['iq']['#']['error'][0]['#'])) + { + $return_code = "Error " . $packet['iq']['#']['error'][0]['@']['code'] . ": " . $packet['iq']['#']['error'][0]['#']; + $this->AddToLog('ERROR: TransportRegistration()'); + } + } + + return $return_code; + } + else + { + return 3; + } + } + + + + function GetvCard($jid = NULL, $id = NULL) + { + if (!$id) + { + $id = "vCard_" . md5(time() . $_SERVER['REMOTE_ADDR']); + } + + if ($jid) + { + $xml = " + + "; + + $this->SendPacket($xml); + sleep($this->iq_sleep_timer); + $this->Listen(); + + return $this->GetFromQueueById("iq", $id); + } + else + { + $this->AddToLog("ERROR: GetvCard() #1 - to and id are mandatory"); + return FALSE; + } + } + + + + function PrintLog() + { + if ($this->enable_logging) + { + if ($this->log_filehandler) + { + echo "

Logging enabled, logged events have been written to the file {$this->log_filename}.

\n"; + } + else + { + echo "

Logging enabled, logged events below:

\n"; + echo "
\n";
+				echo (count($this->log_array) > 0) ? implode("\n\n\n", $this->log_array) : "No logged events.";
+				echo "
\n"; + } + } + } + + + + // ====================================================================== + // private methods + // ====================================================================== + + + + function _sendauth_0k($zerok_token, $zerok_sequence) + { + // initial hash of password + $zerok_hash = mhash(MHASH_SHA1, $this->password); + $zerok_hash = bin2hex($zerok_hash); + + // sequence 0: hash of hashed-password and token + $zerok_hash = mhash(MHASH_SHA1, $zerok_hash . $zerok_token); + $zerok_hash = bin2hex($zerok_hash); + + // repeat as often as needed + for ($a = 0; $a < $zerok_sequence; $a++) + { + $zerok_hash = mhash(MHASH_SHA1, $zerok_hash); + $zerok_hash = bin2hex($zerok_hash); + } + + $payload = "{$this->username} + $zerok_hash + {$this->resource}"; + + $packet = $this->SendIq(NULL, 'set', $this->auth_id, "jabber:iq:auth", $payload); + + // was a result returned? + if ($this->GetInfoFromIqType($packet) == 'result' && $this->GetInfoFromIqId($packet) == $this->auth_id) + { + return TRUE; + } + else + { + $this->AddToLog("ERROR: _sendauth_0k() #1"); + return FALSE; + } + } + + + + function _sendauth_digest() + { + $payload = "{$this->username} + {$this->resource} + " . bin2hex(mhash(MHASH_SHA1, $this->stream_id . $this->password)) . ""; + + $packet = $this->SendIq(NULL, 'set', $this->auth_id, "jabber:iq:auth", $payload); + + // was a result returned? + if ($this->GetInfoFromIqType($packet) == 'result' && $this->GetInfoFromIqId($packet) == $this->auth_id) + { + return TRUE; + } + else + { + $this->AddToLog("ERROR: _sendauth_digest() #1"); + return FALSE; + } + } + + + + function _sendauth_plaintext() + { + $payload = "{$this->username} + {$this->password} + {$this->resource}"; + + $packet = $this->SendIq(NULL, 'set', $this->auth_id, "jabber:iq:auth", $payload); + + // was a result returned? + if ($this->GetInfoFromIqType($packet) == 'result' && $this->GetInfoFromIqId($packet) == $this->auth_id) + { + return TRUE; + } + else + { + $this->AddToLog("ERROR: _sendauth_plaintext() #1"); + return FALSE; + } + } + + + + function _listen_incoming() + { + unset($incoming); + + while ($line = $this->CONNECTOR->ReadFromSocket(4096)) + { + $incoming .= $line; + } + + $incoming = trim($incoming); + + if ($incoming != "") + { + $this->AddToLog("RECV: $incoming"); + } + + return $this->xmlize($incoming); + } + + + + function _check_connected() + { + $incoming_array = $this->_listen_incoming(); + + if (is_array($incoming_array)) + { + if ($incoming_array["stream:stream"]['@']['from'] == $this->server + && $incoming_array["stream:stream"]['@']['xmlns'] == "jabber:client" + && $incoming_array["stream:stream"]['@']["xmlns:stream"] == "http://etherx.jabber.org/streams") + { + $this->stream_id = $incoming_array["stream:stream"]['@']['id']; + + return TRUE; + } + else + { + $this->AddToLog("ERROR: _check_connected() #1"); + return FALSE; + } + } + else + { + $this->AddToLog("ERROR: _check_connected() #2"); + return FALSE; + } + } + + + + function _get_packet_type($packet = NULL) + { + if (is_array($packet)) + { + reset($packet); + $packet_type = key($packet); + } + + return ($packet_type) ? $packet_type : FALSE; + } + + + + function _split_incoming($incoming) + { + $temp = preg_split("/<(message|iq|presence|stream)/", $incoming, -1, PREG_SPLIT_DELIM_CAPTURE); + $array = array(); + + for ($a = 1; $a < count($temp); $a = $a + 2) + { + $array[] = "<" . $temp[$a] . $temp[($a + 1)]; + } + + return $array; + } + + + + function _create_logfile() + { + if ($this->log_filename != '' && $this->enable_logging) + { + $this->log_filehandler = fopen($this->log_filename, 'w'); + } + } + + + + function AddToLog($string) + { + if ($this->enable_logging) + { + if ($this->log_filehandler) + { + fwrite($this->log_filehandler, $string . "\n\n"); + } + else + { + $this->log_array[] = htmlspecialchars($string); + } + } + } + + + + function _close_logfile() + { + if ($this->log_filehandler) + { + fclose($this->log_filehandler); + } + } + + + + // _array_htmlspecialchars() + // applies htmlspecialchars() to all values in an array + + function _array_htmlspecialchars($array) + { + if (is_array($array)) + { + foreach ($array as $k => $v) + { + if (is_array($v)) + { + $v = $this->_array_htmlspecialchars($v); + } + else + { + $v = htmlspecialchars($v); + } + } + } + + return $array; + } + + + + // ====================================================================== + // parsers + // ====================================================================== + + + + function GetInfoFromMessageFrom($packet = NULL) + { + return (is_array($packet)) ? $packet['message']['@']['from'] : FALSE; + } + + + + function GetInfoFromMessageType($packet = NULL) + { + return (is_array($packet)) ? $packet['message']['@']['type'] : FALSE; + } + + + + function GetInfoFromMessageId($packet = NULL) + { + return (is_array($packet)) ? $packet['message']['@']['id'] : FALSE; + } + + + + function GetInfoFromMessageThread($packet = NULL) + { + return (is_array($packet)) ? $packet['message']['#']['thread'][0]['#'] : FALSE; + } + + + + function GetInfoFromMessageSubject($packet = NULL) + { + return (is_array($packet)) ? $packet['message']['#']['subject'][0]['#'] : FALSE; + } + + + + function GetInfoFromMessageBody($packet = NULL) + { + return (is_array($packet)) ? $packet['message']['#']['body'][0]['#'] : FALSE; + } + + + + function GetInfoFromMessageError($packet = NULL) + { + $error = preg_replace("/^\/$/", "", ($packet['message']['#']['error'][0]['@']['code'] . "/" . $packet['message']['#']['error'][0]['#'])); + return (is_array($packet)) ? $error : FALSE; + } + + + + // ====================================================================== + // parsers + // ====================================================================== + + + + function GetInfoFromIqFrom($packet = NULL) + { + return (is_array($packet)) ? $packet['iq']['@']['from'] : FALSE; + } + + + + function GetInfoFromIqType($packet = NULL) + { + return (is_array($packet)) ? $packet['iq']['@']['type'] : FALSE; + } + + + + function GetInfoFromIqId($packet = NULL) + { + return (is_array($packet)) ? $packet['iq']['@']['id'] : FALSE; + } + + + + function GetInfoFromIqKey($packet = NULL) + { + return (is_array($packet)) ? $packet['iq']['#']['query'][0]['#']['key'][0]['#'] : FALSE; + } + + + + function GetInfoFromIqError($packet = NULL) + { + $error = preg_replace("/^\/$/", "", ($packet['iq']['#']['error'][0]['@']['code'] . "/" . $packet['iq']['#']['error'][0]['#'])); + return (is_array($packet)) ? $error : FALSE; + } + + + + // ====================================================================== + // parsers + // ====================================================================== + + + + function GetInfoFromPresenceFrom($packet = NULL) + { + return (is_array($packet)) ? $packet['presence']['@']['from'] : FALSE; + } + + + + function GetInfoFromPresenceType($packet = NULL) + { + return (is_array($packet)) ? $packet['presence']['@']['type'] : FALSE; + } + + + + function GetInfoFromPresenceStatus($packet = NULL) + { + return (is_array($packet)) ? $packet['presence']['#']['status'][0]['#'] : FALSE; + } + + + + function GetInfoFromPresenceShow($packet = NULL) + { + return (is_array($packet)) ? $packet['presence']['#']['show'][0]['#'] : FALSE; + } + + + + function GetInfoFromPresencePriority($packet = NULL) + { + return (is_array($packet)) ? $packet['presence']['#']['priority'][0]['#'] : FALSE; + } + + + + // ====================================================================== + // handlers + // ====================================================================== + + + + function Handler_message_normal($packet) + { + $from = $packet['message']['@']['from']; + $this->AddToLog("EVENT: Message (type normal) from $from"); + } + + + + function Handler_message_chat($packet) + { + $from = $packet['message']['@']['from']; + $this->AddToLog("EVENT: Message (type chat) from $from"); + } + + + + function Handler_message_groupchat($packet) + { + $from = $packet['message']['@']['from']; + $this->AddToLog("EVENT: Message (type groupchat) from $from"); + } + + + + function Handler_message_headline($packet) + { + $from = $packet['message']['@']['from']; + $this->AddToLog("EVENT: Message (type headline) from $from"); + } + + + + function Handler_message_error($packet) + { + $from = $packet['message']['@']['from']; + $this->AddToLog("EVENT: Message (type error) from $from"); + } + + + + // ====================================================================== + // handlers + // ====================================================================== + + + + // application version updates + function Handler_iq_jabber_iq_autoupdate($packet) + { + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: jabber:iq:autoupdate from $from"); + } + + + + // interactive server component properties + function Handler_iq_jabber_iq_agent($packet) + { + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: jabber:iq:agent from $from"); + } + + + + // method to query interactive server components + function Handler_iq_jabber_iq_agents($packet) + { + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: jabber:iq:agents from $from"); + } + + + + // simple client authentication + function Handler_iq_jabber_iq_auth($packet) + { + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: jabber:iq:auth from $from"); + } + + + + // out of band data + function Handler_iq_jabber_iq_oob($packet) + { + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: jabber:iq:oob from $from"); + } + + + + // method to store private data on the server + function Handler_iq_jabber_iq_private($packet) + { + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: jabber:iq:private from $from"); + } + + + + // method for interactive registration + function Handler_iq_jabber_iq_register($packet) + { + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: jabber:iq:register from $from"); + } + + + + // client roster management + function Handler_iq_jabber_iq_roster($packet) + { + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: jabber:iq:roster from $from"); + } + + + + // method for searching a user database + function Handler_iq_jabber_iq_search($packet) + { + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: jabber:iq:search from $from"); + } + + + + // method for requesting the current time + function Handler_iq_jabber_iq_time($packet) + { + $type = $this->GetInfoFromIqType($packet); + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + $id = ($id != "") ? $id : "time_" . time(); + + if ($type == 'get') + { + $payload = "" . gmdate("Ydm\TH:i:s") . " + " . date("T") . " + " . date("Y/d/m h:i:s A") . ""; + + $this->SendIq($from, 'result', $id, "jabber:iq:time", $payload); + } + + $this->AddToLog("EVENT: jabber:iq:time (type $type) from $from"); + } + + + + // method for requesting version + function Handler_iq_jabber_iq_version($packet) + { + $type = $this->GetInfoFromIqType($packet); + $from = $this->GetInfoFromIqFrom($packet); + $id = $this->GetInfoFromIqId($packet); + $id = ($id != "") ? $id : "version_" . time(); + + if ($type == 'get') + { + $payload = "{$this->iq_version_name} + {$this->iq_version_os} + {$this->iq_version_version}"; + + $this->SendIq($from, 'result', $id, "jabber:iq:version", $payload); + } + + $this->AddToLog("EVENT: jabber:iq:version (type $type) from $from"); + } + + + + // keepalive method, added by Nathan Fritz + function Handler_iq_($packet) + { + if ($this->keep_alive_id == $this->GetInfoFromIqId($packet)) + { + $this->returned_keep_alive = TRUE; + $this->AddToLog('EVENT: Keep-Alive returned, connection alive.'); + } + } + + + + // ====================================================================== + // handlers + // ====================================================================== + + + + function Handler_presence_available($packet) + { + $from = $this->GetInfoFromPresenceFrom($packet); + + $show_status = $this->GetInfoFromPresenceStatus($packet) . " / " . $this->GetInfoFromPresenceShow($packet); + $show_status = ($show_status != " / ") ? " ($addendum)" : ''; + + $this->AddToLog("EVENT: Presence (type: available) - $from is available $show_status"); + } + + + + function Handler_presence_unavailable($packet) + { + $from = $this->GetInfoFromPresenceFrom($packet); + + $show_status = $this->GetInfoFromPresenceStatus($packet) . " / " . $this->GetInfoFromPresenceShow($packet); + $show_status = ($show_status != " / ") ? " ($addendum)" : ''; + + $this->AddToLog("EVENT: Presence (type: unavailable) - $from is unavailable $show_status"); + } + + + + function Handler_presence_subscribe($packet) + { + $from = $this->GetInfoFromPresenceFrom($packet); + $this->SubscriptionAcceptRequest($from); + $this->RosterUpdate(); + + $this->log_array[] = "Presence: (type: subscribe) - Subscription request from $from, was added to \$this->subscription_queue, roster updated"; + } + + + + function Handler_presence_subscribed($packet) + { + $from = $this->GetInfoFromPresenceFrom($packet); + $this->RosterUpdate(); + + $this->AddToLog("EVENT: Presence (type: subscribed) - Subscription allowed by $from, roster updated"); + } + + + + function Handler_presence_unsubscribe($packet) + { + $from = $this->GetInfoFromPresenceFrom($packet); + $this->SendPresence("unsubscribed", $from); + $this->RosterUpdate(); + + $this->AddToLog("EVENT: Presence (type: unsubscribe) - Request to unsubscribe from $from, was automatically approved, roster updated"); + } + + + + function Handler_presence_unsubscribed($packet) + { + $from = $this->GetInfoFromPresenceFrom($packet); + $this->RosterUpdate(); + + $this->AddToLog("EVENT: Presence (type: unsubscribed) - Unsubscribed from $from's presence"); + } + + + + // Added By Nathan Fritz + function Handler_presence_error($packet) + { + $from = $this->GetInfoFromPresenceFrom($packet); + $this->AddToLog("EVENT: Presence (type: error) - Error in $from's presence"); + } + + + + // ====================================================================== + // Generic handlers + // ====================================================================== + + + + // Generic handler for unsupported requests + function Handler_NOT_IMPLEMENTED($packet) + { + $packet_type = $this->_get_packet_type($packet); + $from = call_user_func(array(&$this, "GetInfoFrom" . ucfirst($packet_type) . "From"), $packet); + $id = call_user_func(array(&$this, "GetInfoFrom" . ucfirst($packet_type) . "Id"), $packet); + + $this->SendError($from, $id, 501); + $this->AddToLog("EVENT: Unrecognized <$packet_type/> from $from"); + } + + + + // ====================================================================== + // Third party code + // m@d pr0ps to the coders ;) + // ====================================================================== + + + + // xmlize() + // (c) Hans Anderson / http://www.hansanderson.com/php/xml/ + + function xmlize($data) + { + $vals = $index = $array = array(); + $parser = xml_parser_create(); + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); + xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); + xml_parse_into_struct($parser, $data, $vals, $index); + xml_parser_free($parser); + + $i = 0; + + $tagname = $vals[$i]['tag']; + $array[$tagname]['@'] = $vals[$i]['attributes']; + $array[$tagname]['#'] = $this->_xml_depth($vals, $i); + + return $array; + } + + + + // _xml_depth() + // (c) Hans Anderson / http://www.hansanderson.com/php/xml/ + + function _xml_depth($vals, &$i) + { + $children = array(); + + if ($vals[$i]['value']) + { + array_push($children, trim($vals[$i]['value'])); + } + + while (++$i < count($vals)) + { + switch ($vals[$i]['type']) + { + case 'cdata': + array_push($children, trim($vals[$i]['value'])); + break; + + case 'complete': + $tagname = $vals[$i]['tag']; + $size = sizeof($children[$tagname]); + $children[$tagname][$size]['#'] = trim($vals[$i]['value']); + if ($vals[$i]['attributes']) + { + $children[$tagname][$size]['@'] = $vals[$i]['attributes']; + } + break; + + case 'open': + $tagname = $vals[$i]['tag']; + $size = sizeof($children[$tagname]); + if ($vals[$i]['attributes']) + { + $children[$tagname][$size]['@'] = $vals[$i]['attributes']; + $children[$tagname][$size]['#'] = $this->_xml_depth($vals, $i); + } + else + { + $children[$tagname][$size]['#'] = $this->_xml_depth($vals, $i); + } + break; + + case 'close': + return $children; + break; + } + } + + return $children; + } + + + + // TraverseXMLize() + // (c) acebone@f2s.com, a HUGE help! + + function TraverseXMLize($array, $arrName = "array", $level = 0) + { + if ($level == 0) + { + echo "
";
+		}
+
+		while (list($key, $val) = @each($array))
+		{
+			if (is_array($val))
+			{
+				$this->TraverseXMLize($val, $arrName . "[" . $key . "]", $level + 1);
+			}
+			else
+			{
+				echo '$' . $arrName . '[' . $key . '] = "' . $val . "\"\n";
+			}
+		}
+
+		if ($level == 0)
+		{
+			echo "
"; + } + } +} + + + +class MakeXML extends Jabber +{ + var $nodes; + + + function MakeXML() + { + $nodes = array(); + } + + + + function AddPacketDetails($string, $value = NULL) + { + if (preg_match("/\(([0-9]*)\)$/i", $string)) + { + $string .= "/[\"#\"]"; + } + + $temp = @explode("/", $string); + + for ($a = 0; $a < count($temp); $a++) + { + $temp[$a] = preg_replace("/^[@]{1}([a-z0-9_]*)$/i", "[\"@\"][\"\\1\"]", $temp[$a]); + $temp[$a] = preg_replace("/^([a-z0-9_]*)\(([0-9]*)\)$/i", "[\"\\1\"][\\2]", $temp[$a]); + $temp[$a] = preg_replace("/^([a-z0-9_]*)$/i", "[\"\\1\"]", $temp[$a]); + } + + $node = implode("", $temp); + + // Yeahyeahyeah, I know it's ugly... get over it. ;) + echo "\$this->nodes$node = \"" . htmlspecialchars($value) . "\";
"; + eval("\$this->nodes$node = \"" . htmlspecialchars($value) . "\";"); + } + + + + function BuildPacket($array = NULL) + { + + if (!$array) + { + $array = $this->nodes; + } + + if (is_array($array)) + { + array_multisort($array, SORT_ASC, SORT_STRING); + + foreach ($array as $key => $value) + { + if (is_array($value) && $key == "@") + { + foreach ($value as $subkey => $subvalue) + { + $subvalue = htmlspecialchars($subvalue); + $text .= " $subkey='$subvalue'"; + } + + $text .= ">\n"; + + } + elseif ($key == "#") + { + $text .= htmlspecialchars($value); + } + elseif (is_array($value)) + { + for ($a = 0; $a < count($value); $a++) + { + $text .= "<$key"; + + if (!$this->_preg_grep_keys("/^@/", $value[$a])) + { + $text .= ">"; + } + + $text .= $this->BuildPacket($value[$a]); + + $text .= "\n"; + } + } + else + { + $value = htmlspecialchars($value); + $text .= "<$key>$value\n"; + } + } + + return $text; + } + } + + + + function _preg_grep_keys($pattern, $array) + { + while (list($key, $val) = each($array)) + { + if (preg_match($pattern, $key)) + { + $newarray[$key] = $val; + } + } + return (is_array($newarray)) ? $newarray : FALSE; + } +} + + + +class CJP_StandardConnector +{ + var $active_socket; + + function OpenSocket($server, $port) + { + if ($this->active_socket = fsockopen($server, $port)) + { + socket_set_blocking($this->active_socket, 0); + socket_set_timeout($this->active_socket, 31536000); + + return TRUE; + } + else + { + return FALSE; + } + } + + + + function CloseSocket() + { + return fclose($this->active_socket); + } + + + + function WriteToSocket($data) + { + return fwrite($this->active_socket, $data); + } + + + + function ReadFromSocket($chunksize) + { + set_magic_quotes_runtime(0); + $buffer = fread($this->active_socket, $chunksize); + set_magic_quotes_runtime(get_magic_quotes_gpc()); + + return $buffer; + } +} + + + +?>