sleekXMPP: Get list of looged in users on XMPP Server - xmpp

I am new to python & sleekxmpp scripting and would like to know how to pass this iq stanza (XEP-0133: Service administration - Get Online Users) using python (mainly the node in below stanza):
http://xmpp.org/extensions/xep-0133.html#get-online-users-list
<iq from='bard#shakespeare.lit/globe'
id='get-online-users-list-1'
to='shakespeare.lit'
type='set'
xml:lang='en'>
<command xmlns='http://jabber.org/protocol/commands'
action='execute'
node='http://jabber.org/protocol/admin#get-online-users-list'/>
</iq>
What I tried:
iq = self .make_iq_get(queryxmlns='http://jabber.org/protocol/commands', ito=self.domain, ifrom=self.jid, iq='')
response = iq.send()
print ('response = %s' % response)
Running above code in python is always resulting in IqError.
Can anyone please explain how to pass above iq stanza's xmlns, action and node information into make_iq_get ??
Please Help!!

Following code has solved my above problem:
1st line of code returns you a form to be filled, 2nd line returns a session id which is used in last line of code
iq = self['xep_0050'}.send_command(domain, "http://jabber.org/protocol/admin#get-online-users-list")
sessionid = iq['command']['sessionid']
form = self.xmpp.plugin['xep_0004'].make_form(ftype='submit')
field = form.add_field(
ftype='hidden',
type='hidden',
var='FORM_TYPE',
value=ADMIN)
field['type'] = 'hidden'
form.add_field(var='max_items', value='100')
print self['xep_0050'}.send_command(domain, "http://jabber.org/protocol/admin#get-online-users-list", sessionid=sessionid, payload=form)

Related

How to control tracking options and tags when using Mailgun's SMTP option (i.e. not using their API)

I’m using python to send emails using Mailgun’s SMTP server. I wish to use Mailgun’s builtin ability to tag my messages, and to track open and click events.
I know this can be done using Mailgun’s send message API, by adding headers like o:tag, o:tracking, o:tracking-clicks and o:tracking-opens (as explained here: https://documentation.mailgun.com/en/latest/api-sending.html#sending)
However, seeing as I'm the SMTP gateway and not the API, I’m trying to understand how to achieve the same result - emails that are tagged and fully tracked in Mailgun.
Any thoughts on how it can be done?
This is my little script at the moment:
message = MIMEMultipart("alternative")
message["Subject"] = "This is an email"
message["From"] = “<from email>”
message["To"] = “<to email>”
htmlpart = MIMEText("<html><body>email here!</body></html>", "html")
message.attach(htmlpart)
server = smtplib.SMTP_SSL(“<smtp server>”, 465)
server.ehlo()
server.login(“<username>”, “<password>”)
server.sendmail(from_addr=“<from email>”, to_addrs=“<to email>”, msg=message.as_string())
server.close()
Found it!
The following X-Mailgun headers can be added:
https://documentation.mailgun.com/en/latest/user_manual.html#sending-via-smtp
So my script would be:
message = MIMEMultipart("alternative")
message["Subject"] = "This is an email"
message["From"] = “<from email>”
message["To"] = “<to email>”
message["X-Mailgun-Tag"] = "<tag>"
message["X-Mailgun-Track"] = "yes"
message["X-Mailgun-Track-Clicks"] = "yes"
message["X-Mailgun-Track-Opens"] = "yes"
htmlpart = MIMEText("<html><body>email here!</body></html>", "html")
message.attach(htmlpart)
server = smtplib.SMTP_SSL(“<smtp server>”, 465)
server.ehlo()
server.login(“<username>”, “<password>”)
server.sendmail(from_addr=“<from email>”, to_addrs=“<to email>”, msg=message.as_string())
server.close()
Now my email is tagged (can be analysed on a tag level in Mailgun), and clicks are tracked.
Happy days!

xmpp ejabberd - query for user presence

Is there a way to query for user presence in XMPP, given that the user's subscription type is 'both'?
Since i am building for mobile platform, i have blocked all incoming presence stanzas using privacy list. In my use case, a user would be at least be subscribed to 500 users and processing these many presence stanzas would put a lot of stress on the mobile device.
So instead of processing all the user stanzas, i would like to get the presence for a user only when i query for it.
There is no such feature at the moment inside ejabberd, but that's definitely something you can develop as a plugin. You can write a plugin that will be handling http requests using HTTP webserver and do whatever processing and security check you want before answering with the user presence.
For future reference, i have managed to pull together some code(thanks to mod_last.erl) and build a module that lets you query for user presence. Suggestions & feedbacks will be highly appreciated.
-module(mod_query_presence).
-behaviour(gen_mod).
-export([start/2, stop/1,
process_sm_iq/3
]).
-include("ejabberd.hrl").
-include("jlib.hrl").
-include("logger.hrl").
-include("mod_privacy.hrl").
-define(NS_QUERY_PRESENCE, <<"jabber:iq:qpresence">>).
start(Host, Opts) ->
IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1,
one_queue),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
?NS_QUERY_PRESENCE, ?MODULE, process_sm_iq, IQDisc),
?INFO_MSG("Loading module 'mod_iqtest' v.01", []).
stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_QUERY_PRESENCE),
?INFO_MSG("Stoping module 'mod_iqtest' ", []).
process_sm_iq(From, To,
#iq{type = Type, sub_el = SubEl} = IQ) ->
case Type of
set ->
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
get ->
User = To#jid.luser,
Server = To#jid.lserver,
Resource = xml:get_tag_attr_s(list_to_binary("resource"), SubEl),
{Subscription, _Groups} =
ejabberd_hooks:run_fold(roster_get_jid_info, Server,
{none, []}, [User, Server, From]),
if (Subscription == both) or (Subscription == from) or
(From#jid.luser == To#jid.luser) and
(From#jid.lserver == To#jid.lserver) ->
UserListRecord =
ejabberd_hooks:run_fold(privacy_get_user_list, Server,
#userlist{}, [User, Server]),
case ejabberd_hooks:run_fold(privacy_check_packet,
Server, allow,
[User, Server, UserListRecord,
{To, From,
#xmlel{name = <<"presence">>,
attrs = [],
children = []}},
out])
of
allow -> get_presence(IQ, SubEl, User, Server, Resource);
deny ->
IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]}
end;
true ->
IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]}
end
end.
get_presence(IQ, SubEl, LUser, LServer, LResource) ->
case ejabberd_sm:get_session_pid(LUser, LServer, LResource) of
none ->
IQ#iq{type = error,
sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]};
Pid ->
{_U, _Resource, Status, StatusText} = ejabberd_c2s:get_presence(Pid),
IQ#iq{type = result,
sub_el =
[#xmlel{name = <<"query">>,
attrs =
[{<<"xmlns">>, ?NS_QUERY_PRESENCE},
{<<"status">>, Status},
{<<"StatusText">>, StatusText}],
children = []}]}
end.
IQ request format
<iq id='id' to='56876c654366178e0e75a8cd#192.168.1.150' type='get'>
<query xmlns='jabber:iq:qpresence' resource='Smack'/>
</iq>
IQ reply format if user is online
<iq from='56876c654366178e0e75a8cd#192.168.1.150' to='56876c654366178e0e75a8cd#192.168.1.150/Smack' id='last1' type='result'>
<query xmlns='jabber:iq:qpresence' status='dnd' StatusText='YO'/>
</iq>
If the user is not online, you will get an service-unavailable error.

How to log in to a website with urllib?

I am trying to log on this website: http://www.broadinstitute.org/cmap/index.jsp. I am using python 3.3 on Windows. I followed this answer https://stackoverflow.com/a/2910487/651779. My code:
import http.cookiejar
import urllib
url = 'http://www.broadinstitute.org/cmap/index.jsp'
values = {'j_username' : 'username',
'j_password' : 'password'}
data = urllib.parse.urlencode(values)
binary_data = data.encode('ascii')
cookies = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(
urllib.request.HTTPRedirectHandler(),
urllib.request.HTTPHandler(debuglevel=0),
urllib.request.HTTPSHandler(debuglevel=0),
urllib.request.HTTPCookieProcessor(cookies))
response = opener.open(url, binary_data)
the_page = response.read()
http_headers = response.info()
It runs without erros, however the html in the_page is just the log in page. How can I log onto this page?
The site is using a JSESSIONID cookie to create session since HTTP requests are stateless. When you're making your request, you're not getting that session id first.
I sniffed a session to log into that site using Fiddler and found that the POST is made to a different URL, but it has that JSESSIONID cookie set. So you need to make a get to the URL first, capture that cookie using the cookiehandler, then POST to this URL:
post_url = 'http://www.broadinstitute.org/cmap/j_security_check'
You don't need to save the HTTP GET request at all, you can simply call opener.open(url), then in your code change the response line to this:
response = opener.open(post_url, binary_data)
Also the payload was missing the submit method. Here's the whole thing with the changes I suggest:
import http.cookiejar
import urllib
get_url = 'http://www.broadinstitute.org/cmap/index.jsp'
post_url = 'http://www.broadinstitute.org/cmap/j_security_check'
values = urllib.parse.urlencode({'j_username': <MYCOOLUSERNAME>,
'j_password': <MYCOOLPASSSWORD>,
'submit': 'sign in'})
payload = bytes(values, 'ascii')
cj = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(
urllib.request.HTTPRedirectHandler(),
urllib.request.HTTPHandler(debuglevel=0),
urllib.request.HTTPSHandler(debuglevel=0),
urllib.request.HTTPCookieProcessor(cj))
opener.open(get_url) #First call to capture the JSESSIONID
resp = opener.open(post_url, payload)
resp_html = resp.read()
resp_headers = resp.info()
Any other requests using the opener you created will re-use that cookie and you should be able to freely navigate the site.

fulljid is empty after connection to BOSH service with XMPHP

I am trying to pre-bind an XMPP session via XMPHP and pass the rid/sid/jid to a strophe client to attach to the session.
connection code here:
$conn = new CIRCUIT_BOSH('server.com', 7070, $username, $pass, $resource, 'server.com', $printlog=true, $loglevel=XMPPHP_Log::LEVEL_VERBOSE);
$conn->autoSubscribe();
try{
$conn->connect('http://xmpp.server.com/http-bind', 1, true);
$log->lwrite('Connected!');
}catch(XMPPHP_Exception $e){
die($e->getMessage());
}
I am getting the rid and sid but the fulljid in the $conn object stays empty and I cant see a session started on my openfire admin console.
If I create the jid manually by using the given resource and passing jid/rid/sid to strophe to use in attach, I get the ATTACHED status and I see calls from the client to the BOSH ip but I still dont see a session and I cant use the connection.
Strophe Client Code:
Called on document ready:
var sid = $.cookie('sid');
var rid = $.cookie('rid');
var jid = $.cookie('jid');
$(document).trigger('attach', {
sid: sid,
rid: rid,
jid: jid,
});
$(document).bind('attach', function (ev, data) {
var conn = new Strophe.Connection(
"http://xmpp.server.com/http-bind");
conn.attach(data.jid, data.sid, data.rid, function (status) {
if (status === Strophe.Status.CONNECTED) {
$(document).trigger('connected');
} else if (status === Strophe.Status.DISCONNECTED) {
$(document).trigger('disconnected');
} else if (status === Strophe.Status.ATTACHED){
$(document).trigger('attached');
}
});
Object.connection = conn;
});
I think the problem starts on the XMPPHP side which is not creating the session properly.
'attached' is triggered but never 'connected', is status 'connected' supposed to be sent?
What am I missing?
Ok, solved, I saw that XMPPHP lib didn't create a session at all on the openfire server, so I wrote a simple test for the XMPP class which was good and created the session, and for the XMPP_BOSH class that didn't manage create one. Then I saw the issue report here: http://code.google.com/p/xmpphp/issues/detail?id=47 comment no.9 worked, it fixed the issue by copying the processUntil() function from the XMLStream.php to BOSH.php, still can't figure out why this is working. Then I found I had an overlapping bug also with some of the passwords set for users on the openfire server. These passwords contained these ! # % ^ characters, for some reason the XMPP_BOSH is sending the password corrupted or changed so I got Auth Failed exception. Changing the password fixed the issue and I can now attach to the session XMPPHP created with the Strophe.js library.

Using Soap in magento

I'm trying to follow the information about how to use soap in magento, but always get same message in error.log
If any one experience something similar, that could give me some tip, it will be welcome.
"PHP Fatal error: SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://www.site.com/index.php/api/?wsdl' : failed to load external entity "http://www.site.com/index.php/api/?wsdl"\n in /var/www/test.php on line 1"
$client = new SoapClient('http://www.site.com/api/?wsdl');
$session = $client->login('apiUser', 'apiKey');
$result = $client->call($session, 'somestuff.method');
$result = $client->call($session, 'somestuff.method', 'arg1');
$result = $client->call($session, 'somestuff.method', array('arg1', 'arg2', 'arg3'));
$result = $client->multiCall($session, array(
array('somestuff.method'),
array('somestuff.method', 'arg1'),
array('somestuff.method', array('arg1', 'arg2'))
));
// If you don't need the session anymore
$client->endSession($session);
where you have www.site.com in your SOAP code, replace it with localhost or whatever the correct URL is for your server. You'll also need to replace somestuff.method with real objects and methods as per the Magento documentation