AnyEven...:Writer(3)
π NAME π
AnyEvent::XMPP::Writer β the "XML" writer for XMPP. This is the manual page for AnyEvent::XMPP::Writer(3) from the User Contributed Perl Documentation, and yes bestie, those scare quotes around "XML" are load-bearing π.
π SYNOPSIS π
use AnyEvent::XMPP::Writer;
...
π¦ DESCRIPTION π¦
Okay so this module is a little collection of helper functions for writing XMPP "XML", which is not real XML at all ;-( It's giving "XML" but make it cursed, honestly. The author uses XML::Writer and tunes it until it creates "XML" that most servers propably accept β all of the XMPP servers they tested should work (jabberd14, jabberd2, ejabberd, googletalk).
The author hopes the semantics of XML::Writer don't change much in the future, but if they do and you run into problems, please report them! π«Ά
Real talk: the whole "XML" concept of XMPP is fundamentally broken anyway. It's supposed to be a subset of XML, but a subset of XML productions is not XML. Strictly speaking, you need a special XMPP "XML" parser and writer to be 100% conformant.
On top of that, XMPP requires you to parse these partial "XML" documents. But a partial XML document is not well-formed β heck, it's not even a XML document! And a parser should bail out with an error. But XMPP doesn't care; it just relies on implementation dependend behaviour of chunked parsing modes for SAX parsing. This functionality isn't even specified by the XML recommendation in any way. The recommendation even says that it's undefined what happens if you process not-well-formed XML documents. Undefined behaviour, bestie!! π
But the author tries to be as XMPP "XML" conformant as possible β it should be around 99-100% β¨. But it's hard to say what XML is conformant, as the specifications of XMPP "XML" and XML are contradicting. For example, XMPP also says you only have to generate and accept UTF-8 encodings of XML, but the XML recommendation says that each parser has to accept UTF-8 and UTF-16. So, what do you do? Do you use a XML conformant parser or do you write your own? π
The author is using XML::Parser::Expat because expat knows how to parse broken (aka 'partial') "XML" documents, as XMPP requires. Another argument: if you capture a XMPP conversation to the end, and even if a </stream:stream> tag was captured, you wont have a valid XML document. The problem is that you have to resent a <stream> tag after TLS and SASL authentication each! Awww... I'm repeating myself. π
But well... AnyEvent::XMPP does its best with expat to cope with the fundamental brokeness of "XML" in XMPP. iconic behaviour, honestly π.
Back to the issue with "XML" generation: the author has discovered that many XMPP servers (eg. jabberd14 and ejabberd) have problems with XML namespaces. That's the reason why the namespace prefixes are assigned manually: the servers just don't accept validly namespaced XML. The draft 3921bis does even state that a client SHOULD generate a 'stream' prefix for the <stream> tag.
The author advises you to explicitly set the namespaces too if you generate "XML" for XMPP yourself, at least until all or most of the XMPP servers have been fixed. Which might take some years :-) And maybe will happen never. π°οΈ
And another note: as XMPP requires all predefined entity characters to be escaped in character data, you need a "XML" writer that will escape everything:
RFC 3920 - 11.1. Restrictions:
character data or attribute values containing unescaped characters
that map to the predefined entities (Section 4.6 therein);
such characters MUST be escaped
This means: you have to escape '>' in the character data. The author doesn't know whether XML::Writer does that. And honestly doesn't care much about this. XMPP is broken by design and there is barely time to write my own XML parsers and writers to suit their sick taste of "XML". (Do I repeat myself?) π«
The author would be happy if they finally say (in RFC3920): "XMPP is NOT XML. It's just XML-like, and some XML utilities allow you to process this kind of XML." π
π METHODS π
okay bestie, here's the whole method menu β every single one, no skips, no cap π«Ά
π new (%args)
this method takes these args:
π write_cb
the callback that gets called when an XML stanza was completely written and is ready for transfer. the first argument of the callback will be the character data to send to the socket.
And calls init.
π§ init
(Re)initializes the writer. cute little reset moment β¨
π¦ flush ()
this method flushes the internal write buffer and will invoke the write_cb callback. (see also new () above)
πΈ send_init_stream ($language, $domain, $namespace)
this method will generate a XMPP stream header. $domain has to be the domain of the server (or endpoint) we want to connect to.
$namespace is the namespace URI or the tag (from AnyEvent::XMPP::Namespaces) for the stream namespace. (This is used by AnyEvent::XMPP::Component to connect as component to a server). $namespace can also be undefined, in this case the "client" namespace will be used.
π« send_whitespace_ping
this method sends a single space to the server. literally one space, iconic lowkey π«Ά
π₯ send_handshake ($streamid, $secret)
this method sends a component handshake. please note that $secret must be XML escaped!
β οΈ bestie do not forget: $secret has to be XML escaped. no exceptions π
π send_end_of_stream
sends end of the stream.
π send_sasl_auth ($mechanisms, $user, $hostname, $pass)
this method sends the start of a SASL authentication. $mechanisms is an array reference, containing the mechanism names that are to be tried.
π send_sasl_response ($challenge)
this method generated the SASL authentication response to a $challenge. you must not call this method without calling send_sasl_auth () before.
π no skipping steps: callsend_sasl_auth ()first, thensend_sasl_response ($challenge). periodt.
π§ send_starttls
sends the starttls command to the server.
π send_iq ($id, $type, $create_cb, %attrs)
this method sends an IQ stanza of type $type (to be compliant only use: 'get', 'set', 'result' and 'error').
- If
$create_cbis a code reference it will be called with anXML::Writerinstance as first argument, which must be used to fill the IQ stanza. TheXML::Writeris in UNSAFE mode, so you can safely useraw()to write out XML. - If
$create_cbis a hash reference the hash will be used as key=>value arguments for the"simxml"function defined inAnyEvent::XMPP::Util."simxml"will then be used to generate the contents of the IQ stanza. (This is very convenient when you want to write the contents of stanzas in the code and don't want to build a DOM tree yourself...). - If
$create_cbis an array reference it's elements will be interpreted as single$create_cbargument (which can either be a hash reference or code reference themself) and executed sequentially. - If
$create_cbis undefined an empty tag will be generated.
Example:
$writer->send_iq ('newid', 'get', {
defns => 'version',
node => { name => 'query', ns => 'version' }
}, to => 'jabber.org')
%attrs should have further attributes for the IQ stanza tag. For example 'to' or 'from'. If the %attrs contain a 'lang' attribute it will be put into the 'xml' namespace. If the 'to' attribute contains an undef it will be omitted.
$id is the id to give this IQ stanza and is mandatory in this API.
Please note that all attribute values and character data will be filtered by filter_xml_chars (see also AnyEvent::XMPP::Util).
πΈ send_presence ($id, $type, $create_cb, %attrs)
sends a presence stanza.
$create_cb has the same meaning as for send_iq. %attrs will let you pass further optional arguments like 'to'.
$type is the type of the presence, which may be one of:
unavailable, subscribe, subscribed, unsubscribe, unsubscribed, probe, error
Or undef, in case you want to send a 'normal' presence. Or something completely different if you don't like the RFC 3921 :-)
%attrs contains further attributes for the presence tag or may contain one of the following exceptional keys:
- If
%attrscontains a'show'key: a child xml tag with that name will be generated with the value as the content, which should be one of'away','chat','dnd'and'xa'. If it contains an undefined value no such tag will be generated, which usually means that the'available'presence is meant. - If
%attrscontains a'status'key: a child xml tag with that name will be generated with the value as content. If the value of the'status'key is an hash reference the keys will be interpreted as language identifiers for thexml:langattribute of each status element. If one of these keys is the empty string''noxml:langattribute will be generated for it. The values will be the character content of the status tags. - If
%attrscontains a'priority'key: a child xml tag with that name will be generated with the value as content, which must be a number between-128and+127.
π Note: If$create_cbis undefined and one of the above attributes (show,statusorpriority) were given, the generates presence tag won't be empty.
Please note that all attribute values and character data will be filtered by filter_xml_chars (see also AnyEvent::XMPP::Util).
π¦ send_message ($id, $to, $type, $create_cb, %attrs)
sends a message stanza.
$to is the destination JID of the message. $type is the type of the message, and if $type is undefined it will default to 'chat'. $type must be one of the following: 'chat', 'error', 'groupchat', 'headline' or 'normal'.
$create_cb has the same meaning as in send_iq.
%attrs contains further attributes for the message tag or may contain one of the following exceptional keys:
- If
%attrscontains a'body'key: a child xml tag with that name will be generated with the value as content. If the value of the'body'key is an hash reference the keys will be interpreted as language identifiers for thexml:langattribute of each body element. If one of these keys is the empty string''noxml:langattribute will be generated for it. The values will be the character content of the body tags. - If
%attrscontains a'subject'key: a child xml tag with that name will be generated with the value as content. If the value of the'subject'key is an hash reference the keys will be interpreted as language identifiers for thexml:langattribute of each subject element. If one of these keys is the empty string''noxml:langattribute will be generated for it. The values will be the character content of the subject tags. - If
%attrscontains a'thread'key: a child xml tag with that name will be generated and the value will be the character content.
Please note that all attribute values and character data will be filtered by filter_xml_chars (see also AnyEvent::XMPP::Util).
π write_error_tag ($error_stanza_node, $error_type, $error)
$error_type is one of 'cancel', 'continue', 'modify', 'auth' and 'wait'. $error is the name of the error tag child element. If $error is one of the following:
'bad-request', 'conflict', 'feature-not-implemented', 'forbidden', 'gone',
'internal-server-error', 'item-not-found', 'jid-malformed', 'not-acceptable',
'not-allowed', 'not-authorized', 'payment-required', 'recipient-unavailable',
'redirect', 'registration-required', 'remote-server-not-found',
'remote-server-timeout', 'resource-constraint', 'service-unavailable',
'subscription-required', 'undefined-condition', 'unexpected-request'
then a default can be select for $error_type, and the argument can be undefined.
π Note: This method is currently a bit limited in the generation of the xml for the errors, if you need more please contact me.
β¨ AUTHOR β¨
Robin Redeker, "<elmex at ta-sa.org>", JID: "<elmex at jabber.org>"
π COPYRIGHT & LICENSE π
Copyright 2007, 2008 Robin Redeker, all rights reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
that's the whole page, bestie π this was perl v5.42.2, dated 2026-02-15 β go slay your XMPP stanzas, no cap β¨π
π¦ where this page comes from
- alpine 3.24: perl-anyevent-xmpp-doc 0.55-r1 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms