ejabberd: Manipulate bookmarks with ejabberdctl - xmpp

I am currently writing shell code that pushes data from LDAP into ejabberd, concerning MUC rooms. The last step I need to do is add some MUC rooms to users' bookmarks so they are auto-joined in their clients. There does not seem to be a module for that like there is in Prosody.
So I assume I need to mnipulate the users' private XML storage, in particular the storage:bookmarks part. I can get all existing bookmarks with:
ejabberdctl private_get user host storage storage:bookmarks
Then, there is ejabberdctl private_set, but I do not really understand it. From what I get, it seems that I need to replace the entire storage element at once, with old and new entries merged together.
Is there another way to add conference sub-elements to the node, or add bookmarks in some other way?
I tried to use private_set, but it seems to break on spaces in the element string. I tried escaping them in all possible ways, but to no avail.

OK, I found out for sure that adding new conferences to bookmarks requires re-uploading the entire bookmark storage set. That means the correct way is using private_get as shown in the question, then modify the XML to add a new entry and then use private_set to re-upload all of it.
As to the issue with spaces: Erlang shell (that's what ejabberdctl is) needs another level of quoting with single quotes, so some XML would become "'<storage xmlns="storage:bookmarks"><conference jid=…'" and so on in a shell argument.
You can find a shell script that does this and much more with ejabberdctl here: https://www.teckids.org/gitweb/?p=verein.git;a=blob;f=sysadmin/scripts/teckids-ejmaint

There are two standards for MUC bookmarks in XMPP. The old standard, XEP-0049, uses Private XML storage that can be modified with the private_set command. But the more recent standard is to store the bookmarks in PEP: XEP-0223
Dominik George's answer works for the old standard; for the new PEP method you can use:
sudo ./ejabberdctl send_stanza user#domain.tld user#domain.tld '
<iq type="set" id="asdf">
<pubsub xmlns="http://jabber.org/protocol/pubsub">
<publish node="storage:bookmarks">
<item id="current">
<storage xmlns="storage:bookmarks">
<conference jid="room#conference.domain.tld" autojoin="true" name="name">
<nick>nick</nick>
</conference>
</storage>
</item>
</publish>
<publish-options>
<x xmlns="jabber:x:data" type="submit">
<field var="FORM_TYPE" type="hidden">
<value>http://jabber.org/protocol/pubsub#publish-options</value>
</field>
<field var="pubsub#access_model">
<value>whitelist</value>
</field>
</x>
</publish-options>
</pubsub>
</iq>
'
This command is also accessible using the REST API: https://docs.ejabberd.im/developer/ejabberd-api/admin-api/#send-stanza

Related

Can I read the maxOccurs property for a segment from the stream being processed?

I am trying to create a mapping file for a fixed length file that contains multiple repeating segments. Problem is, that more than one of these segments are repeated an indefinite number of times, which is not supported by beanio for flat files. I understand, that there is a good reason for this, as beanio can do only so much guesswork about how often a segment repeats.
However the number of repetitions for each segment is present in the file, at a position before the repeating segments occur, so I am trying to figure out whether there is a way to read that number from the stream and then populate the "minOccurs" and "maxOccurs" properties for the following segment with the correct value.
Basically my mapping file looks like:
<beanio>
<stream name="employeeFile" format="fixedlength">
<record name="record1" class="example.Record1">
<field name="field1" length="10"/>
<field name="field2" length="2"/>
<field name="length1" length="2"/>
<segment name="list1" collection="list" minOccurs="1" maxOccurs="unbounded" class="example.List1">
...
</segment>
<field name="length2" length="2"/>
<segment name="list2" collection="list" minOccurs="1" maxOccurs="unbounded" class="example.List2">
...
</segment>
</record>
</stream>
</beanio>
I now need some way to use the value of fields length1 and length2 as "maxOccurs" property in the segments. I am fairly certain that there is no "official" way to get this behavior, but I have so far failed to come up with an even remotely elegant solution for this.
An idea I had was to create a procedure that loads the number of repetitions for each segment from the file and then doing a search-replace on the mapping file, before loading this in beanio, however this seems like a very complicated way of doing things.
Thanks,
Sönke
Found the answer myself. I was reading the beanio reference documentation for version 2.0, not 2.1 which introduced the feature I am looking for.
The reference document states:
If a field repeats a fixed number of times based on a preceding field
in the same record, the occursRef attribute can be used to identify
the name of the controlling field. If the controlling field is not
bound to a separate property of its parent bean object, be sure to
specify ignore="true". The following mapping file shows how to
configure the accounts field occurrences to be dependent on the
numberOfAccounts field. If desired, minOccurs and maxOccurs may still
be specified to validate the referenced field occurrences value.
So one can use:
<field name="accounts" type="int" collection="list" occursRef="numberOfAccounts" />
to get the intended result.
I don't think this property works with xml streams, as it is not really needed here. I accidentally tried to add this in a mapping file and got an exception instead of a proper error message.

CruiseControl.net - configuration of users / email at server level

We have around 50 projects configured in CruiseControl.net, and each is individually configured to send an email out on completion / change / whatever.
Is there any way of configuring the user / email address list at a higher (e.g. server) level? I've searched the documentation, and googled for any clues, but I can't find anything.
I need to update who gets sent emails, and updating 50 files isn't a sustainable or ideal solution!
Thanks.
I'm not sure this the exact case of yours, but might work for you too. I have separated all the email settings into separate file, and then use the include in project configuration.
So it looks sth like this:
File: EmailPublisher.xml
<cb:config-template xmlns:cb="urn:ccnet.config.builder">
<email from="notification#example.com" mailhost="mailhost.example.com" mailport="587" includeDetails="true" mailhostUsername="username"
mailhostPassword="mailPwd" useSSL="TRUE" replyto="admin#example.com">
<description>Sending email notifications</description>
<groups>
<group name="developers">
<notifications>
<notificationType>Failed</notificationType>
<notificationType>Fixed</notificationType>
</notifications>
</group>
<group name="buildmaster">
<notifications>
<notificationType>Always</notificationType>
</notifications>
</group>
</groups>
<converters>
<regexConverter find="$" replace="#example.com" />
</converters>
<modifierNotificationTypes>
<NotificationType>Failed</NotificationType>
<NotificationType>Fixed</NotificationType>
</modifierNotificationTypes>
</email>
</cb:config-template>
And then in the project configuration in publishers section:
<!-- email publisher -->
<cb:include href="EmailPublisher.xml"/>
The downside is that you need to have the same configuration for each project, or alternatively use several include files (which starts to cause the same issue again).
Anyway, it seems to work for our team rather well.
[EDIT]
You can also go one step further, and for example only include the users list from separate file, and have the notifications settings applied separately for project.
You could use variables/substitutions like this: $(admins), $(programmers), $(ProductAScrumMaster), $(ProductBEntireTeam), $(HolyCrapTheMachineFriedEmailEveryone) and the like. You can append or nest them as well if you need combinations.
This post might be more useful as an example - it has lots more detail: Using dynamic parameters in email publisher subjectSettings block with CruiseControl.Net

How to use the same WSDL message defenitions in multiple functions?

I had some errors about invalid definitions coming from Visual Studio 2010 when trying to call a WSDL defined function. The problem was that you cannot use the same message definition in two seperate functions. So I have to create multiple message definitions while they do the same.
For instance:
<message name="Hi">
<part name="input" type="xsd:string">
</message>
<message name="Say_hi_back">
<part name="return" type="xsd:string">
</message>
<message name="I_hate_you">
<part name="return" type="xsd:string">
</message>
<portType name="DataPort">
<operation name="sayHello">
<input message="tns:Hi"/>
<output message="tns:Say_hi_back"/>
</operation>
<operation name="sayIHateYou">
<input message="tns:Hi"/>
<output message="tns:I_hate_you"/>
</operation>
</portType>
Now calling either one of the functions will give you an error. Unless I add a Hi2 with exactly the same parts and change one of the input messages in the operation definitions to tns:Hi2.
Why is this? It makes no sense. I'm building up a service where I'm going to have to add the customerID to all the functions I'm going to build. One function for getting the appointments, one for the payments, one for all. This means I'm going to have to copy the message definition like 10 times and name them getCustomerID*N*.
Also a lot of times I'm going to have to have multiple input parameters. Say for instance someone wants to have all appointments between date x and date y. (And this goes for all the information that is stored like payments etc.) While I only need one message with an int, a date and a date. I'm going to have to write a huge document.
So my question is if there is any other way to do this. I've only been working with WSDL for two days and those were two days full of problems and deceiving 'victories'. Where you solve one problem only to find out that opened the gate to the next.
Thanks. :)
You are creating a WSDL reflecting an RPC style as evidenced by the 'type' attributes in the message part definitions. I am not entirely sure why this would cause a problem with VS, but the RPC style has gone out of vogue in favor of the document style (the modern versions of some tools have dropped support for RPC altogether).
You may have better results using the document style (document/literal/wrapped is our standard). You can read a little more about style differences here (http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/).
The changes required are not too complex and this site (http://wso2.org/library/knowledge-base/convert-rpc-encoded-wsdl-document-literal-wrapped-wsdl) gives some help, although I think the author flipped his rpc vs literal output definitions in the #Output message section.

How to create an oauth_signature when some parameters are in the content body in XML

I am building an REST-ful API and I want to implement 2-legged authentication with OAuth. I feel I have a good grasp of the fundamentals, i.e. constructing the oauth_signature based on the request parameters as mentioned here http://oauth.net/core/1.0/#rfc.section.9.1.1 and the use of a nonce and a timestamp.
However if you are doing POST and the body content is XML which contains your parameters what is the best practice for encoding those into your oauth_signature.
For example if I have an end point of http://burger.me/order/ with an accepted method of POST, and the content body is as follows:-
<order>
<item name="Big Mac" count="1" />
<item name="Whopper" count="2" />
<item name="Zinger Tower" count="1" />
</order>
How does that affect the construction of the oauth_signature? Do I just append the entire xml string or ignore it? I am not sure of the accepted best practice in this example.
You can either choose to not sign the body (if you're providing over SSL you could probably skip it). Or you can choose to use the oauth_body_hash extension to the OAuth Spec.
Documentation here: http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/drafts/4/spec.html

What is the best way to update data for an iPhone app?

I am developing an application for iPhone and one part of it deals with a list of currencies and daily exchange rates. I am using SQLite to store all these rates.
Now I came to the part where I want to make the update part of my database with the new exchange rates.
The first thought was make a request to a server with a specific date and to read back an XML containing something like:
<date value="2010-10-04">
<currency name="EUR" rate="xxx" />
<currency name="USD" rate="yyy" />
<currency name="GBP" rate="zzz" />
........
</date>
<date value="2010-10-05">
<currency name="EUR" rate="xxx" />
<currency name="USD" rate="yyy" />
<currency name="GBP" rate="zzz" />
........
</date>
But now I was thinking isn't it better to make my own format, something like:
#|2010-10-04#EURxxx#USDyyy#GBPzzz#|2010-10-05#EURxxx#USDyyy#GBPzzz##
The separator will be #. Known that always the date takes 11 characters and starts with | and currency code takes 3 characters, I can search the rate until I will find a # sign.
Because I want to send as little data as I can I think this second approach will be better than the usual XML, even if I reduce the XML to:
<d v="2010-10-04">
<c name="EUR" r="xxx" />
<c name="USD" r="yyy" />
<c name="GBP" r="zzz" />
........
</d>
<d v="2010-10-05">
<c name="EUR" r="xxx" />
<c name="USD" r="yyy" />
<c name="GBP" r="zzz" />
........
</d>
What are your pro & cons for this?
XML is easier to read and parse. Unless you're fetching a zillion currencies and daily rates a day, the # of bytes shouldn't be an issue.
JSON format would split the difference between a proprietary format and a standard format. It is somewhat less verbose than XML and has the flexibility and maintainability vodkhang rightly expects.
The pros:
As you already stated, it is shorter, faster to retrieve.
Faster to parse as well
The cons:
If you develop the server side and the other developer on the mobile side, then he may get confused when there are no meanings
It is hard to scale when you have more and more attributes and if you delete or change some attributes, you have to go over all codes to change it.
CFPropertyList is pretty good if you're using PHP as your server-side language.
Easy to integrate with your server code and has built in support in iOS (e.g. an NSDictionary can be created directly from a plist file).
Link: http://code.google.com/p/cfpropertylist/