{"id":19477586,"url":"https://github.com/xmppo/xmpp-php","last_synced_at":"2025-04-25T14:32:35.152Z","repository":{"id":49759454,"uuid":"160332557","full_name":"xmppo/xmpp-php","owner":"xmppo","description":"PHP client library for XMPP (Jabber) protocol","archived":false,"fork":false,"pushed_at":"2024-01-22T10:00:23.000Z","size":109,"stargazers_count":47,"open_issues_count":12,"forks_count":22,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-20T15:07:14.486Z","etag":null,"topics":["jabber","jid","php","phpstorm","protocol","socket","xml","xmpp","xmpp-client"],"latest_commit_sha":null,"homepage":"https://github.com/xmppo/xmpp-php","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xmppo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-12-04T09:30:45.000Z","updated_at":"2025-02-18T13:11:53.000Z","dependencies_parsed_at":"2024-11-10T19:46:40.704Z","dependency_job_id":"61ed9145-384e-4be0-bde1-97cef16129b7","html_url":"https://github.com/xmppo/xmpp-php","commit_stats":null,"previous_names":["norgul/xmpp-php"],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmppo%2Fxmpp-php","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmppo%2Fxmpp-php/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmppo%2Fxmpp-php/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmppo%2Fxmpp-php/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xmppo","download_url":"https://codeload.github.com/xmppo/xmpp-php/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250834219,"owners_count":21494930,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["jabber","jid","php","phpstorm","protocol","socket","xml","xmpp","xmpp-client"],"created_at":"2024-11-10T19:45:26.093Z","updated_at":"2025-04-25T14:32:34.789Z","avatar_url":"https://github.com/xmppo.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PHP client library for XMPP (Jabber) protocol\n\n[![Latest Stable Version](https://poser.pugx.org/norgul/xmpp-php/v/stable)](https://packagist.org/packages/norgul/xmpp-php)\n[![Total Downloads](https://poser.pugx.org/norgul/xmpp-php/downloads)](https://packagist.org/packages/norgul/xmpp-php)\n[![Latest Unstable Version](https://poser.pugx.org/norgul/xmpp-php/v/unstable)](https://packagist.org/packages/norgul/xmpp-php)\n[![Build Status](https://travis-ci.org/Norgul/xmpp-php.svg?branch=master)](https://travis-ci.org/Norgul/xmpp-php)\n[![License](https://poser.pugx.org/norgul/xmpp-php/license)](https://packagist.org/packages/norgul/xmpp-php)\n\nThis is low level socket implementation for enabling PHP to \ncommunicate with XMPP due to lack of such libraries online (at least ones I \ncould find that had decent documentation). \n\nXMPP core documentation can be found [here](https://xmpp.org/rfcs/rfc6120.html).\n\n# Installation requirements and example\n\nProject requirements are given in `composer.json` (\n[Composer website](https://getcomposer.org)):\n\nYou can use this library in your project by running:\n\n```\ncomposer require norgul/xmpp-php\n```\n\nYou can see usage example in `Example.php` file by changing credentials to \npoint to your XMPP server and from project root run `php Example.php`.\n\n# Library usage\n## Initialization\nIn order to start using the library you first need to instantiate a new `Options` \nclass. Host, username and password are mandatory fields, while port number, if omitted,\nwill default to `5222` which is XMPP default. \n\nUsername can be either bare `JID` or in `JID/resource` form. If you are using a bare `JID`\nthe resource will be added automatically. You can override this by explicitly setting a \nresource with `$client-\u003eiq-\u003esetResource()`. In the second case the username will be automatically\nparsed to `username` and `resource` variables. In case of `JID/resource/xyz` format, everything\nafter second slash will be ignored. If both `JID/resource` is present as well as using the\n`$client-\u003eiq-\u003esetResource()` method, which ever was defined last will take precedence. \n\n```\n$options = new Options();\n\n$options\n    -\u003esetHost($host)            // required\n    -\u003esetPort($port)            // not required, defaults to 5222\n    -\u003esetUsername($username)    // required\n    -\u003esetPassword($password);   // required\n```\n\n`Options` object is required for establishing the connection and every other subsequent\nrequest, so once set it should not be changed. \n\nOnce this is set you can instantiate a new `XmppClient` object and pass the `Options` object in.\n\n## XMPP client class explanation\nSince XMPP is all about 3 major stanzas, (**IQ, Message and Presence**), I've \ncreated separate classes which are dependant on socket implementation so that you \ncan directly send XML by calling a stanza method. \n\nThis means that 3 stanzas have been made available from `XmppClient` class constructor\nto be used like a chained method on client's concrete class. \n\nCurrent logic thus is `$client-\u003eSTANZA-\u003eMETHOD()`. For example:\n\n```\n$client-\u003eiq-\u003egetRoster();\n$client-\u003emessage-\u003esend();\n$client-\u003epresence-\u003esubscribe();\n```\n\n## Connecting to the server\nBeside being a stanza wrapper, `XmppClient` class offers a few public methods.\n\n`$client-\u003econnect()` method does a few things:\n1. Connects to the socket which was initialized in `XmppClient` constructor\n2. Opens an XML stream to exchange with the XMPP server\n3. Tries to authenticate with the server based on provided credentials\n4. Starts the initial communication with the server, bare minimum to get you started\n\nCurrent version supports `PLAIN` and `DIGEST-MD5` auth methods. \n\nTLS is supported by default. If server has support for TLS, library will \nautomatically try to connect with TLS and make the connection secure. \n\nIf you'd like to explicitly disable this functionality, you can use `setUseTls(false)` \nfunction on the `Options` instance so that TLS communication is disabled. Note\nthat this will function in environments where TLS is supported but not required. \nIf TLS is required, program will connect to it independently of the option you \nset. \n\n## Sending raw data\n`send()` message is exposed as being public in `XmppClient` class, and its intention\nis to send raw XML data to the server. For it to work correctly, XML which you send\nhas to be valid XML. \n\n## Getting raw response\nServer responses (or server side continuous XML session to be exact) can be retrieved with \n`$client-\u003egetResponse()`. This should be used in an infinite loop or for more sustainable\nsolution in some WebSocket solution like [Ratchet](http://socketo.me/) if you'd like to \nsee continuous stream of everything coming from the server.\n\nIf you would like to see the output of the received response in the console you can call the\n`$client-\u003eprettyPrint($response)` method.\n\n## Receiving messages and other responses\n\nIn case you are not interested in complete response which comes from server, you may also use \n`$client-\u003emessage-\u003ereceive()` (`$client-\u003egetMessages()` was removed because it was just a shorthand\nmethod for this one) which will match message tags with regex and return array of matched messages. \nIn case you'd like to see the response in the terminal, you can do something like this:\n\n```\ndo {\n    $response = $client-\u003emessage-\u003ereceive();\n    if($response)\n        echo print_r($response);\n} while (true);\n```\n\n## Disconnect\nDisconnect method sends closing XML to the server to end the currently open session and\ncloses the open socket. \n\n# Stanza method breakdown\nRemember from [here](#xmpp-client-class-explanation) -\u003e `$client-\u003eSTANZA-\u003eMETHOD()`\n\n## Message\n`send()` - sending a message to someone. Takes 3 parameters of which the last one is \noptional. First parameter is the actual message you'd like to send (body), second \none is recipient of the message and third one is type of message to be sent. This \ndefaults to `chat`.\n\nYou can find possible types in [this RFC document](https://xmpp.org/rfcs/rfc3921.html#stanzas)\n\n`receive()` - covered in [this section](#receiving-messages-and-other-responses)\n\n## IQ\n`getRoster()` - takes no arguments and fetches current authenticated user roster. \n\n`setGroup()` - puts a given user in group you provide. Method takes two arguments: \nfirst one being the group name which you will attach to given user, and other \nbeing JID of that user. \n\n## Presence\n\n`setPriority()` - sets priority for given resource. First argument is an integer \n`-128 \u003c\u003e 127`. If no second argument is given, priority will be set for currently used resource.\nOther resource can be provided as a second argument whereas the priority will be set for that\nspecific resource. \n\n`subscribe()` - takes JID as an argument and asks that user for presence.\n\n`acceptSubscription()` - takes JID as an argument and accepts presence from that user.\n\n`declineSubscription()` - takes JID as an argument and declines presence from that user.\n\n## Sessions\n\nSessions are currently being used only to differentiate logs if multiple connections\nare being made. \n\n`XmppClient` class takes in second optional parameter `$sessionId` to which you can \nforward session ID from your system, or it will be assigned automatically. \n\nYou can disable sessions through `Options` object (`$options-\u003esetSessionManager(false)`), \nas they can cause collision with already established sessions if being used inside \nframeworks or similar. Needless to say if this is disabled, forwarding a second parameter\nto `XmppClient` will not establish a new session. \n\n# More options (not required)\n\n`Options` object can take more options which may be chained but are not required. These are explained\nand commented in the code directly in the `Options` class:\n\n```\n$options\n    -\u003esetProtocol($protocol)  // defaults to TCP\n    -\u003esetResource($resource)  // defaults to 'norgul_machine_' string + timestamp\n    -\u003esetLogger($logger)      // logger instance (logging explained below)\n    -\u003esetAuthType($authType)  // Takes on classes which implement Authenticable\n```\n\n## Socket options\nMost of the socket options are set by default so there is no need to tamper\nwith this class, however you can additionally change the timeout for the period \nthe socket will be alive when doing a `socket_read()`, and you can do that with\n`$socket-\u003esetTimeout()`.\n\n## Logging\n\nUpon new established session the library is creating a `xmpp.log` log file in `logs/` folder:\n\nYou can manually set logger when instantiating `Options` with `setLogger($logger)`. The method accepts\nany object which implements `Loggable` interface so you can create your own implementation. \n\nFun fact: this used to be a `PSR-3` logger interface, but I decided it was an overkill for this \nstage of development. \n  \n# Other\n\n`Example.php` has a `sendRawXML()` method which can be helpful with debugging. Method works in a way\nthat you can provide hand-written XML and send it to the server. On the other hand you can \nalso trigger a method by providing method name instead of XML. \n\n```\nEnter XML: \u003cxml\u003efoo\u003c/xml\u003e           \u003c-- will send XML\nEnter XML: getRoster                \u003c-- will run getRoster() method\nEnter XML: requestPresence x@x.com  \u003c-- will run with argument requestPresence(x@x.com)\n```\n\nSome valid XMPP XML will be declined (like sending `\u003cpresence/\u003e`) because `simplexml_load_string()` \nis not able to parse it as being a valid XML. In cases you need to do some custom stuff like \nthat and you are sure it is a XMPP valid XML, you can remove the parsing line and just let the\n`send()` method do its magic.\n \n **Be aware! Be very aware!** sending an invalid XML to the server\nwill probably invalidate currently open XML session and you will probably need to restart the \nscript. This is highly experimental and not maintained really. It is a poor orphan method whose\nparents have abandoned it and left in a hurry. It may prove to be Harry Potter one day, but hey...\nwe all clearly doubt it. You may be a special snowflake but no one likes you. Onward to \norphanagemobil! Begone method (just kidding, I won't delete it)!\n\nWho says readme's are boring. \n\n# Dev documentation\nFor anyone willing to contribute, a quick breakdown of the structure:\n\n---\n- `Options.php` - everything that is variable about the library\n- `Socket.php` - socket related implementation (connecting, reading, writing etc.)\n- `XmppClient.php` - user friendly methods to interact with the library and stanza wrapper enabling users to call stanza methods through\ninstantiated class. This should contain as little logic as possible, turns out it's not so easy :)\n---\n- `AuthTypes` - contains methods to authenticate yourself to XMPP server. Besides concrete implementations there is also an \nabstract class with minor logic to avoid duplication and interface having all the necessary methods should the need for new\nauth type arise. \n\n- `Buffers` - implementation of buffer (or should I say a simple array) which gets filled when socket is calling the `receive()`\nmethod, and it flushes on any read, which happens when calling `getResponse()` method for example. A brief history of why: I had \nissues when a non-recoverable error would be thrown. In this situation I had to do 2 things: try to reconnect, show the error \nto the user. The thing is that `getResponse()` returns string, and in case of reconnection the program execution would continue\nreturning either nothing or returning error string after the server already connected for the second time, thus misinforming the \nuser of the error which occurred before reconnection. Buffer was born. \n\n- `Exceptions` - this is more or less a standard. I am just overriding constructors so I can get my message in.\n\n- `Loggers` - containing logic to store logs to the `logs/xmpp.log` file. The idea was to keep several log types inside (full, simple,\nno logger), but I found the one made to be sufficient. \n\n---\n\n`Xml` \n\n- `Xml.php` - a trait consisting of way too many regex matching. This should be reformatted. \n- `Stanzas` - main logic for all stanza communication with the server. This used to be just plain XML, but I have decided to\nforward a socket dependency inside so that when you call the method, you actually also send it to the server. That used to be \nsomething like `$this-\u003esocket-\u003esend($this-\u003eiq-\u003egetRoster())` which is correct from the programming perspective, but for the\nsimplicity sake, I like the `$client-\u003eiq-\u003egetRoster()` more. I'm open to other suggestions. \n\n---\n\n## CI\nContinuous integration is done through [Travis CI](https://travis-ci.org/), and each push goes through a process which is currently\nas simple as:\n- check unit tests (and god knows I have them)\n- check for syntax errors\n- run `phpcs` (configuration in `phpcs.xml`)\n- run `phpmd` (configuration in `phpmd.xml`)\n\n## TODO's\n\n- **unit testing** - unfortunately I have been prolonging this for far too long, maybe there is a good soul out there who enjoys \nwriting tests.\n- **throttling** - when an unrecoverable error occurs (currently I am catching `\u003cstream:error\u003e` ones which break the stream)\nreconnect is being made automatically. In case this is happening over and over again, program will try connecting indefinitely, \nwhich is fine to any aspect except logs which will get clogged. I would like to throttle the connection so that it increases the\nconnection time each time it is unsuccessful. Problem here is that I can only catch the error when getting the response, and\nresponse can be successful on the first XML exchange (for example when you send opening stream request), while breaking on the \nsecond request. With this in mind my only idea was to implement throttling with timestamps or something. \n- **sessions** - I presume this part is working correctly but should be tested from a framework\n- **multiple connections** - I think this part works fine, but I am worried that triggering `getRoster()` while simultaneously\nfetching a message may delete one server response. If you get in one batch both roster and message, it will be added to the buffer.\nCalling back the response will get either roster or message, not both. And then buffer will be flushed. This is something that\nneeds thinking. \n- **structure of XmppClient** - in order to enable the `$client-\u003estanza-\u003emethod` I need to instantiate all stanzas within the \nclass. I feel as this could be simplified.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxmppo%2Fxmpp-php","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxmppo%2Fxmpp-php","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxmppo%2Fxmpp-php/lists"}