Automatically logging into a Lync conference on Linux

Hello, Habr!



For me, this phrase is akin to hello world, since I finally got to my first publication. I postponed this wonderful moment for a long time, since there was nothing to write about, but I also did not want to suck on what was already sucked up a lot of times. In general, for my first publication I wanted something original, useful to others and containing some sort of challenge and problem solving. And now I can share this. Now, first things first.



Introduction



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



When switching to the dark side of Linux, things got a little complicated: there is, of course, an entrance to the conference in Pidgin too, but for this you need to select the option to join the conference in the menu properties in your sip account and insert the conference link in the window that opens or enter the organizer name and conf id. And after some time I began to think: "Is it possible to somehow simplify this?" Yeah, you say, why the hell did you need it, I would have sat on Windows and wouldn’t have blown it.



Step 1. Research



“What a whim will go into the head - you won’t beat her out of it,” - said Nekrasov in his work “Who can live well in Russia”.



So, since the thought hit the head, after some time the first idea arose for implementation. It seemed simple - you need to intercept the call to meet.company.com/user/confid links - put the local process of the web application on 127.0.0.1 on your wheelbarrow and enter the static entry for the company domain through which in / etc / hosts in a conference pointing to localhost. Further, this web server should process the link that came to it and somehow transfer it into Pidgin (I’ll say right away that at this stage I didn’t have any idea how to give it to him at all). The solution, of course, smells like crutches, but we are programmers, crutches do not scare us (squeak).



Then by chance I somehow opened a link to an invitation to Google Chrome (and usually I always use Mozilla Firefox). And to my surprise, the web page looked completely different - there was no user data input form and immediately after entering the page there was a request to open something through xdg-open . For fun, 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 in order for such links to open? An autopsy reading the documentation showed that this is a graphical shell handler that helps launch associated applications with either the protocols for the uri scheme or certain types of files. Associations are configured through a mime-type mapping. So, we see that we are starting the search for a mapped application for uri scheme with the name lync15 and the link is passed to xdg-open, which in theory should pass it 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 open source world? That's right, we will write it ourselves.



Further immersion in the Linux world and especially in the study of how the graphical shell (desktop environment, DE) works, by the way I have it Xfce in Linux Mint, showed that applications and the mime-type associated with it are usually written directly in shortcut files with the extension .desktop. Well, why not, I create a simple application shortcut, which should simply launch the bash script and output the argument passed to it to the console, I will only give 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 launch xdg-open from the console with the same link that comes from the browser and ... bummer. Again he says that he cannot process the link.



As it turned out, I did not update the directory of the associated mime-type with my application. This is done with a simple command:



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





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



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



 bash -x xdg-open $url
      
      





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



Having run through the interiors of xdg-open, I found out that it analyzes various environmental parameters and passes control to either some tools for opening files / links specific to a particular DE, or it has a fallback in the form of the open_generic function



 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 cut a small hack here with the analysis of the passed argument, and if our specific substring lync15 is there , then we immediately pass control to the open_generic function.



Try number 3 and you think it worked? Yeah, now how. 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 very link passed as an argument.



This time it turned out to be the function is_file_url_or_path , which analyzes the link to the file: // file or the path to the file or something else. And the check did not work correctly due to the fact that our prefix (url scheme) has numbers, and the regular expression is checked only for a character set consisting of: alpha: dots and dashes. After consulting the rfc3986 standard for a uniform resource identifier, it became clear that this time Microsoft did not violate anything (although I had such a version). Just a character class: alpha: contains only letters of the Latin alphabet. I quickly change the regular check to alphanumeric. Done, you are delightful, everything finally starts up, control after all checks is given to our script application, our link is displayed on the console, everything is as it should. After that, I begin to suspect that all problems in exo-open are also due to the validation of the link format due to the numbers in the circuit. To test the hypothesis, I change the mime-type registration of the application to just the lync scheme 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 the link with lync15 exactly.



So, the first part of the path has been completed. We can intercept the link call and then we need to somehow process it and pass it inside Pidgin. In order to understand how it works internally when entering data using the link in the “join the conference” menu, I cloned the Sipe project repository and prepared to dive into the code again. But here, fortunately, I was attracted to the scripts in the contrib / dbus / directory:





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



Step 2. Implementing a handler for an auto-join



Since there are ready-made examples for the pearl, I decided to just use sipe-join-conference-with-uri.pl and modify it a bit for myself. I can write in pearl, so this did not cause any particular difficulties.



After testing the script separately, I entered its call into the lync.desktop file. And it was a victory! Upon entering the page of joining the conference and allowing the launch of xdg-open, the pop-up window of the conference from Pidgin opened automatically. How I rejoiced.

Encouraged by the success, I decided to do the same for my main browser, Mozilla Firefox. When entering through the fox, a page for authorization opens and at the very bottom there is a join button using office communicator . She attracted my attention. When you click on it in the browser, the link goes to:



 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 already passed it.



I quickly register my script application also for the conf uri-scheme and ... nothing happens. The browser continues to complain that there is no application that processes my links. At the same time, a call from the xdg-open console with parameters works fine.



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



 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 of course foo with conf):



 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 a line from the documentation catches your eye:

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


- Semen Semenych

- Ahh



We don’t click on the link, but simply the web page makes window.location change through javascript. I am writing a simple html file with a link to the conf protocol, open it in a browser, click on the link - Yos! A window opens with a question in which application you need to open our link and there we already have our Lync application in the list - we honestly registered it in all possible ways. There is a checkmark in the window “remember the choice and always open links in our application”, note, click ok. And this is the second victory - the conference window opens. At the same time, the opening of conferences already works not only when you click on the link, but also when switching from the desired page to join the conference.



Then I checked that deleting the network.protocol-handler.expose.conf parameters did not affect the protocol operation in the fox in any way. Links continued to work.



Conclusion



I uploaded all my achievements 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 best practices. I must say right away that I did everything only for my Linux Mint system, so some other distributions or desktops may not work in that version. Rather, I am even almost sure of this, because I patched only 1 function in xdg-open that relates only to my DE. If you want to add support for other systems or dextops, write me the pool requests in the github.



The implementation of the entire project took 1 evening.



References:






All Articles