Automatically sign in to Lync conference calls on Linux

Hey Habr!

For me, this phrase is akin to hello world, since I finally got to my first publication. I put off this wonderful moment for a long time, since there was nothing to write about, and I didn’t want to suck on what had already been sucked on a bunch of times. In general, for my first publication, I wanted something original, useful to others and containing some kind of challenge and problem solving. And now I can share this. Now about everything in order.

Entry

It all started with the fact that some time ago I rolled Linux Mint on my working computer. Many of you probably know that Pidgin with the Sipe plugin is quite a suitable replacement for Microsoft Lync (now called Skype for business) for Linux systems. Due to the specifics of my work, I often have to participate in sip-conferences, and when I was a Windows user, entering conferences was elementary: we receive an invitation by mail, click on the login link, and we are ready inside.

When switching to the dark side of Linux, everything became somewhat more complicated: of course, there is also an entrance to conferences in Pidgin, but for this you need to select the join conference item in the menu in the properties of your sip account and in the window that opens, insert a link to the conference or enter the name of the organizer and conf id. And after some time, I began to think: “is it possible to simplify it somehow?” Yeah, you say, why the hell did you need it, would you sit on Windows and not blow your mustache.

Step 1 Research

“What a whim gets stuck in the head - you won’t knock it out of there with a stake,” Nekrasov said in his work “Who Lives Well in Rus'.”

So, since the thought got into my head, after some time the first idea for implementation arose. Everything seemed simple - you need to intercept access to links meet.company.com/user/confid - put a local web application process on your wheelbarrow at 127.0.0.1 and in /etc/hosts add a static entry for the company domain through which you enter the conference, pointing to localhost. Next, this web server must process the link that came to it and somehow transfer it inside Pidgin (I’ll say right away that at this stage I still had no idea how to give it to him at all). The solution, of course, smacks of crutches, but we are programmers, crutches do not scare us (shutka).

Then, by accident, I somehow opened the invitation link in Google Chrome (and I usually always use Mozilla Firefox). And to my surprise, the web page looked completely different - there was no form for entering user data, and immediately after entering the page, a request was made to open something through xdg-open. For the sake of interest, I click "yes" and an error message appears - the link lync15:confjoin?url=https://meet.company.com/user/confid cannot be opened. Hmm. What kind of xdg-open is this and what does it need to open such links? An autopsy reading the documentation revealed that it is a GUI handler that helps launch associated applications either with uri scheme protocols or certain file types. Associations are configured via mime-type mapping. So, we see that we start searching for a matched application for uri scheme with the name lync15 and the link is passed to xdg-open, which, in theory, should pass it on to some application that is responsible for this type of links. Which we, of course, do not have in the system. And if not, how do they act in the world of open source? That's right, we'll write it ourselves.

Further immersion in the world of Linux and especially in the study of how the graphical shell (desktop environment, DE) works, by the way, I have Xfce in Linux Mint, showed that applications and the mime-type associated with it are usually written directly in shortcut files with the .desktop extension. Well, why not, I create a simple application shortcut, which should just run the bash script and output the argument passed to it to the console, I give only the shortcut file itself:

[Desktop Entry]
Name=Lync
Exec=/usr/local/bin/lync.sh %u
Type=Application
Terminal=false
Categories=Network;InstantMessaging;
MimeType=x-scheme-handler/lync15;

I run xdg-open from the console, passing in the same link that comes from the browser, and… bummer. Again says that he can not process the link.

As it turns out, I didn't update the associated mime-type directory with my application. This is done with a simple command:

xdg-mime default lync.desktop x-scheme-handler/lync15

which just edits the file ~/.config/mimeapps.list.

Attempt number 2 with a call to xdg-open - and again failure. Nothing, difficulties do not scare us, but only stir up interest. And armed with all the power of bash (i.e. tracing), we dive headlong into debugging. It's important to note here that xdg-open is just a shell script.

bash -x xdg-open $url

Analyzing the output after the trace, it becomes a little clear that further control is transferred to exo open. And this is already a binary file and it is already more difficult to understand why it returns an unsuccessful return code when passing a reference to it in an argument.

Having run through the internals of xdg-open, I found out that it analyzes various environment parameters and transfers control further either to some tools for opening file links specific to a particular DE, or it has a fallback function open_generic

open_xfce()
{
if exo-open --help 2>/dev/null 1>&2; then
exo-open "$1"
elif gio help open 2>/dev/null 1>&2; then
gio open "$1"
elif gvfs-open --help 2>/dev/null 1>&2; then
gvfs-open "$1"
else
open_generic "$1"
fi

if [ $? -eq 0 ]; then
exit_success
else
exit_failure_operation_failed
fi
}

I quickly stick a little hack here with the analysis of the passed argument and if our specific substring is there lync15:, then we immediately transfer control to the function open_generic.

Attempt number 3 and you think it worked? Yep, how about now. But the error message has already changed, this is already progress - now he told me that the file was not found and in the form of a file he wrote me the same link passed as an argument.

This time it turned out to be a function is_file_url_or_path, which analyzes the file link passed to the input file:// or the path to the file, or something else. And the validation didn't work correctly because our prefix (url scheme) has numbers, and the regular expression only checks for a character set consisting of :alpha: dots and dashes. After consultation with rfc3986 standard for uniform resource identifier it became clear that this time Microsoft did not violate anything (although I had such a version). It's just that the :alpha: character class contains only letters of the Latin alphabet. I quickly change the regular expression check to alphanumeric. Done, you are amazing, everything finally starts, after all the checks, control is given to our script application, our link is displayed on the console, everything is as it should be. After that, I begin to suspect that all the problems with exo-open are also due to the validation of the link format due to the numbers in the scheme. To test the hypothesis, I change the mime-type registration of the application to a simple scheme Lync and voila - everything works without redefining the open_xfce function. But this will not help us in any way, because the web page for entering the conference creates exactly a link with lync15.

So, the first part of the journey has been completed. We can intercept the link call and then it needs to be processed somehow and passed inside Pidgin. In order to understand how it works internally when entering data through the link in the “join the conference” menu, I cloned the git repository of the Sipe project and got ready to dive into the code again. But here I was fortunately attracted by the scripts in the directory contrib/dbus/:

  • sipe-join-conference-with-uri.pl
  • sipe-join-conference-with-organizer-and-id.pl
  • sipe-call-phone-number.pl
  • SipeHelper.pm

It turns out that the Sipe plugin is available for interaction via dbus (desktop bus) and inside the scripts there are directly examples of joining a conference by link, either through the name of the organizer and conf-id, or you can initiate a call via sip. This is exactly what we were missing.

Step 2: Implementing the AutoJoin Handler

Since there are ready-made examples for pearl, I decided to just use sipe-join-conference-with-uri.pl and tweak it a bit. I know how to write in pearl, so it didn’t cause any particular difficulties.

After testing the script separately, I entered its call into a file lync.desktop. And it was a victory! When entering the conference join page and allowing xdg-open to run, the conference popup window from Pidgin opened automatically. How I rejoiced.
Encouraged by the success, I decided to do the same for my main browser, Mozilla Firefox. When you enter through the fox, a page for authorization opens and at the very bottom there is a button join using office communicator. It was she who attracted my attention. When you click on it in the browser, you go to the address:

conf:sip:{user};gruu;opaque=app:conf:focus:id:{conf-id}%3Frequired-media=audio

to which he kindly tells me that he does not know how to open it and, perhaps, I do not have an associated application for such a protocol. Well, we've already been through this.

I quickly register my script application for the uri scheme as well conf and… nothing happens. The browser keeps complaining that there is no application that handles my links. At the same time, calling xdg-open from the console with parameters works fine.

“Set custom protocol handler in firefox” - I went online with this question. After going through several discussions on stackoverflow (and where without it), it seems that the answer was found. You need to create a special parameter in about: config (replacing foo with conf of course):

network.protocol-handler.expose.foo = false

We create, open the link and ... it was not there. The browser, as if nothing had happened, says that it does not know our application.

I read the official documentation on registering the protocol with Mozilla, there is an option to register associations in the gnome desktop itself (replacing foo with conf, of course):

gconftool-2 -s /desktop/gnome/url-handlers/foo/command '/path/to/app %s' --type String
gconftool-2 -s /desktop/gnome/url-handlers/foo/enabled --type Boolean true

I register, open the browser ... and again the beard.

Here's a line from the documentation:

Next time you click a link of protocol-type foo you will be asked which application to open it with.

— Semyon Semenych
— ahh

We do not click on the link, but simply the web page changes window.location via javascript. I write a simple html file with a link to the conf protocol, open it in the browser, click on the link - Yos! A window opens asking in which application we need to open our link, and there we already have our Lync application in the list - we honestly registered it in all possible ways. In the same place in the window there is a checkmark “remember the choice and always open links in our application”, mark it, press ok. And this is the second victory - the conference window opens. At the same time, the opening of conferences already works and not only when clicking on the link, but also when moving from the page we need to join the conference.

Then I checked, deleting the parameters network.protocol-handler.expose.conf did not affect the operation of the protocol in the fox. The links continued to work.

Conclusion

I uploaded all my developments to the github repository, links to all resources will be at the end of the article.
It will be interesting for me to get feedback from those who want to use my developments. I’ll note right away that I did all the development only for my Linux Mint system, so some other distributions or desktops may not work in that version. Or rather, I'm even almost sure of this, because I patched only 1 function in xdg-open, related only to my DE. If you want to add support for other systems or desktops, write me a pull request on github.

The whole project took 1 evening.

Links:

Source: habr.com

Add a comment