[
  {
    "path": ".gitignore",
    "content": "*~\n*Makefile\n*Makefile.in\n*Makefile.in.in\n*.la\n*.lo\n*.log\n.deps\n.libs\nlibtool\nconfig.*\nconfigure\n/ABOUT-NLS\nautom4te*\n*.swp\naclocal.m4\ncompile\ndepcomp\nGITVERSION\ninstall-sh\nintltool-extract*\nintltool-merge*\nintltool-update*\n*.bz2\n*.gz\n*.xz\nltmain.sh\n/m4/\nmissing\nmkinstalldirs\n/INSTALL\npixmaps/*/im-sipe.*\npo/Makevars.template\npo/POTFILES\npo/Rules-quot\npo/stamp-it\npo/*.header\npo/*.sed\npo/*.sin\n*.gmo\nsrc/*/*.o\nsrc/adium/adium-frameworks\nsrc/adium/SIPEAdiumPlugin.xcodeproj/project.pbxproj-e\nsrc/adium/SIPEAdiumPlugin.xcodeproj/project.xcworkspace/\nsrc/adium/SIPEAdiumPlugin.xcodeproj/xcuserdata/\nsrc/core/sipe-rtf.c\nsrc/core/*_tests\nsrc/core/sipe_ntlm_analyzer\nsrc/core/sipe_tls_analyzer\nsrc/core/sipe_tls_tester\nsrc/purple/tests\nsrc/purple/tests_load\nsrc/telepathy/telepathy-sipe\nsrc/telepathy/data/org.freedesktop.Telepathy.ConnectionManager.sipe.service\nstamp-h1\nsiplcs.vcxproj.user\ntest-driver\nylwrap\n*.trs\n*.DS_Store\nadium/SIPEAdiumPlugin.xcodeproj/project.xcworkspace/*\nadium/SIPEAdiumPlugin.xcodeproj/xcuserdata/*\n"
  },
  {
    "path": ".tx/config",
    "content": "[main]\nhost = https://www.transifex.com\n\n[pidgin-sipe.mob]\nfile_filter = po/<lang>.po\nsource_file = po/pidgin-sipe.pot\nsource_lang = en\n\n"
  },
  {
    "path": "AUTHORS",
    "content": "Maintainers:\n\nStefan Becker <chemobejk at gmail dot com>\nJakub Adam <jakub dot adam at ktknet dot cz>\n\nRetired Maintainers:\n\nJochen De Smet <jochen dot siplcs at leahnim dot org> (Miranda port)\nMichael Lamb <mlamb1976 at yahoo dot com> (Adium port)\nAnibal Avelar <debianmx at gmail dot com>\nTomáš Hrabčík <tomas dot hrabcik at tieto dot com>\npier11 <pier11 at operamail dot com>\nGabriel Burt  <gburt at novell dot com>\nDaniel Beichl <daniel_beichl at gmx dot net>\n\nOther Contributors:\n\nJakub 'jimmac' Steiner <jimmac at gmail dot com> (icon artwork)\nHarris Kauffman <harris dot kauffman at gmail dot com> (Adium port)\nMatt Meissner <meissnem at gmail dot com> (Adium port)\nMichael Steffens <michael_steffens at gmx dot net>\nCarl Seutter <cseutter at sbcglobal dot net>\nSean E. Millichamp <sean at bruenor dot org>\nAndrew Rechenberg <therealdjflux at gmail dot com>\nMatthias Scharrer <matthias dot scharrer at gmail dot com>\nGarett Shulman <garett dot shulman at gmail dot com>\nTyson Vinson <lornoss at gmail dot com>\nAndrew Schenck <lane_andrew at hotmail dot com>\nIvan Frade <ivan at kustu at (none)>\nJay (Rhyas) <biteme at scream at com>\nJohn Beranek <john at redux dot org dot uk>\nDavid Woodhouse <David dot Woodhouse at intel dot com>\nEdmondas Girkantas <eg at fbsd dot lt>\nPeter Fales\nKyle Hubert <khubert at lottle dot net>\nAndrey Vaynberger <platerx at gmail dot com>\nMichael Olbrich <m dot olbrich at pengutronix dot de>\n\nBased on the initial SIP/SIMPLE gaim protocol plugin by:\n\nThomas Butter <butter at uni-mannheim dot de>\n\nTranslators:\n\nPlease check the \"Translators:\" section in the po/*.po files.\n"
  },
  {
    "path": "COPYING",
    "content": "\t\t    GNU GENERAL PUBLIC LICENSE\n\t\t       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc.,\n 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n\t\t\t    Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Lesser General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n\t\t    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n\t\t\t    NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n\t\t     END OF TERMS AND CONDITIONS\n\n\t    How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License along\n    with this program; if not, write to the Free Software Foundation, Inc.,\n    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program is interactive, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    Gnomovision version 69, Copyright (C) year name of author\n    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, the commands you use may\nbe called something other than `show w' and `show c'; they could even be\nmouse-clicks or menu items--whatever suits your program.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n  <signature of Ty Coon>, 1 April 1989\n  Ty Coon, President of Vice\n\nThis General Public License does not permit incorporating your program into\nproprietary programs.  If your program is a subroutine library, you may\nconsider it more useful to permit linking proprietary applications with the\nlibrary.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.\n"
  },
  {
    "path": "ChangeLog",
    "content": "version 1.25.1 \"???\" (????-??-??)\n\t- Fixed #359: Incorrect build due to false negative configure checks (Stefan Becker)\n\t- refactor --enable-quality-check (Stefan Becker)\n\nversion 1.25.0 \"Buddy Idle Time, RTF\" (2019-10-12)\n\t- Feature #107: Provide idle start time for a buddy (Stefan Becker)\n\t- Feature #77: RTF support (incoming) (Stefan Becker)\n\t  * the code only extracts plain text from incoming RTF\n\t- Fixed #358: FTBFS with glib-2.0 >= 2.62.0 (Stefan Becker)\n\t- Fixed #350: Inconsistent parsing of From:/To: headers (Stefan Becker)\n\t- raise BR telepathy-glib >= 0.24.0 (Stefan Becker)\n\t- switch from GPLv2+ to SPDX identifier GPL-2.0-or-later (Stefan Becker)\n\nversion 1.24.0 \"Application Sharing II\" (2018-11-10)\n\t- Feature #104: Use user agent also for HTTP (Stefan Becker)\n\t- Feature #6: Application Sharing Server (Jakub Adam)\n\t  * requires freerdp-shadow2\n\t- Fixed #343: Build fails on FreeBSD\n\t- add timeout handling for media streams (Alaoui Youness)\n\t- update AppStream handling (Jakub Adam, Stefan Becker)\n\t- fix missing localisation in some code modules (Stefan Becker)\n\t- debug log improvements (Stefan Becker)\n\nversion 1.23.3 \"Bug Fixes III\" (2018-08-20)\n\t- appshare: fix black screen with Remmina v1.2.0-rcgit.27 (Jakub Adam)\n\t- various minor fixes (Jakub Adam, Michael Olbrich)\n\t- fix compilation errors with libpurple 2.14.0 & GCC 8.0 (Jakub Adam, Stefan Becker)\n\t- mingw: update fetch script to Pidgin 2.13.0 (Stefan Becker)\n\nversion 1.23.2 \"Bug Fixes II\" (2018-03-10)\n\t- fix some HTTP requests that were not sent (Jakub Adam, Stefan Becker)\n\nversion 1.23.1 \"Bug Fixes I\" (2018-02-25)\n\t- Fixed #338: Incorrect port 0 for IPv6 socket on Windows (Stefan Becker)\n\t- Fixed #337: Duplicate candidates in SDP (Jakub Adam, Stefan Becker)\n\t- Fixed #336: Lync autodiscover does not follow user redirect (Stefan Becker)\n\t- media: unconditionally ignore multichannel codecs (Jakub Adam)\n\t- updated translations: Turkish (tr)\n\nversion 1.23.0 \"D-Bus, IPv6, OS X 10.11+\" (2017-10-28)\n\t- Feature #101: Mac OS X 10.13 OpenSSL support (Stefan Becker)\n\t- Feature #100: Extend libpurple D-Bus interface (Stefan Becker)\n\t- Feature #99: IPv6 addresses in SIP & SDP messages (Stefan Becker)\n\t- Feature #96: Support for OS X 10.11+ SDK (Stefan Becker)\n\t- don't load buddy photos from unknown sites by default (Jakub Adam, Stefan Becker)\n\t  * custom web URIs pose a security risk as they may be abused\n\t  * users can override this behaviour in the account settings\n\t  * Office365 accounts should not be affected by this change\n\t- add support for GMime 3.0 API (Stefan Becker)\n\t- raise BR glib-2.0 >= 2.18.0 (Stefan Becker)\n\t- raise BR purple >= 2.7.0 (Stefan Becker)\n\t- drop support for GMime 2.4 (Stefan Becker)\n\t- drop support for gstreamer-0.10 (Stefan Becker)\n\nversion 1.22.1 \"Bug Fixes I\" (2017-06-11)\n\t- Fixed #320: Multiple client detection broken (Stefan Becker)\n\t- speed up Lync Autodiscover by using AccessLocation (Andrey Vaynberger)\n\t- adium: update build instructions for Xcode 7.x or newer (Stefan Becker)\n\t  * the build environment used for releases 1.22.0 or older (Xcode 6.x\n\t    on OS X 10.11) is no longer available to the project\n\t  * releases starting with 1.22.1 will use Xcode 8.x on macOS 10.12\n\t  * build target continues to be OS X 10.9\n\t- purple: avoid rare SSL read deadlock (Stefan Becker)\n\t- various minor fixes (Michael Olbrich)\n\t- crypto: make code compile with OpenSSL 1.1.0 (Stefan Becker)\n\t- drop references to Reuters Messaging (Stefan Becker)\n\t- updated translations: Lithuanian (lt), Russian (ru), Swedish (sv), Turkish (tr)\n\nversion 1.22.0 \"Application Sharing, Lync Autodiscover & Logging\" (2017-02-01)\n\t- Feature #93: Support for Lync Autodiscover (Stefan Becker)\n\t- Feature #6: Application Sharing Viewer (Jakub Adam)\n\t  * requires libpurple >= 2.12.0\n\t  * needs an external RDP client - remmina and xfreerdp are supported\n\t- Fixed #315: Crash when contact list is empty (Stefan Becker)\n\t- Fixed #314: sipe login problems with long pw (Stefan Becker)\n\t- separate logging and debugging output (Stefan Becker)\n\t  * logging is always shown, e.g. in the Pidgin debug window\n\t  * full message debugging now requires PURPLE_UNSAFE_DEBUG=1\n\t- new translations: Greek (el), Lithuanian (lt)\n\nversion 1.21.1 \"Bug Fixes I\" (2016-05-28)\n\t- various bug fixes in media support (Jakub Adam)\n\t- configure no longer ignores CFLAGS/LDFLAGS/LIBS (Stefan Becker)\n\nversion 1.21.0 \"Lync File Transfer\" (2016-04-23)\n\t- Feature #91: Support embedded XML as buddy photo URL (Stefan Becker)\n\t- Feature #90: Add AppStream metadata file (Jiri Eischmann, Stefan Becker)\n\t- Feature #89: Improve \"Join scheduled conference\" dialog  (Stefan Becker)\n\t- Feature #87: Support multiple HTTP cookies (Stefan Becker)\n\t- Feature #85: XML raw extract should ignore name space (Stefan Becker)\n\t- Fixed #311: Crash when SIP transport becomes invalid (Stefan Becker)\n\t- Fixed #293: Mandatory wsa:MessageID node missing (Stefan Becker)\n\t- add support for Lync File Transfer protocol (Jakub Adam)\n\t  * requires libpurple >= 2.12.0\n\t  * Lync FT will be used for sending files when Lync 2013 is detected\n\t- add build options to \"About SIPE plugin\" message (Stefan Becker)\n\nversion 1.20.1 \"Bug Fixes I\" (2015-10-24)\n\t- add support for another type of ADFS response (Stefan Becker)\n\t- improve configure check for back-ported features (Stefan Becker, Jakub Adam)\n\t- updated translations: French (fr), Russian (ru)\n\nversion 1.20.0 \"SRTP, Conference URL & TLS-DSK Improvements\" (2015-08-29)\n\t- Feature #82: Parse HTML from Lync conference URL (Stefan Becker)\n\t- Feature #69: SRTP Support (Jakub Adam)\n\t  * requires libpurple >= 3.0.0\n\t- Fixed #285: Office365 rejects RC4 in TLS-DSK (Stefan Becker)\n\t  * added support for AES-128/256-CBC\n\nversion 1.19.1 \"Bug Fixes I\" (2015-04-04)\n\t- Fixed #278: 488 error after libnice upgrade (Jakub Adam)\n\t- fix SIP re-authentication timeout to be max. 8 hours (Stefan Becker)\n\nversion 1.19.0 \"Auto Authentication, MFA & Search Improvements\" (2015-02-07)\n\t- Feature #80: Move parsing of login name (Stefan Becker)\n\t- Feature #79: support for Adium group chat bookmarks (David Matz, Stefan Becker)\n\t- Feature #78: Support searching for SIP ID (Stefan Becker)\n\t- Feature #76: ADFS can't always be used (Stefan Becker)\n\t  * for accounts that have Multi-Factor Authentication (MFA) enabled\n\t- Feature #73: Support buddy photos from contactCard (Stefan Becker)\n\t- Feature #65: Fall back from Kerberos to NTLM (Stefan Becker)\n\t- Fixed #277: Raised contact names (Stefan Becker)\n\t- Fixed #240: Corrupted HTTP response crashes SIPE (Stefan Becker)\n\t- fix calendar state machine when EWS URL is set (Stefan Becker)\n\t- fall back to [MS-DLX] BasicSearch to improve search experience (Stefan Becker, various)\n\t- implement search functionality for UCS (Stefan Becker)\n\t- adium: add chat room list UI (David Matz)\n\t- adium: fix duplicate debug log messages (Stefan Becker)\n\t- support for libnice TCP mode (Youness Alaoul, Jakub Adam)\n\t- refactor CCCP request code (Jakub Adam)\n\nversion 1.18.5 \"Bug Fixes V\" (2014-12-29)\n\t- Fixed #276: Redundant \"const\" breaks build with clang (Stefan Becker)\n\t- Fixed #269: purple idle-away converted to Away (Stefan Becker)\n\t- svc: use authuser for RealmInfo request (Stefan Becker)\n\t- adium: add release checking script (Stefan Becker)\n\t- mingw: update fetch script to Pidgin 2.10.11 (Stefan Becker)\n\t- updated translations: Italian (it), Swedish (sv)\n\nversion 1.18.4 \"Bug Fixes IV\" (2014-10-18)\n\t- Fixed #263: ADFS fails when user and login name differ (Stefan Becker)\n\t- Fixed #262: Adium: SIPE doesn't auto- or re-connect (Stefan Becker)\n\t- fixed memory leaks (Stefan Becker)\n\t- fixed processing of presence publish event response (John Zhang, Stefan Becker)\n\t  * fixes a longstanding issue that the Pidgin user status sometimes\n\t    didn't switch back to \"Available\" after the end of a meeting\n\nversion 1.18.3 \"Bug Fixes III\" (2014-08-16)\n\t- Fixed #259: HTML response to EWS autodiscover triggers libxml2 assert (Stefan Becker)\n\t- Fixed #258: V&V call gets rejected when IPv6 is enabled (Stefan Becker, Jakub Adam)\n\t- Fixed #257: Windows 7: SIPE crashes after a minute (Stefan Becker)\n\t- mingw: improve crash information reporting (Stefan Becker)\n\nversion 1.18.2 \"Bug Fixes II\" (2014-06-07)\n\t- Fixed #255: Crash when PersistentChat sends BYE instead of response (Stefan Becker)\n\t- Fixed #248: Remove libpurple SSL configure check (Stefan Becker)\n\t- Fixed #245: \"Unable to resolve DNS SRV record\" error when joining conference (Stefan Becker)\n\t- Fixed #241: Adium filters \":\" from \"sip:\" (Stefan Becker)\n\t- Fixed #210: Conference call ends with error message (for real this time, Jakub Adam)\n\t- ews: extract settings also from type EXPR (Stefan Becker)\n\t- ucs: honor user specified email URL (Stefan Becker)\n\t- adium: fix compilation on OS X 10.7 (Stefan Becker)\n\t- updated Transifex URLs (Stefan Becker)\n\t- updated translations: Hindi (hi), Telugu (te)\n\nversion 1.18.1 \"Bug Fixes I\" (2014-04-12)\n\t- Fixed #238: False \"not delivered\" in conference (Stefan Becker)\n\t- Fixed #237: HTML escaping not removed from URL (Stefan Becker)\n\t- Fixed #210: Conference call ends with error message (Jakub Adam)\n\t- fix endless loop with failed HTTP Basic authentication (Stefan Becker)\n\t- fix crash when gstreamer nice plugin is missing (Stefan Becker, Jakub Adam)\n\t- fix EWS autodiscover for some Office 365 users (Stefan Becker)\n\t- purple: fix missing \"Copy to\" in buddy menu (Stefan Becker)\n\t- purple/adium: ignore empty search values (Stefan Becker)\n\t- adium: fix group chat UI (Stefan Becker)\n\t- adium: implement BEAST mitigations for 10.8.5 (Michael Lamb)\n\t- add indication when user is connected from a mobile device (Harris Kauffman)\n\t- updated translations: Chinese (zh_CN), Portuguese (pt)\n\nversion 1.18.0 \"Adium, GSS-NTLMSSP & OpenSSL\" (2014-01-11)\n\t- Feature #71: Add support for EWS Autodiscover redirection (Stefan Becker)\n\t- Feature #69: Add UI support for (group) chats (Michael Lamb)\n\t  * NOTE: Adium does not have an UI to fetch the room list\n\t- Feature #64: Add support for GSS-NTLMSSP (Stefan Becker)\n\t  * sip-sec-krb5.c module has been renamed to sip-sec-gssapi.c\n\t  * if gssapi/gssapi_ntlmssp.h is detected then sip-sec-ntlm.c will\n\t    be disabled and NTLM will be handled by sip-sec-gssapi.c instead\n\t  * NOTE: at the time of this writing the user has to set up\n\t          GSS-NTLMSSP by hand on his system, i.e. /etc/gss/mech\n\t- Fixed #227: Adium client doesn't save email option settings (Harris P. Kauffman)\n\t- Fixed #216: SIPE stops working on Mavericks (Stefan Becker, Michael Lamb)\n\t  * add an UI option to disable SSL BEAST mitigations\n\t  * NOTE: requires Adium 1.5.10\n\t- Fixed #197: Account stays in connecting stage (Harris P. Kauffman)\n\t- cleanup for sip-sec Kerberos & SSPI modules (Stefan Becker)\n\t  * replace old TGT hack with gss_acquire_cred_with_password()\n\t  * clean up Kerberos detection in configure\n\t  * remove special case handling; code is more straight-forward now\n\t  * thanks to David Woodhouse and Simo Sorce for the GSSAPI information\n\t- implement internal keepalive handling (Stefan Becker)\n\t- implement crypto backend based on OpenSSL (Stefan Becker)\n\t- adium: Xcode project files update (Michael Lamb)\n\t- adium: replace NSS crypto backend with OpenSSL (Stefan Becker)\n\t  * NOTE: please make sure to read the updated build instructions!\n\nversion 1.17.3 \"Bug Fixes III\" (2013-12-11)\n\t- Fixed #225: HTTP re-authentication with NTLM fails (Stefan Becker)\n\t- Fixed #222: SIPE crashes when groupchat session expires (Stefan Becker)\n\t- fix UCS Persona key extraction (Stefan Becker)\n\nversion 1.17.2 \"Bug Fixes II\" (2013-11-30)\n\t- Fixed #214: Typing notification does not always work (Stefan Becker)\n\t  * reverted one change which caused problems for some users\n\t- Fixed #222: SIPE crashes when groupchat session expires (Stefan Becker)\n\t- updated translations: Romanian (ro)\n\nversion 1.17.1 \"Bug Fixes I\" (2013-11-16)\n\t- Fixed #215: Password not entity encoded in WSSE element (Stefan Becker)\n\t- Fixed #214: Typing notification does not always work (Stefan Becker)\n\t- accept alternatives for webticket timestamp/keydata (Stefan Becker)\n\t- adium: add \"don't publish calendar\" to account UI (Stefan Becker)\n\t- contrib: add SSL BEAST mitigation patch for Adium (Stefan Becker)\n\t- updated translations: French (fr)\n\nversion 1.17.0 \"Lync 2013\" (2013-09-21)\n\t- Feature #62: Support for Lync 2013 Unified Contact Store (Stefan Becker)\n\t- Feature #59: Support for Lync 2013 Persistent Chats (Stefan Becker)\n\t- Fixed #211: Status \"away\" or \"busy\" incorrectly mapped to \"Invisible\" (Michael Lamb)\n\t- Fixed #209: group chat doesn't like HTML (Stefan Becker)\n\t- Fixed #200: OCS archiving system blocks audio/video connection (Jakub Adam)\n\t- Fixed #187: Duplicate messages in group chat (Stefan Becker)\n\t- Fixed #184: Duplicate users showing in Group Chat (Stefan Becker)\n\t- fix EWS autodiscover for Office 365 (Stefan Becker)\n\t- add support for group chat history (Stefan Becker)\n\t- add support for buddy photos on Lync 2013 (Stefan Becker)\n\nversion 1.16.1 \"Bug Fixes I\" (2013-07-13)\n\t- Feature #66: Windows DLL version information (Stefan Becker)\n\t- fix call failure when host has multiple IP addresses (Jakub Adam)\n\t- fix buddy list handling after moving to Lync 2013 (Stefan Becker)\n\t  * Lync 2013 migrates buddy list to Unified Contact Store (UCS)\n\t  * NOTE: modifying the buddy list is *NOT* supported yet!\n\t- crash fixes for new HTTP stack (Stefan Becker)\n\nversion 1.16.0 \"HTTP Rewrite & Subscription Fixes\" (2013-06-14)\n\t- Feature #58: Implement Digest authentication scheme for SIP Proxy Authentication (Stefan Becker)\n\t- Fixed #196: Useragent value not forwarded to core (Michael Lamb)\n\t- Fixed #193: Pidgin Status changes stop working (Stefan Becker)\n\t- Fixed #186: Users appear offline when they are not (Stefan Becker)\n\t- fix kinit-less use case with krb5 >= 1.11 (Stefan Becker)\n\t- rewritten HTTP stack from scratch (Stefan Becker)\n\t  * cleaner, layered and hopefully less error-prone implementation\n\t  * HTTP stack internals no longer exposed to user code\n\t  * reduced network traffic and less SSL handshakes by utilizing HTTP/1.1\n\t    connection keep alive for multiple HTTP requests to the same host\n\t- switch purple backend to deferred destruction approach (Stefan Becker)\n\t  * Pidgin should no longer crash at connection close, even in corner cases\n\t- add menu entry to make a call with a phone number (Jakub Adam)\n\t- some progress on telepathy backend (Stefan Becker)\n\t  * add TLS certificate accept/reject user interaction\n\t  * add \"Single Sign-On\" & \"Don't Publish Calendar\" account options\n\nversion 1.15.1 \"Bug Fixes I\" (2013-04-07)\n\t- NOTE: SIPE SourceForge project got updated. Because of this all bug\n\t        and feature request numbers have changed.\n\t- Fixed #190: SIP 407 response rejected with invalid message signature (Stefan Becker)\n\t- Fixed #189: Adium SIPE plugin vs. libpurple linking issues (Michael Lamb)\n\t- fixed free-after-use issue that caused crashes for some users (Stefan Becker)\n\t- fixed broken NTLM fallback in Negotiate (Stefan Becker)\n\t- fixed subscriptions expiration by subscribing again after re-authentication (Stefan Becker)\n\t- allow different user name and login for Office 365 authentication (Stefan Becker)\n\t- add SIPE version & git commit ID to debug log (Stefan Becker)\n\t- added valgrind log analyzer script (Stefan Becker)\n\t- added NTLM message anaylzer (Stefan Becker)\n\t- updated translations: Hungarion (hu), Romanian (ro)\n\t- updated Adium port (Michael Lamb, Harris P. Kauffman)\n\nversion 1.15.0 \"Authentication & Autodiscovery Update\" (2013-03-09)\n\t- Feature #3578135: Support Kerberos for HTTP(S) authentication w/o SSPI (Stefan Becker)\n\t  * effective for all platforms that support --with-krb5\n\t  * this triggered a series of cleanup & simplification changes and\n\t    functionality & memory leak fixes in the sip-sec modules\n\t  * special thanks to Jarek Polok for the logs and testing\n\t- Feature #3594094: Add HTTPS to autodiscover probe (Stefan Becker)\n\t- Feature #3607040: Simple button to disable calendar integration (Stefan Becker)\n\t- Fixed #3603228: Crash on 1.14.1 when connecting to server (Stefan Becker)\n\t- Fixed #3604671: sip uri with apostrophe is not valid (Stefan Becker)\n\t- fixed HTTP redirect crash (Stefan Becker)\n\t- unified Single Sign-On handling in all places (Stefan Becker)\n\t  * if SSO is enabled then \"Login\" & \"Password\" settings are ignored\n\t  * SSO is now off by default for new accounts\n\t  * NOTE: if you do *NOT* use SSO, then be sure to disable it in the\n\t          \"Advanced\" tab of the account settings after updating!\n\t- added implementation for HTTP \"WWW-Authenticate: Negotiate\" scheme (Stefan Becker)\n\t  * effective for all platforms that support --with-krb5\n\t  * it will try Kerberos first, then fall back to NTLM\n\t  * valid Kerberos Single Sign-On setup will be detected automatically\n\t  * setup for a mixed Kerberos/NTLM HTTP environment:\n\t    - login name:     DOMAIN\\account\n\t    - password:       domain password\n\t    - authentication: Kerberos\n\t    - Single Sign-On: OFF(!)          (see above)\n\t- enabled TLS-DSK support in Windows SSPI version\n\t- TLS-DSK: don't ask for password if SSPI or Kerberos are compiled in\n\t- Farstream 0.1.1 compatibility fix (Jakub Adam)\n\t- support conf:sip: meeting URIs (Jakub Adam)\n\t- updated Adium port (Michael Lamb)\n\nversion 1.14.1 \"Bug Fixes I\" (2012-12-26)\n\t- Feature #3578132: Kerberos configuration should be passwordless (Stefan Becker)\n\t  * purple: non Single Sign-on users are asked for the password again\n\t- bug & memory leak fixes in sipe-buddy.c (Jakub Adam)\n\nversion 1.14.0 \"Buddy photo & ADFS support, Web Ticket Optimizations\" (2012-12-16)\n\t- Feature #3585364: Add support for Web Ticket authentication using ADFS (Stefan Becker)\n\t  * special thanks to user bhakta79 for the hard work taking logs\n\t- Feature #3578132: Kerberos configuration should be passwordless (Stefan Becker)\n\t- Fixed #3580212: Connection drops after a few hours (Stefan Becker)\n        - add support for buddy photos (Jakub Adam)\n\t- add support for call to Audio Test Service (Jakub Adam)\n\t- initial implementation for telepathy backend (Stefan Becker)\n\t  * nothing much to see for end users yet...\n\t- reduce Web Ticket traffic by queueing requests & caching tickets (Stefan Becker)\n\t- update OBS packaging information for Debian (Stefan Becker)\n        - various minor bug & build fixes\n\nversion 1.13.3 \"Bug Fixes III\" (2012-08-19)\n\t- Fixed #3537084: OpenBSD build issue (Stefan Becker)\n\t- Fixed #3543294: Support Lync 2010 meet URLs (Jakub Adam)\n\t- revert to legacy MSOC protocol on Lync FT invitation (Jakub Adam)\n\t- fix broken busy->available status switch (Stefan Becker)\n\t- updated translations: Portuguese (pt)\n\nversion 1.13.2 \"Bug Fixes II\" (2012-06-10)\n\t- tls: fix buffer overrun (Oleksandr Hryshchuk, Stefan Becker)\n\t- win32: fix TCP connections (Stefan Becker)\n\t- nsis: fix broken locale installation (Stefan Becker)\n\t- updated translations: French (fr)\n\t- various build fixes (Stefan Becker, Jakub Adam)\n\nversion 1.13.1 \"Bug Fixes I\" (2012-04-09)\n\t- detect incompatible encryption level with Lync (Jakub Adam)\n\t- purple: add URI validity check to Add Buddy callback (Stefan Becker)\n\t- new translations: Romanian (ro), Turkish (tr)\n\t- various build fixes (Stefan Becker)\n\nversion 1.13.0 \"Lync & Office365\" (2012-03-14)\n\t- added [MS-SIPAE] TLS-DSK authentication scheme (Stefan Becker)\n\t  * TLS-DSK has been introduced in Lync\n\t  * mandatory for Office365 accounts\n\t  * also works for non-public Lync installations\n\t  * does not work yet with SSPI on Windows\n\t- added [MS-DLX] based Get Info/Contact Search (Stefan Becker)\n\t  * [MS-PRES] SIP-Based Active Directory Search is disabled in Lync\n\t- added experimental media TCP transport (Jakub Adam)\n\t- make it compile against the latest purple 3.0.x API (Stefan Becker)\n\t- make it compile against the latest glib2 2.31.x API (Stefan Becker)\n\t- completed cleanup: core no longer requires libpurple (Stefan Becker)\n\t- refactored crypto code, ie. NSS can replaced if necessary (Stefan Becker)\n\t- sipe-domino.c is no longer built under UNIX to remove dead code (Stefan Becker)\n\t- restricted XXX_CFLAGS to modules that need them (Stefan Becker)\n\t- NSS is now a mandatory build requirement (Stefan Becker)\n\t- decoupled SSPI from HAVE_LIBKRB5 flag. New flag is HAVE_SSPI (Stefan Becker)\n\t- OBS mingw packages now use SSPI instead of NTLM (Stefan Becker)\n\t- added NSIS package generation to OBS mingw packages (Stefan Becker)\n\t- removed kopete backend. KDE is moving to telepathy (Stefan Becker)\n\t- added MinGW cross-compilation on Linux instructions (Stefan Becker)\n\nversion 1.12.0 \"Group Chat\" (2011-08-29)\n\t- Feature #3064877: Add support for OCS2007R2 Group Chat (Stefan Becker)\n\t- Feature #3311026: Support for HTTP/1.1 Transfer-Encoding: chunked (Stefan Becker)\n\t- Fixed #2834758: First NTLM signature check after startup fails (Stefan Becker)\n\t- Fixed #3082602: Crash on Autodiscover (Stefan Becker)\n\t- Fixed #3090663: Re-authentication fails (Stefan Becker)\n\t- Fixed #3092324: Core dump in \"make check\" (psfales)\n\t- Fixed #3130915: Failed to authenticate to server (Stefan Becker)\n\t- Fixed #3148124: sipe segfaults during login on Solaris (Jakub Adam)\n\t- Fixed #3150482: \"configure --with-vv\" test uses wrong include (Stefan Becker)\n\t- Fixed #3156430: Messages not Delivered (rwinchsf, Stefan Becker)\n\t- Fixed #3161273: Lost Connection Gives No Error Message (rwinchsf, Stefan Becker)\n\t- Fixed #3198585: Extra line breaks (Stefan Becker)\n\t- Fixed #3267073: False \"could not be delivered\" errors (sort of..., Stefan Becker)\n\t- Fixed #3399007: Crash when sipe_cal_working_hours->days_of_week is NULL (Stefan Becker)\n\t- Patch #3091490: Make 1.11.0 Compile on FreeBSD (jprather)\n\t- Patch #3108246: Patch for better windows installer (archrival, galiven)\n\t- add random Ms-Conversation-ID to INVITE (Jakub Adam)\n\t- fix parsing of P-Asserted-Identity header (Jakub Adam)\n\t- added MS TURN support (Jakub Adam)\n\t- fix crash on zero length password in NTLM (Vladimir Ushakov)\n\t- implement timeouts for SIP request. Used for REGISTER (Stefan Becker)\n\t- more work on Voice & Video call support (Jakub Adam)\n\t- make it compile against the purple 2.8.x & 3.0.x APIs (Stefan Becker)\n\t- more internal changes to prepare for non-purple backends (Stefan Becker)\n\t- added integration for transifex.net update (Stefan Becker)\n\t- configure improvements for 64-bit: use libdir, gsize/size_t compatibility (Stefan Becker)\n\t- update compiler warnings configuration for all build platforms (Stefan Becker)\n\t- updated Adium port (Matthew Duggan)\n\t- mingw build updates (Harris P. Kauffman, Stefan Becker)\n\t- added miranda port (Jochen De Smet)\n\t- added mingw to OpenSUSE Build Service configuration (Stefan Becker)\n\nversion 1.11.2 \"Hot fixes II\" (2010-11-02)\n\t- Revert \"mingw: add missing purple-notify.c to build\" (Anibal Avelar)\n\t- Sipe-sign: fix parsing of P-Asserted-Identity header (Jakub Adam)\n\t- Fixed memory leaks (Stefan Becker)\n\t- Fix #3090663: Re-authentication fails (Stefan Becker)\n\t- Fix #3090663: Re-authentication fails (2nd attempt) (Stefan Becker)\n\t- Fix #3090663: Re-authentication fails (3rd attempt) (Stefan Becker)\n\t- Fix #3090663: Re-authentication fails (4th attempt) (Stefan Becker)\n \t- Apply patch #3091490: Make 1.11.0 Compile on FreeBSD (jprather)\n\t- Fix #3092324: Core dump in \"make check\" (Stefan Becker)\n\nversion 1.11.1 \"Hot fixes\" (2010-10-24)\n\t- mingw: add missing purple-notify.c to build (Stefan Becker)\n\t- Fix for bug #2834758: First NTLM signature check after startup fails\n\t- purple: fix memory leak in sipe_backend_transport_connect() error path\n\t- Fix for bug #3082602: Crash on Autodiscover (Stefan Becker)\n\t- configure: use libdir & datadir instead of prefix + path (Stefan Becker)\n\t- configure: update 32-bit vs. 64-bit header conflict test (Stefan Becker)\n\t- debian: build stability fix in post-install (Stefan Becker)\n\nversion 1.11.0 \"Lotus Domino/Calendar & Voice Call\" (2010-10-04)\n\t- Feature #2859239: Voice call support (Jakub Adam)\n\t  * requires updated versions of libnice, farsight & pidgin\n\t  * only unencrypted calls as SRTP support is missing in farsight\n\t- Feature #2945346: Lotus Notes/Domino Calendar integration (pier11):\n\t  * Sipe can now retrieve calendar data (Meeting schedule/subject/\n\t    location) from a web-enabled Lotus Domino server and publish it to\n\t    OCS2007/LCS2005 as availability information.\n\t  * Example: \"Calendar: Currently Busy. Free at 11:30\".\n\t  * Team members (contacts with access level Team) will be able to see\n\t    information about our current meeting (subject & location) (OCS2007).\n\t  * First calendar update is scheduled 1 minute after connect,\n\t  * Subsequent calendar updates happen in 30 minute intervals.\n\t  * Manual calendar update can be triggered using the following menu:\n\t\t   Accounts->{SIPE_ACCOUNT}->\"Republish Calendar\"\n\t  * Though Domino integration can work without any additional settings\n\t    in account configuration (on Windows), there are options to manually\n\t    provide Domino Services URL and email address/password if it's\n\t    different from SIP URI/Password settings on Basic tab.\n\t- Fixed #2971422: idle check for OCS2005 presence case (Stefan Becker)\n\t- Fixed #2982424: krb5 build errors on FreeBSD (Stefan Becker)\n\t- Fixed #2997639: pidgin crash after accepting cert (Stefan Becker)\n\t- Fixed #3001523: Cancelling a long pending file transfer crashes Pidgin (Jakub Adam)\n\t- Fixed #3002993: Group Name issues with ampersand (Stefan Becker)\n\t- Fixed #3029228: Calendar published at/with incorrect time (Stefan Becker)\n\t- Fixed #3029929: Crash with outlook 2k3 Calendar (Stefan Becker)\n\t- Fix logout from OCS (Jakub Adam)\n\t- Implement workaround for buddy list menu memory leaks (Stefan Becker)\n\t- Dropped UDP transport support (Stefan Becker)\n\t- Rewrote TCP & TLS transport support (Stefan Becker)\n\t- HTTP improvements: GET, cookies (pier11)\n\t- Alternative crypt/digest implementation based on NSS (pier11)\n\t- Rewrote message debug log and implemented an analyzer script for it (Stefan Becker)\n\t- More internal changes to prepare for non-purple backends (Stefan Becker)\n\t- New translation: Dutch (Flemish) 'nl' (fieona, ridiekel)\n\t- New translation: Swedish 'sv' (Rijad)\n\t- Added translations 'ar' 'hu' 'ja' 'ko' 'sv' 'zh_TW' submitted by Novell\n\t- New build option: nss/mozilla-nss/microb-engine-nss for non-purple backends\n\t- Add build option for kopete backend (Stefan Becker)\n\t- mingw build using standard approach, i.e. with auto* tools. (pier11)\n\t- Updated Adium port (Emanuele Zattin)\n\nversion 1.10.1 \"Bugfix release\" (2010-06-27)\n\t- Fix broken sipe_ht_equals_nick(); the broken code has been in the 1.10.0 release. As it affects the buddy list it could be the root cause for some of the \"buddy appears offline\" reports. (Stefan Becker)\n\t- Make it compile against the final purple 2.7.0 API; (Stefan Becker)\n\nversion 1.10.0 \"Access Levels\" (2010-04-04)\n\t- Feature #2823160: Access Levels (2007+ environment). The functionality is available through contact's context menu \"Access level\" and also presented on contact's tooltip. Current individual access level is marked with star (*), current group access level is marked with equals sign (=). (pier11)\n\t- Feature #2957811: add support for \"automaton\" class (Stefan Becker)\n\t- Feature #2972823: fail on in-line variable declarations (Stefan Becker)\n\t- Fixed #2971422: handle OCS 2005 idiosyncrasy of varying SIP URI case (pier11)\n\t- Fixed #2981563: Authentication protocol v4 - invalid signature of some incoming messages containing P-Asserted-Identity or P-Preferred-Identity with uppercased SIP or TEL in URI. (pier11)\n\t- Fixed publication/\"409 Conflict\" endless looping (Stefan Becker, pier11)\n\t- Prepare for Pidgin 2.7.0 (Stefan Becker, pier11)\n\t- Windows build updated to gtk+2.14, gettext 0.17, libxml2 2.7.4, gcc 4.4 (pier11)\n\t- Added SVG icon artwork (Jakub 'jimmac' Steiner)\n\t- Many changes to configure script. Be sure to look at \"configure --help\"! (Stefan Becker)\n\t- Many internal changes to prepare for non-purple backends (Stefan Becker)\n\t- New build requirements: libxml2, glib-2.0 >= 2.12.0\n\t- New build option: gmime-2.4 >= 2.4.16 or gmime-2.6 >= 2.5.2 for non-purple backends\n\nversion 1.9.1 \"Hot fixes\" (2010-03-16)\n\t- Fixed #2969327: Kerberos authentication always fails on *nix platforms (pier11)\n\t- Fixed #2968287: Authentication failure in scenario when director server is Office Communications Server 2007 or above and home server is Live Communications Server 2005 (pier11)\n\t- Send BYE when response to IM message is 408/480/481 (Stefan Becker)\n\t- Re-enable offline status to be user settable (Stefan Becker)\n\nversion 1.9.0 \"File transfer & NTLMv2\" (2010-03-10)\n***** Important Security Update for *nix users *****\n\t- Contributed File transfer functionality. File encryption is supported. (Jakub Adam, Tomáš Hrabčík)\n\t- NTLMv2 and NTLMv2 Session Security support (pier11)\n\t- Implemented SIP Authentication Extensions protocol version 4 and 3 (pier11)\n\t- Adoption for commercial UNIX - HP/UX, Irix, Solaris - big endian fixes and build improvements (Peter Fales, Stefan Becker)\n\t- Packaged for Maemo platform (Nokia N900, etc.) at Maemo.org. Works with Pidgin from the same site. (Stefan Becker)\n\t- Adoption of file transfer for Windows build (pier11)\n\t- Official Debian package files in contrib (Anibal Avelar)\n\t- another shot at presence update problems (Stefan Becker)\n\t- fix crash caused by uninitialized security contexts (Stefan Becker)\n\t- Code analysis with Coverity Prevent. (Stefan Becker)\n\t- Updated translations: 'ru' (100%, pier11), 'de' (100%, Stefan Becker)\n\t  'es' & 'pt_BR' (100%, Anibal Avelar)\n\t- Fix for \"SIP/2.0 481 Call leg unavailable\" error (Anibal Avelar)\n\t- Increased libpurple build requisite to >= 2.4.0\n\nversion 1.8.1 \"Exchange/Calendar crash fixes\" (2010-02-16)\n\t- many crash fixes for error or corner cases in calendar integration (pier11, Stefan Becker)\n\t- more detailed code analysis with Coverity Prevent (Stefan Becker)\n\t- build fixes for older libpurple/glib2 versions (pier11)\n\t- OpenSUSE Build Service configuration files (pier11)\n\t- Fix NTLM crash if login setting is undefined (pier11)\n\t- Use of g_str_has_prefix() available since glib 2.2 and null-safe (pier11)\n\nversion 1.8.0 \"Exchange/Calendar\" (2010-02-07)\n\t- Added integration with Exchange 2007/2010. Now Sipe retrieve our Calendar data (Free/Busy, Working Hours, Meeting Subject/Location, Out-of-Office Note) from Exchange Web Services and publishes it to OCS2007/LCS2005. Thus our contacts can see our availability information based on Calendar data. For example: \"Calendar: Currently Busy. Free at 11:30\" or \"Calendar: Currently Free. Outside of working hours at 18:00\". Contacts will also see our Out-of-Office message if it's enabled in Exchange/Outlook. Team members (contacts with access level Team) will be able to see information about our current meeting - subject and location (OCS2007).\n\tFirst call to Exchange is scheduled with 1 minute delay after Sipe start. Subsequent update intervals are 30 minutes. There is a way to manually trigger Calendar data update: Accounts->{SIPE_ACCOUNT}->\"Republish Calendar\" menu option.\n\tThough Exchange integration can work without any additional settings in account configuration, there are options to manually provide email address if it's different from SIP URI, Exchange Services URI, email account authentication if it is different from configuration on Basic tab. (pier11)\n\t- Added Calendar information to contact's tooltip. You can see it like \"Calendar: Currently Tentative. Busy at 11:30\" or \"Calendar: Outside of working hours for next 8 hours\". (pier11)\n\t- 2005 presence engine has been completely rewritten. Now it supports \"Do not disturb\" status(taken from UserState), \"In a meetinfg\" status (taken from Calendar stream data, and most importantly changing autonomously in line with the stream). \"In a meeting\" activity reflects scheduled times of activities in Outlook/Exchange with Busy state. Updated 2007 presence engine too. Pidgin Statusbox now reflects last status and note set by our other points of presence; also updates according to our Calendar state (i.e without manual action); displays our Out-of-Office message if any. (pier11)\n\t- Added \"Accounts->{SIPE_ACCOUNT}->Status Reset\" menu option to clean User Status set manually. The latter can override Calendar status for example. (pier11)\n\t- Added \"Find on LinkedIn\" link on contact's User Info screen for more in-depth information about your contact if available. Both SIPE and LinkedIn.com professional network belong to enterprise domain, so match is quite good. (pier11)\n\t- Enhanced custom NTLM security provider to pass connection-oriented authentication. Used in Web authentication, for example with Exchange Web Services. In contrast to connectionless (datagram) NTLM authentication type used in SIP. (pier11)\n\t- Added Negotiate authentication scheme (Windows only). Used in HTTP authentication. (pier11)\n\t- Contributed code for Adium port. (Matt Meissner)\n\t- Added Windows Messenger 5.0 (RTC/1.2) compatibility. Though very old, some our clients use it on LCS2005. (pier11)\n\t- New BusyIdle status. (pier11)\n\t- Placed Sipe to Transifex.net translation portal allowing easily add/modify translations through web interface. (Stefan Becker)\n\t- Updated Sipe About screen (\"Accounts->{SIPE_ACCOUNT}->About SIPE plugin\") with our translation page. (pier11)\n\t- New translation: Polish 'pl' (Piotr Drąg)\n\t- Updated translations: 'zh_CN' (Kang Kai), 'ru' (pier11) and 'de' (Stefan Becker)\n\t- Static/dynamic code analysis with Coverity Prevent, memory leaks fixes (Stefan Becker)\n\t- Fixed memory leaks found with cppcheck (http://sourceforge.net/projects/cppcheck) (Edmondas Girkantas)\n\t- Fixed localization on Windows platform(!) Now translations are shown. (pier11)\n\t- Fix for #2907567 Note parsing issue. Incoming html markup (like < symbol) could wierdly rerender Pidgin's contacts list UI - for example to \"rename\" contact, or even replace contact name by group name.\n\t- Fix for #2908830 Federated contacts appear to be broken. 2005 Public IM Connectivity (PIC) environment. (pier11)\n\t- Fix crash when SSL connect fails (Stefan Becker)\n\t- Fix for server auto-discovery (Anibal Avelar)\n\t- Fix for #2912926 crash on exist. Caused by improper CSTA communications. (pier11)\n\t- Fix for xdg-email invocation. (David Woodhouse)\n\t- Fix for SLED 10 compilation. (pier11)\n\t- Fix for OpenSolaris port - #pragma pack() issue. (Stefan Becker)\n\t- Fix compilation without Kerberos (Stefan Becker)\n\t- Fix for User Agent string. (pier11)\n\t- Fix for compilation with Pidgin 2.6.4 and 2.6.5 on mingw. (pier11)\n\t- Fixed #2944156: SIPE Authentication Causes Pidgin Crash(Stefan Becker)\n\t- RPM SPEC: add Epoch: for git packages. (Stefan Becker)\n\t- Remove static link build option, remove unused config.h, other build improvements. (Stefan Becker)\n\t- Make tests compile again; Simplify \"make tests\" (Stefan Becker)\n\t- Code: Take PURPLE_INIT_PLUGIN into use.(Stefan Becker)\n\nversion 1.7.1 (2009-11-19)\n\t- \"About SIPE plugin\" screen implemented. Accessible as \"Accounts->{Your Account}->About SIPE plugin\".\n\t- New correct 'User Agent:' header in SIP messages with Purple and Sipe versions, host operating system type and processor architecture as well as OCS version. To take advantage of it - empty your old 'User Agent' setting in the account configuration.\n\t- Version now stored in single place - VERSION file and used for all builds.\n\t- Core - not using bodies for single subscriptions in 2005 environment. Optimized CSeq numbers usage. Beautified debug log output.\n\t- Call Control - session timer for dialog with CSTA. Otherwise session with CSTA got expired after ~30 min due to no refresh. RFC4028.\n\t- Call Control - removing internal alternative phone number from phone string.\n\t- RPM spec file update for CentOS/RHEL 5 - purple-sipe needed a \"Group\" (John B.)\n\t- Fixed crash in 2005 'New Chat' menu.\n\t- Fixed #2886534 - routing - Request-URI/Route headers. Problem was a re-subscription failure resulting in stopping contacts' status update after approximately 8 hours.\n\t- Fixed #2892842 - interference of conference invite to normal IM dialog on 2007 environment. Incoming BYE from conf invite process used to kill ongoing regular IM dialog with the same user.\n\t- Fixed crash in presense processing on Reuters environment (LSC 2005) on Linux.\n\t- Fixed #2882304 - 'Note' not working with LCS2005\n\t- Fix for the First message in 2005 multiparty chat.\n\t- Fix for initial outgoing messages - some were lost if typed too fast if dialog was not established yet.\n\t- Fixed #2882658 - SIGSEGV in process_incoming_info_csta() - happened on some Cisco-Systems 7 CSTA Gateways.\n\t- Fixes for SLED 10 SP2 and SP3 compilations.\n\nversion 1.7.0 \"Remote Call Control\" (2009-10-19)\n       - Added integration with PBX (external phones) using CSTA protocol (ECMA TR-87). Users can initiate a call by clicking on contact phones in right-click context menu. This feature should be enabled for user on the server side.\n       - Added reconnection to chat after disconnection by continue typing in the same open chat window (OCS 2007 only). Feature request #2866630.\n       - More precise errors shown on message undelivery event.\n       - Better re-subscription logic for contact status updates.\n       - 'Out of Office', 'In a Meeting', 'In a Conference', etc. contact activities are shown now in contast's status and tooltip. Also meeting subject and location are shown in 2007 environment if contact is in Team access category.\n       - New Idle status.\n       - Added 'Site' to User Info panel. Can be a link to user's corporate directory page or similar.\n       - Removed message acceptance in incoming INVITE.\n       - Fixed type errors in sip-sec-ntlm.c for Linux/Unix platforms.\n       - Added 32- and 64-bit header conflict check to configure.\n       - Removed libsipe.so from old incorrect installation location. This makes sure that DIY users don't have two copies of libsipe.so.\n       - Moved libsipe.so to the correct installation directory. The libpurple protocol plugins directory is $(libdir)/purple-2. While the name of the plugin is pidgin-sipe, it works perfectly fine with 'finch' too.\n       - Rewritten transaction payload handling. This should fix memory leaks in transaction handling.\n       - Fixed crash on reauthentication when IM window is open not Chat window\n       - Fixed warnings on compilation.\n       - Fixed memory leaks.\n\nversion 1.6.3 (2009-09-09)\n       - Added missing krb5-devel BuildRequires to the RPM spec file.\n       - Cleanup of source code compatibility for libpurple 2.4.x\n       - Fixed for msrtc statuses, bug #2843985\n       - Fixed HTML markup in note, bug #2841095\n       - Fixed a segmentation fauls when the function sipmsg_parse_header backs\na null value.\n       - Possible fixed a crash when SIPE account added, bug #2844545\n       - Reduced libpurple build requisite to >= 2.3.1\n       - Fixed NetBSD compilation errors in sipe-utils.c, bug #2847380\n       - Updated zh_CN translation\n       - Fixed a crash when pidgin auto-away fires, bug #2849156\n\nversion 1.6.2 (2009-08-23)\n       - Treat of 504 Server time-out error\n       - Decrease libpurple build prerequisites to >= 2.4.1\n       - Updated windows build to latest Pidgin 2.6.1\n       - Fix compilation errors against libpurple >= 2.6.0 API\n       - Publishing optimization\n       - Separate storage for subscription dialogs.\n       - Fixed '409 Conflict' case. We are extracting proper versions of our publications and updating local mirror with them.\n       - Fixed CSeq for subscription dialog.\n       - Fixed for unsubscribes\n       - Fixed for Active Directory search\n       - Make OCS2007+ conditionals self-documenting\n       - Fixed compilation problem on 64-bit and NetBSD platforms #2839689\n       - The 'context' element only for just added subscriptions #2836290\n       - Removed dependency on com_err.h\n       - Fixed warnings on compilation.\n       - Fixed memory leaks.\n\n       - Updated \"de\" translation\nversion 1.6.1 (2009-08-12)\n       - Fixed missing backslash in \"es\" translation file\n       - Support publication: modular publications\n       - Support publication: manual vs machine status publication\n       - Fix timeout calculation in sipe_buddy_subscribe_cb(), make sure timeout is never 0\n       - Fixed crash in sipe_process_roaming_self()\n       - Add purple >= 2.5.0 as configuration requirement\n       - Cleanup username handling in sipe_login()\n       - Make password mandatory again\n       - Fixed memory leaks in sipe_login() error paths\n       - Removed controversial dependency in windows branch used for old MAC code\n       - Got rid of MAC in epid generation\n       - Updated \"es\" translation\n       - Updated \"de\" translation\n       - Cleaned up connection configuration and setup\n       - More precise treatment of incoming typing info\n       - Fixed improvements reported in #2833015\n       - Fixed for \"message was not delivered\" reported in bug #2832551\n       - Fixed for CHOWA problems reported in bug #2795132\n       - Fixed for crash reported in bug #2795132\n       - Tag all unused function parameters\n       - Added Empathy support - telepathy-haze config for sipe\n       - Code around GCC bug on ppc platforms\n       - License file cleanup\n       - Fixed ppc64 compilation errors\n       - Many refinements to the RPM SPEC file\n       - Added convenience script to (re)build from git repository\n       - Added convenience script for creating git snapshots\n\nversion 1.6.0 \"Multiparty Chat\" (2009-07-27)\n       - Multi-party conversation (Chat) functionality for:\n\t + OCS 2007+ as a conference [MS-CONFBAS], [MS-CONFIM], [MS-CONFPRO];\n\t + LCS 2005- as a multi-party chat.\n       - Fixed our status in OCS 2007+ environment as seen by others.\n       - Asks user if he wants add counterparty which added him to his contact list (OCS 2007+). User dialog wording improvement.\nAlso defined default group in Add User dialog which appear after user search in catalog.\n       - More strict compilation warnings treatment.\n       - Started code split to functional modules.\n       - Tailored subscriptions for environment - eliminated not needed subscriptions in 2007 environment.\n       - Fixed session closing on unsuccessful message delivery.\n       - More correct incoming BYE processing.\n       - Fixed stealth bug when action payload got freed. Initial bug was that contact could not be removed.\n       - Fix handling of empty note text in incoming rlmi NOTIFY.\n       - patch for FreeBSD 7.x by jprather.\n       - Fix for wrong epid generation on Windows platform in case of missing MAC.\n       - Fix for Route processing.\n       - Improvements for compilation under ppc/ppc64 platfolrm.\n       - Fixed crash if work in non-authenticating environment.\n\nversion 1.5.0 \"Kerberos\" (2009-06-24)\n       - Fixed bug #2800325 for crash if wrong IP manually typed into Pidgin.\n       - New Security Framework: dedicated to use plug-able security mechanisms.\n\t + Added Kerberos/NTLM SSPI for Windows\n\t + Added Kerberos MIT for Linux\n\t + Fixed the NTLM native implementation for Linux\n       - New options on Advanced tab: Use Kerberos and Single Sign-on (for both\n kerberos implements).\n       - Fixed the --with-krb5 compilation option. Now pidgin-sipe can be compiled with krb5 support again.\n       - To send presence subscribe requests to poolFqdn servers\n       - Record-Route header can contain multiple routes. For CHOWA clients.\n       - Fixed 2 bugs with INVITE messages from incoming CHOWA clients.\n       - FreeBSD compatibility\n       - Fixed for 'same conversation ID' issue\n       - Fixed for Reuters(LCS2005) frequent disconnects\n       - Fixed many warnings on compilation.\n       - Fixed many potential memory leaks. Thank you Stefan\n       - Fixed I18n support and sync from launchpad\n\t + Added 'it' and 'ru' translations\n\t + Updated 'zh', 'cs', 'es' and 'nb' translations.\n\nversion 1.4.1 (2009-06-01)\n       - Patch for spaces in Login's username\n       - Fixed bugs #2793431, #2793688 for crash in process_incoming_notify_rlmi_resub\n       - Fixed the correct presence for contacts with the presenceMode=\"msrtc\".\n       - Simplify keep alive timeout setting code\n       - Fixed the resubscription process in LCS2005 and OCS2005.\n       - Fixed the support for batched subscription\n       - Fixed a problem when you added a new contact on OCS2007\n       - Fixed potential memory leaks. Thank you Stefan\nversion 1.4.0 (2009-05-17)\n       - Simplified Account Settings Basic screen\n       - Full support for presence using Batched Category Subscription for\n\t OCS2007. [MS-PRES]\n       - Full support for presence usgin Batched Simple Subscription for\n\t LCS2005. [MS-SIP]\n       - Active Directory search for 'Get Info' screen.\n       - Buddy URI are replaced with Display Name.\n       - Added non sensitive support between the client and servers answers.\n       - Support for deregistration [MS-SIPREGE]\n       - Support for 2007 R2 client message formatting.\n       - Re-subscription after expiration. LCS2005\n       - Added escaping to SOAP request parameters\n       - Implemented a new scheduling system\n       - Cleanup status id handling\n       - NOTIFY and BENOTIFY similarly handled\n       - Implemented piggy-back for buddy subscription.\n       - Request for functions only supported for each kind of servers\n\t (Allow-Events) OCS2007 and LCS2005. (may be LCS2003?)\n       - Fixed many warnings on compilation.\n       - Fixed many potential memory leaks. Thank you Stefan\n       - Fixed bug #2786479: some messages could not be delivered to all users.\n       - Fixed bug #2779386: fix for invalid NTLM signature.\n\nversion 1.3.4 (2009-04-13)\n       - Fix segmentation fault caused by redirect\n       - Added check for zlib.h, com_err and purple version on configure script,\n       - Added note to tooltip\n       - Added timeout of security association after eight hours as described\n\t in [MS-SIPAE] 3.2.2 Timers.\n       - Updates to enable compilation in a Cygwin/MinGW environments\n       - Fix a problem with the function purple_get_host_name() in libpurple\n\t versions <  2.5.x\n       - Support for responses with m=x-ms-message rather than m=message\n       - Support for Reuters Messaging environment (LCS2005 like)\n       - Support for message formatting (font face, style, color).\n       - Introduced invisible mode (Appear Offline). Better status support.\n\t official clients\n       - Richer status support with reference to [MS-PRES] and work of\n       - Fix for bug #2528391: Accepts the first message from the first packet (INVITE). Counterparty's first message now can appear up to 2 sec earlier.\n       - Fixed the offline contacts problem in OCS2007 following [MS-PRES]\n       - Added notification support for undelivered messages.\n\nversion 1.3.3 (2009-02-09)\n\t- Implemented keep alive support. Thanks Stefan Becker\n\t- Support LCS 2005 buddy auth/blocking. Thanks Gabriel Burt\n\t- Fixed SSL errors.\n\t- Fixed many segmentation fault errors.\n\t- Added many translation files.\n\nversion 1.3.2 (2008-12-14)\n\t- Added support for mingw. Thanks Carl Seutter\n\t- Merge with stable branch in the git repository\n\t- Fixed SSL input processing\n\t- Extended contact search implementation\n\t- Path to xBSD support\n\nversion 1.3.1 (2008-12-09)\n\t- Locale/translations support\n\t- Search contacts support\n\t- Code cleaned\n\t- LCS 2005 fixed send/receive messages;partially fixed\n\nversion 1.3 (2008-12-04)\n\t- TLS/SSL support\n\t- Fixed signing messages, thanks Gabriel Burt\n\t- Fixed LCS contacts with add/remove/modify, thanks Gabriel Burt\n\t- Added Presence support for OCS 2007 and LCS 2005\n\t- A lot of patches to fix:\n\t   +TLS connections,\n\t   +Send/receive messages,\n\t   +Full presence,\n\t   +TCP connections and optimal options in Advanced tap.\n\t- A lot bugs fixed\n\nversion 1.2 (2007-03-22)\n\t- Finished the pidgin 2.0 porting\n\t- Fixed a NTLM auth problem about the flags on challenge3.\n\t- Fixed the Contact problem.\n\t- Fixed the segmentation on network detection.\n\t- Other minor bugs\n\nversion 1.1 (2007-03-09)\n\t- Fixed a bug in NOTIFY and SUBSCRIBE methods (401 error)\n\t- Changed the method PUBLISH(don't aply in LCS) for SERVICE\n\t- Added new tags in transactions to cloned the LCS transactions.\n\t- The MESSAGE method works. Now you can send a message to online user.\n\nversion 1.0 (2007-03-04)\n\tGaim plug-in releases. First release using autoconf and automake.\n\tCompiles with gaim-2beta5 (or newer). On Debian systeam you need\n\tthe gaim-dev package for compile it.\n\n\tFirst version. Just added this functionalities:\n\t- Authentication (just type NTLM)\n\t- Presence (double sided)\n\t- Retrieves all contacts from server (with groups)\n\t- Delete contacts and groups\n"
  },
  {
    "path": "Makefile.am",
    "content": "SUBDIRS = src pixmaps po\n\nEXTRA_DIST = \\\n\tcontrib \\\n\tintltool-extract.in \\\n\tintltool-merge.in \\\n\tintltool-update.in \\\n\tpidgin-sipe.nsi \\\n\tpidgin-sipe.wxs \\\n\tsiplcs.vcxproj \\\n\tsiplcs.vcxproj.filters \\\n\tMakefile.mingw \\\n\tpo/Makefile.mingw\n\nCLEANFILES = \\\n\tintltool-extract \\\n\tintltool-update \\\n\tintltool-merge\n\nMAINTAINERCLEANFILES = \\\n\taclocal.m4 \\\n\tABOUT-NLS \\\n\tcompile \\\n\tconfigure \\\n\tconfig.guess \\\n\tconfig.h.in \\\n\tconfig.rpath \\\n\tconfig.sub \\\n\tdepcomp \\\n\tGITVERSION \\\n\tINSTALL \\\n\tinstall-sh \\\n\tintltool-extract.in \\\n\tintltool-merge.in   \\\n\tintltool-update.in  \\\n\tltmain.sh \\\n\tMakefile.in \\\n\tmissing \\\n\tmkinstalldirs \\\n\tpo/Makevars.template \\\n\tpo/Rules-quot \\\n\tpo/*.header \\\n\tpo/*.sed \\\n\tpo/*.sin \\\n\ttest-driver \\\n\tylwrap\n\nmaintainer-clean-local:\n\t-rm -rf m4\n\nACLOCAL_AMFLAGS = -I m4\n"
  },
  {
    "path": "Makefile.mingw",
    "content": "################################### tell Emacs this is a -*- makefile-gmake -*-\n#\n# Copyright (C) 2012-2014 SIPE Project <http://sipe.sourceforge.net/>\n#\n# Makefile.mingw\n#\n# Author: pier11@operamail.com\n# Author: zup@sbox.tugraz.at\n# Date 11 Nov 2009\n# Description: Top Makefile for win32 (mingw) port of LCS protocol plugin\n#\n###############################################################################\n\nifndef PIDGIN_TREE_TOP\n# standalone MinGW build\nexport PIDGIN_TREE_TOP := ../pidgin-2.10.0\nendif\ninclude $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak\n\nexport CFLAGS=-Werror\n\nWIX3_HOME := /cygdrive/c/Program\\ Files/Windows\\ Installer\\ XML\\ v3\nWXS_NAME := pidgin-sipe\nexport VERSION := $(shell cat VERSION)\nPIDGIN_VERSION := $(shell cat $(PIDGIN_TREE_TOP)/VERSION)\n\n.PHONY: all clean install msi dev devinst nsis\n\nall:\n\t$(MAKE) -C src -f $(MINGW_MAKEFILE)\n\t$(MAKE) -C po -f $(MINGW_MAKEFILE)\n\ndev:\n\t$(MAKE) -C src -f $(MINGW_MAKEFILE)\n\nclean:\n\t$(MAKE) -C src -f $(MINGW_MAKEFILE) clean\n\t$(MAKE) -C po -f $(MINGW_MAKEFILE) clean\n\trm -f $(WXS_NAME).wix*\n\trm -f $(WXS_NAME)-$(VERSION).msi\n\trm -f pidgin-sipe-$(VERSION).exe\n\nrmbak:\n\trm -f *~\n\t$(MAKE) -C src -f $(MINGW_MAKEFILE) rmbak\n\ninstall: all\n\t$(MAKE) -C src -f $(MINGW_MAKEFILE) install\n\t$(MAKE) -C po -f $(MINGW_MAKEFILE) install\n\t$(MAKE) -C pixmaps -f $(MINGW_MAKEFILE) install\n\ndevinst: dev\n\t$(MAKE) -C src -f $(MINGW_MAKEFILE) install\n\ntests: dev\n\t$(MAKE) -C src -f $(MINGW_MAKEFILE) tests\n\nmsi: all\n\tPACKAGE_VERSION=$(VERSION) $(WIX3_HOME)/bin/candle $(WXS_NAME).wxs\n\t$(WIX3_HOME)/bin/light $(WXS_NAME).wixobj\n\tmv $(WXS_NAME).msi $(WXS_NAME)-$(VERSION).msi\n\nnsis: install\n\tmakensis -DTREETOP=..\\\\pidgin-2.10.0 -DVERSION=$(VERSION) pidgin-sipe.nsi\n\n# MinGW cross-compile build (see contrib/mingw-cross-compile/README.txt)\n.PHONY: cross-compile-nsis\ncross-compile-nsis:\n\t$(MAKE) -f Makefile.mingw install\n\tmv $(PIDGIN_INSTALL_DIR)/plugins $(PIDGIN_INSTALL_DIR)/purple-2\n\tperl contrib/opensuse-build-service/generate_nsi.pl po/LINGUAS \\\n\t\t<contrib/opensuse-build-service/pidgin-sipe.nsi.template \\\n\t\t>$(PIDGIN_INSTALL_DIR)/pidgin-sipe.nsi\n\tset -e; cd $(PIDGIN_INSTALL_DIR); \\\n\tmakensis \\\n\t\t-DPIDGIN_VERSION=$(PIDGIN_VERSION) \\\n\t\t-DVERSION=$(VERSION) \\\n\t\t-DMINGW_LIBDIR=. \\\n\t\t-DMINGW_DATADIR=. \\\n\t\tpidgin-sipe.nsi\n\tmv $(PIDGIN_INSTALL_DIR)/pidgin-sipe-$(VERSION).exe $(PIDGIN_TREE_TOP)\n\trm -rf $(PIDGIN_INSTALL_DIR)\n"
  },
  {
    "path": "NEWS",
    "content": "version 1.25.0 \"Buddy Idle Time, RTF\" (2019-10-12)\n\t- Feature #107: Provide idle start time for a buddy (Stefan Becker)\n\t- Feature #77: RTF support (incoming) (Stefan Becker)\n\t  * the code only extracts plain text from incoming RTF\n\t- Fixed #358: FTBFS with glib-2.0 >= 2.62.0 (Stefan Becker)\n\t- Fixed #350: Inconsistent parsing of From:/To: headers (Stefan Becker)\n\t- raise BR telepathy-glib >= 0.24.0 (Stefan Becker)\n\t- switch from GPLv2+ to SPDX identifier GPL-2.0-or-later (Stefan Becker)\n"
  },
  {
    "path": "README",
    "content": "Introduction\n============\n\nSIPE is a third-party plugin for the Pidgin/Adium/Miranda/Telepathy\nmulti-protocol instant messaging clients/frameworks. It implements the\nextended version of SIP/SIMPLE used by various products:\n\n    * Skype for Business\n    * Microsoft Office 365\n    * Microsoft Business Productivity Online Suite (BPOS)\n    * Microsoft Lync Server\n    * Microsoft Office Communications Server (OCS 2007/2007 R2)\n    * Microsoft Live Communications Server (LCS 2003/2005)\n\nWith this plugin you should be able to replace your Microsoft Office\nCommunicator client with Pidgin/Adium/Miranda/Telepathy.\n\n\nFeatures\n========\n\nThe plugin has support for\n\n    * Instant Messaging (IM)\n    * Multiparty chat (OCS 2005) or conference (OCS 2007+)\n    * Group chat (Lync 2010) or Persistent chat (Lync 2013) - [MS-XCCOSIP]\n    * Enhanced presence\n    * Calendar integration with Exchange 2007+ (can be disabled)\n    * Contact details information - company, phones, photo, web site, etc.\n    * Unified Contact Store (Lync 2013) - [MS-OXWSCOS]\n    * Contact search - [MS-PRES] and [MS-DLX] methods supported\n    * Encrypted file transfer (OCS2007: send & receive, Lync: receive only)\n    * Voice & Video calls\n    * Call initiation through PBX\n    * NTLMv2, Kerberos & TLS-DSK authentication methods\n    * Single Sign-On (depends on OS and authentication method)\n    * Automatic SSL/TLS protection for SIP/HTTP connections\n    * Crypto implementation using NSS or OpenSSL\n    * Localization\n\nThe plugin has backends for\n\n    * Pidgin/Finch (libpurple)\n    * Adium (libpurple)\n    * Miranda\n    * Telepathy (under development)\n\n\nAdvantages over Office Communicator products\n============================================\n\n    * Available on broader range of platforms: Linux, *BSD, Maemo, OSX,\n      commercial UNIX, Windows.\n    * Ability to simultaneously connect to several Office Communicator\n      accounts in addition to public IM network accounts like MSN, AOL,\n      Yahoo. For example one account is in vendor company and another is\n      in client company.\n    * Keeps history of communications in environments without Outlook. For\n      example in companies where Lotus Notes is deployed as a default\n      groupware client instead of Outlook.\n    * Lotus Notes/Domino calendar integration. Unique to SIPE.\n    * Open development model, open source product. License is GPL-2.0-or-later\n\n\nSupport\n=======\n\nThe Pidgin or Adium projects do not support third-party plugins! Please do\nnot ask questions about SIPE in their forums or report SIPE problems to their\nbug trackers.\n\nIf you set up your Office Communicator/Lync account with SIPE for the first\ntime then please make sure to read this page:\n\n    https://sourceforge.net/p/sipe/wiki/How%20to%20setup%20an%20account/\n\nIf you encounter problems then please make sure to check out the Frequently\nAsked Question page:\n\n    https://sourceforge.net/p/sipe/faq/\n\nIf you still have problems then please check the support forum if another\nuser encountered the same problem and maybe solved it already:\n\n    http://sourceforge.net/p/sipe/discussion/\n\nIf you think that you have found a bug in SIPE then please report it to the\nSIPE bug tracker:\n\n    https://sourceforge.net/p/sipe/bugs/\n\nThe SIPE project kindly requests that you do not ignore the instructions that\nappear at the head of the \"Create Ticket\" page. These instructions are there\nfor a reason and if you ignore them then you will only cause unnecessary work\nfor the project and yourself. Please do not report missing features as bugs.\n\nNew or missing features can be requested here:\n\n    https://sourceforge.net/p/sipe/feature-requests/\n\n\nLocalization\n============\n\nSIPE has already been localized for several languages. You can help to\ntranslate SIPE to your native language at Transifex:\n\n    https://www.transifex.com/stefanb/pidgin-sipe/\n\nThe service offers a convenient web editor.\n\n\nD-Bus support (libpurple backend only)\n======================================\n\nIf libpurple and SIPE have been compiled with D-Bus support and the D-Bus\nbackend has been successfully initialized at libpurple start, then SIPE\nextends the libpurple D-Bus interface with the following APIs:\n\n    Function\t\t  Description\n\n    SipeCallPhoneNumber(aId, phone_number)\n\t\t\t  Same as \"Call a phone number\" menu\n\n    SipeJoinConferenceWithOrganizerAndId(aId, organizer_email, meeting_id)\n\t\t\t  Same as \"Organizer email\" and \"Meeting ID\" in the\n\t\t\t  dialog opened by \"Join scheduled conference...\"\n\n    SipeJoinConferenceWithUri(aId, uri)\n\t\t\t  Same as \"Meeting location\" in the dialog opened by\n\t\t\t  \"Join scheduled conference...\"\n\n    SipeRepublishCalendar(aId)\n\t\t\t  Same as \"Republish Calendar\" menu\n\n    SipeResetStatus(aId)\n\t\t\t  Same as \"Reset status\" menu\n\nTo use the APIs from a script you'll need a D-Bus object for the libpurple\ninterface and a valid & connected account ID as first parameter. An invalid\naccount ID will cause SIPE to silently ignore the D-Bus invocation.\n\nExample script code (without error checks to keep it simple):\n\nPerl:\n\n    use Net::DBus;\n    my $bus       = Net::DBus->session;\n    my $service   = $bus->get_service('im.pidgin.purple.PurpleService');\n    my $purple    = $service->get_object('/im/pidgin/purple/PurpleObject',\n                                         'im.pidgin.purple.PurpleInterface');\n    my $accountId = $purple->PurpleAccountsFind($accountName, 'prpl-sipe');\n    $purple->SipeXYZ($accountId, parameters... );\n\nPython:\n\n    import dbus\n    bus       = dbus.SessionBus()\n    object    = bus.get_object(\"im.pidgin.purple.PurpleService\",\n                               \"/im/pidgin/purple/PurpleObject\")\n    purple    = dbus.Interface(object, \"im.pidgin.purple.PurpleInterface\")\n    accountId = purple.PurpleAccountsFind($accountName, 'prpl-sipe')\n    purple.SipeXYZ(accountId, parameters... );\n\n\nInstalling from a distribution repository\n=========================================\n\nMany Open Source OS distributions have a ready-made package \"pidgin-sipe\".\nBefore trying to compile it from the source code yourself you should try\nto install this package with the standard installation method provided by\nyour OS.\n\nOnce you have SIPE installed and are connected to your account you can check\nfrom the following Pidgin menu\n\n\tAccounts -> <SIPE Account> -> About SIPE plugin...\n\nwhich optional features have been enabled in your SIPE build.\n\n\nDo It Yourself I: compiling against \"pidgin\" package\n====================================================\n\nNOTE: for instructions how to setup a build environment on Windows to\n      compile the Windows Pidgin plugin, please read:\n\n\thttps://developer.pidgin.im/wiki/BuildingWinPidgin\n\nNOTE: for instructions how to cross-compile the Windows Pidgin plugin on\n      Linux, please read:\n\n\tcontrib/mingw-cross-compile/README.txt\n\nNOTE: for instructions how to compile the SIPEAdiumPlugin on Mac OS X,\n      please read:\n\n\tsrc/adium/README.adium\n\n\nIf you already have installed the \"pidgin\" package from your distribution\nrepository and want compile SIPE from source code yourself, then you need to\ninstall the necessary headers first. Depending on your distribution you'll\nneed to install one of the following packages\n\n\tlibpurple-dev\n\tlibpurple-devel\n\nFor the compilation you'll need to install a C compiler and some of the\nfollowing packages\n\n\tlibtool\n\tintltool\n\n\tpkg-config\n\tlibglib2.0-dev\n\tlibxml2-dev\n\tlibgmime-2.6-dev  (optional)\n\n\tpkgconfig\n\tlibglib2-devel\n\tlibxml2-devel\n\tgettext-devel\n\tgmime-devel       (optional)\n\nYou have to choose between NSS or OpenSSL for the crypto backend. You'll\nneed one of the following packages\n\n\tfor NSS:\n\tlibnss3-dev\n\tnss-devel\n\tmozilla-nss-devel\n\n\tfor OpenSSL:\n\tlibssl-dev\n\topenssl-devel\n\nIf you want to enable Kerberos authentication support then you'll need one\nof the following packages\n\n\tlibkrb5-dev\n\tkrb5-devel\n\nIf you additionally want to disable the internal NTLM implementation and\nauthenticate with NTLM via GSSAPI then you'll need one of the following\npackages\n\n\tgssntlmssp-devel\n\nIf you want to enable the D-Bus support then you'll need one of the\nfollowing packages\n\n\tlibdbus-1-dev\n\tdbus-devel\n\nIf you want to enable Voice & Video features then you'll need some of the\nfollowing packages. You need to install the same version of the GStreamer\ndevelopment packages which where used to compile Pidgin!\n\n\tlibfarstream-0.2-dev\n\tlibgstreamer1.0-dev\n\tlibgstreamer-plugins-base1.0-dev\n\tlibnice-dev                   (>= 0.1.13)\n\tlibpurple-dev                 (>= 2.10.12)\n\n\tfarstream02-devel\n\tgstreamer1-devel\n\tgstreamer1-plugins-base-devel\n\tlibnice-devel                 (>= 0.1.13)\n\tlibpurple-devel               (>= 2.10.12)\n\nNow you should be able to compile the source code with\n\n\t./configure --prefix=/usr\n\tmake\n\nIf you get errors then you are missing some required package. After\nsuccessful compilation you can install SIPE with:\n\n\tsu -c \"make install\"\n\nIf you get errors from configure or libtool about version conflicts then\nyou need to regenerate the autoconf files. You'll need these additional\npackages\n\n\tautoconf\n\tautomake\n\tflex\n\nNow you should be able to regenerate the files with\n\n\tautopoint --force\n\tAUTOPOINT=\"intltoolize --copy --force --automake\" \\\n\t\tautoreconf --force --install\n\nAfter that go back to the configure step above.\n\n\nDo It Yourself II: compiling against self-compiled pidgin\n=========================================================\n\nIf you have compiled pidgin from source code yourself then you'll have to\nspecify the correct installation path in configure. Usually pidgin is\ninstalled in /usr/local so the following command should work\n\n\t./configure --prefix=/usr/local\n\nThe rest of the steps are the same as in the previous section.\n\n\nDo It Yourself III: building from git checkout\n==============================================\n\nBuilding from a git checkout is meant for project maintainers, i.e. you\nneed to generate the configure script first:\n\n\t./autogen.sh\n\nThe rest of the steps are the same as in the previous sections.\n\nTo clean all artifacts and reset the source tree to pristine condition use\n\n\tmake maintainer-clean\n\nIf you just want to quickly run a one-shot build from a git checkout then\nyou can use the following helper script which executes all necessary steps\nin the correct order:\n\n\t./git-build.sh\n\n\nContributing code\n=================\n\nIf you want to contribute to the SIPE project please have a look at\n\n    http://sipe.sourceforge.net/git/\n\nSome of the instructions are unfortunately out-dated. If in doubt then\n*ASK* from the current maintainers before committing!\n\nPlease also have a look at the Pidgin coding style guide\n\n    https://developer.pidgin.im/wiki/StyleGuide\n"
  },
  {
    "path": "TODO",
    "content": "Bugs:\n\nBig Targets:\n\t- Native telepahty backend\n\t- Desktop sharing/Live Meeting integration on Windows platform.\n\t- Update projects site with\n\t  * SIPE features\n          * better/more complete screenshots\n\t  * page about standards used in SIPE with references\n\nCall Control:\n\t- change user state to On Call when line is active and then back\n\t- answer incoming call (logs required)\n\t- (?) work with multiple phone lines (not the first one)\n\t- (?) Call transfer set up, other RCC features from Communicator.\n\nGroup Chat:\n        - channel management: add, delete\n        - (?) lock/unlock channel (is this possible?)\n        - file sharing: up & downloading from web server\n        - ??? (unknown as we don't have XCCOS protocol specification)\n"
  },
  {
    "path": "VERSION",
    "content": "1.25.0\n"
  },
  {
    "path": "autogen.sh",
    "content": "#! /bin/sh\n###############################################################################\n# Generate GITVERSION\n###############################################################################\n_gitversion=$(git describe | grep -e -)\nif [ -n \"${_gitversion}\" ]; then\n\t_gitversion=$(echo ${_gitversion} | cut -d- -f3 | sed 's/^g//')\n\techo -n ${_gitversion} >GITVERSION\nelse\n\trm -f GITVERSION\nfi\n\n###############################################################################\n# Set up build from git tree\n###############################################################################\nset -e\n\n# Set up initial NLS stuff...\nautopoint --force\n\n# ...now replace \"autopoint\" with \"intltoolize\" in full setup run\nAUTOPOINT=\"intltoolize --copy --force --automake\" \\\n\t autoreconf --force --install\n"
  },
  {
    "path": "configure.ac",
    "content": "dnl ensure recent enough version of Autoconf\nAC_PREREQ([2.69])\n\nAC_CONFIG_MACRO_DIRS([m4])\n\ndnl Use 'VERSION' files to get version.\nm4_define([SIPE_VERSION_DATA], m4_include([VERSION]))\n\ndnl Strip off newline characters.\nm4_define([SIPE_VERSION],\n\tm4_substr(SIPE_VERSION_DATA,\n\t\t  [0], m4_decr(m4_len(SIPE_VERSION_DATA))))\n\ndnl homepage\nm4_define([SIPE_HOMEPAGE], [http://sipe.sourceforge.net/])\n\ndnl initialize package name, version, bugtracker & homepage\nAC_INIT([pidgin-sipe], SIPE_VERSION,\n\t[https://sourceforge.net/p/sipe/bugs/], [],\n\tSIPE_HOMEPAGE)\n\nAC_DEFINE([SIPE_TRANSLATIONS_URL],\n\t[\"https://www.transifex.com/stefanb/pidgin-sipe/\"],\n\t[URL for submitting translations.])\n\ndnl define optional git commit ID generated by autogen.sh\nm4_define([SIPE_GIT_COMMIT], m4_sinclude([GITVERSION]))\nAS_IF([test \"x\"SIPE_GIT_COMMIT != x],\n\t[AC_MSG_NOTICE([set git commit])\n\t AC_DEFINE(PACKAGE_GIT_COMMIT, \"SIPE_GIT_COMMIT\", [Define to the git commit for this package.])\n])\n\ndnl setup automake and require recent enough version\nAM_INIT_AUTOMAKE([1.16 dist-bzip2 dist-xz no-define tar-ustar])\n\nAC_CANONICAL_HOST\n\ndnl set PACKAGE_URL for autoconf < 2.64\nAS_IF([test \"x${PACKAGE_URL}\" = x],\n\t[AC_MSG_NOTICE([set PACKAGE_URL for autoconf < 2.64])\n\t AC_DEFINE(PACKAGE_URL, \"SIPE_HOMEPAGE\", [Define to the home page for this package.])\n])\n\ndnl set programming language\nAC_LANG(C)\nAM_PROG_CC_C_O\nAM_PROG_LEX\nAC_HEADER_STDC\n\ndnl setup shared library generation\nLT_INIT([disable-static])\n\ndnl checks for tools\nIT_PROG_INTLTOOL([0.41.0])\nAC_PROG_INSTALL\n\ndnl ******************************\ndnl Win32\ndnl ******************************\nAC_MSG_CHECKING([for Win32])\nAS_CASE([\"$host\"],\n\t\t[*-mingw*], [os_win32=yes],\n\t\t[os_win32=no])\nAC_MSG_RESULT([$os_win32])\nAM_CONDITIONAL(SIPE_OS_WIN32, [test \"x${os_win32}\" = xyes])\n\ndnl checks for header files\nAC_CHECK_HEADERS([])\n\ndnl checks for library functions\nAC_CHECK_FUNCS([])\n\ndnl tell pkgconfig to look in the same prefix where we're installing this to,\ndnl as that is likely where libpurple will be found if it is not in the default\ndnl pkgconfig path\nPKG_CONFIG_PATH=\"${PKG_CONFIG_PATH}:${libdir}/pkgconfig\"\nexport PKG_CONFIG_PATH\n\ndnl debug mode\nAC_ARG_ENABLE(debug,\n\t[AS_HELP_STRING([--enable-debug],\n\t\t\t[compile with debugging support @<:@default=no@:>@])],\n\t[],\n\t[enable_debug=no])\n\nAS_IF([test \"x$enable_debug\" = xyes],\n\t[AC_DEFINE(DEBUG, 1, [Define if debugging is enabled.])])\nAC_SUBST(DEBUG_CFLAGS)\n\ndnl\ndnl Quality check mode - try to find bugs instead of hiding them\ndnl\ndnl Developers & contributors:\ndnl\ndnl     You are *NOT* allowed to commit code to SIPE repository that only\ndnl     builds with --disable-quality-check!\ndnl\ndnl Distro package maintainers:\ndnl\ndnl     You may choose to add --disable-quality-check to the package build\ndnl     specification if you can't fix all build dependencies properly.\ndnl\nAC_ARG_ENABLE(quality-check,\n\t[AS_HELP_STRING([--enable-quality-check],\n\t\t\t[compile with compiler checks enabled @<:@default=yes@:>@])],\n\t[],\n\t[enable_quality_check=yes])\n\ndnl default quality configuration\nQUALITY_CFLAGS=\"$QUALITY_CFLAGS -Wall\"\n\ndnl convert warnings to errors\nAS_IF([test \"x$enable_quality_check\" = xyes],\n\t[QUALITY_CFLAGS=\"$QUALITY_CFLAGS -Werror\"])\n\ndnl enable warnings supported by the GCC on the build system\ndnl @TODO: not included in -Wall: \"-Wwrite-strings\" \\\nfor newflag in \\\n\t\"-Wextra\" \\\n\t\"-Waggregate-return\" \\\n\t\"-Wcast-align\" \\\n\t\"-Wcast-function-type\" \\\n\t\"-Wdeclaration-after-statement\" \\\n\t\"-Wdeprecated-declarations\" \\\n\t\"-Wduplicate-decl-specifier\" \\\n\t\"-Winit-self\" \\\n\t\"-Wmaybe-uninitialized\" \\\n\t\"-Wmissing-declarations\" \\\n\t\"-Wmissing-prototypes\" \\\n\t\"-Wnested-externs\" \\\n\t\"-Wpointer-arith\" \\\n\t\"-Wundef\" \\\n\t\"-Wunused-but-set-variable\" \\\n; do\n\tac_save_CFLAGS=\"$CFLAGS\"\n\tAC_MSG_CHECKING([if $CC supports $newflag])\n\tCFLAGS=\"$CFLAGS $newflag\"\n\tAC_COMPILE_IFELSE(\n\t\t[AC_LANG_SOURCE([[]])],\n\t\t[AC_MSG_RESULT(yes)\n\t\t\tQUALITY_CFLAGS=\"$QUALITY_CFLAGS $newflag\"],\n\t\t[AC_MSG_RESULT(no)]\n\t)\n\tCFLAGS=\"$ac_save_CFLAGS\"\ndone\nAC_SUBST(QUALITY_CFLAGS)\n\ndnl check for availability of addition linker flags\nfor newflag in \\\n\t\"-Wl,-Bsymbolic-functions\" \\\n; do\n\tac_save_LDFLAGS=\"$LDFLAGS\"\n\tAC_MSG_CHECKING([if $CC supports $newflag])\n\tLDFLAGS=\"$LDFLAGS $ADDITIONAL_LDFLAGS $newflag\"\n\tAC_LINK_IFELSE(\n\t\t[AC_LANG_SOURCE([[\nint main(int argc, char *argv[])\n{\n\treturn(0);\n}\n\t\t ]])],\n\t\t[AC_MSG_RESULT(yes)\n\t\t ADDITIONAL_LDFLAGS=\"$ADDITIONAL_LDFLAGS $newflag\"],\n\t\t[AC_MSG_RESULT(no)]\n\t)\n\tLDFLAGS=\"$ac_save_LDFLAGS\"\ndone\nAC_SUBST(ADDITIONAL_LDFLAGS)\n\ndnl Check for pkg-config before using it\nPKG_PROG_PKG_CONFIG\n\ndnl check for valgrind (optional, only needed for debugging)\nPKG_CHECK_MODULES(VALGRIND, [valgrind],\n\t[AC_DEFINE(HAVE_VALGRIND, 1, [Define to 1 if you have the valgrind headers])],\n\t[AC_MSG_RESULT(no)])\n\ndnl build option: with AppStream support\nAC_ARG_WITH(appstream,\n\t[AC_HELP_STRING([--with-appstream],\n\t\t[install AppStream XML file @<:@default=yes@:>@])],\n\t[AS_IF([test \"x$withval\" = xno], [with_appstream=no])],\n\t[with_appstream=yes])\nAM_CONDITIONAL(SIPE_WITH_APPSTREAM, [test \"x$with_appstream\" != xno])\n\ndnl build option: with voice & video support (for all backends)\nAC_ARG_WITH(vv,\n\t[AC_HELP_STRING([--with-vv],\n\t\t[compile with voice and video support @<:@default=check@:>@])],\n\t[AS_IF([test \"x$withval\" = xyes], [with_vv=yes])],\n\t[with_vv=check])\n\ndnl check for Kerberos 5 support\nAC_ARG_WITH([krb5],\n\t[AC_HELP_STRING([--with-krb5],\n\t\t[compile with Kerberos 5 support @<:@default=check@:>@])],\n\t[AS_IF([test \"x$withval\" = xyes], [with_krb5=check])],\n\t[with_krb5=check])\n\nAS_IF([test \"x$with_krb5\" = xno], [], dnl disabled by user\n      [test \"x$with_krb5\" = xcheck],  dnl autodetect with krb5-config\n\t[AC_MSG_CHECKING(if Kerberos 5 is available)\n\t AS_IF([AC_RUN_LOG([krb5-config --version])],\n\t\t[KRB5_CFLAGS=`krb5-config --cflags 2>/dev/null`\n\t\t KRB5_LDFLAGS=\"\"\n\n\t\t dnl same as AC_CHECK_LIB()\n\t\t LIBS=\"$LIBS `krb5-config --libs gssapi 2>/dev/null`\"],\n\t\t[AC_MSG_RESULT(no)\n\t\t with_krb5=no])],\n      [                               dnl path specified by user\n\tKRB5_CFLAGS=\"-I${with_krb5}/include\"\n\tKRB5_LDFLAGS=\"-L${with_krb5}/lib\"\n      ])\nAS_IF([test \"x$with_krb5\" != xno],\n      [ac_save_CFLAGS=\"$CFLAGS\"\n       ac_save_LDFLAGS=\"$LDFLAGS\"\n       CFLAGS=\"$CFLAGS $KRB5_CFLAGS\"\n       LDFLAGS=\"$LDFLAGS $KRB5_LDFLAGS\"\n       AC_CHECK_HEADERS([gssapi/gssapi.h gssapi/gssapi_krb5.h],\n\t\t\t[],\n\t\t\t[AC_ERROR([GSSAPI headers not found])])\n       AC_CHECK_FUNC([gss_init_sec_context],\n\t\t     [],\n\t\t     [AC_ERROR([GSSAPI libraries not found])])\n\n       dnl older GSSAPI releases don't have gss_acquire_cred_with_passwd()\n       AC_CHECK_HEADER([gssapi/gssapi_ext.h],\n\t\t       [AC_CHECK_FUNC([gss_acquire_cred_with_password],\n\t\t\t\t      [AC_DEFINE(HAVE_GSSAPI_PASSWORD_SUPPORT, 1, [Define to 1 if gssapi has gss_acquire_cred_with_passwd()])],\n\t\t\t\t      [AC_MSG_NOTICE([gss_acquire_cred_with_passwd() required: disabling GSSAPI non-SSO support])])],\n\t\t       [AC_MSG_NOTICE([gssapi/gssapi_ext.h required: disabling GSSAPI non-SSO support])])\n\n       CFLAGS=\"$ac_save_CFLAGS\"\n       LDFLAGS=\"$ac_save_LDFLAGS\"\n      ])\n\nAM_CONDITIONAL(SIP_SEC_GSSAPI, [test \"x$with_krb5\" != xno])\nAC_SUBST(KRB5_CFLAGS)\nAC_SUBST(KRB5_LDFLAGS)\n\ndnl check for DBUS support\nAC_ARG_WITH([dbus],\n\t[AC_HELP_STRING([--with-dbus],\n\t\t[compile with D-BUS support @<:@default=check@:>@])],\n\t[AS_IF([test \"x$withval\" = xyes], [with_dbus=check])],\n\t[with_dbus=check])\n\nAS_IF([test \"x$with_dbus\" = xno], [], dnl disabled by user\n      [test \"x$with_dbus\" = xcheck],  dnl autodetect with pkg-config\n\t[PKG_CHECK_MODULES(DBUS, [dbus-1],\n\t\t[with_dbus=yes],\n\t\t[with_dbus=no])\n\t])\nAM_CONDITIONAL(SIPE_DBUS, [test \"x$with_dbus\" = xyes])\nAS_IF([test \"x$with_dbus\" = xyes],\n\t[AC_DEFINE(HAVE_DBUS, 1, [Define if D-BUS should be used in sipe.])])\n\nAC_ARG_ENABLE(gssapi_only,\n\t[AS_HELP_STRING([--enable-gssapi-only],\n\t\t\t[disable all internal authentication code and only use\n                         GSSAPI for authentication @<:@default=yes@:>@])],\n\t[],\n        dnl requires Kerberos which provides GSSAPI\n\t[enable_gssapi_only=$with_krb5])\nAS_IF([test \"x$enable_gssapi_only\" != xno],\n\t[AC_CHECK_HEADER([gssapi/gssapi_ntlmssp.h],\n\t\t       [AC_DEFINE(HAVE_GSSAPI_ONLY, 1, [Define to 1 to enable GSSAPI-only mode])],\n\t\t       [AC_MSG_NOTICE([gssapi/gssapi_ntlm.h required: falling back to internal authentication implementation])\n                        enable_gssapi_only=no])\n        ])\nAM_CONDITIONAL(SIP_SEC_GSSAPI_ONLY, [test \"x$enable_gssapi_only\" != xno])\n\ndnl\ndnl oldest supported LTS release vs. package versions\ndnl\ndnl last checked: Jun-2019\ndnl\ndnl package        | Debian  | RHEL    | SLES    | Ubuntu  | win32  |\ndnl                | 8.0     | 6.10    | 12 SP4  | 16.04   | 2.13.x |\ndnl            EOL | 07/2020 | 12/2020 | 11/2024 | 04/2021 |    N/A |\ndnl ---------------|---------|---------|---------|---------|--------|\ndnl glib-2.0       |  2.42.x |  2.28.x |  2.48.x |  2.48.x | 2.18.x |\ndnl gmime-2.6      |     YES |      NO |     YES |     YES |     NO |\ndnl gss-ntlmssp    |      NO |      NO |      NO |   0.7.x |    N/A |\ndnl intltool       |  0.50.2 |  0.41.0 |  0.51.0 |  0.51.0 | 0.40.4 |\ndnl nice           | TOO OLD | TOO OLD |  0.1.13 |  0.1.13 |    N/A |\ndnl purple         |  2.11.x |   2.7.x |  2.12.x |  2.10.x | 2.13.x |\ndnl telepathy-glib |  0.24.x |      NO |  0.24.x |  0.24.x |    N/A |\ndnl\n\ndnl check for glib\nPKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.18.0])\nPKG_CHECK_MODULES(GMODULE, [gmodule-2.0 >= 2.18.0])\n\ndnl check for gmime\nPKG_CHECK_MODULES(GMIME, [gmime-3.0 >= 3.0.0],\n\t[ac_have_gmime=yes],\n\t[PKG_CHECK_MODULES(GMIME, [gmime-2.6 >= 2.6.0],\n\t\t[ac_have_gmime=yes],\n\t\t[ac_have_gmime=no])\n\t])\nAM_CONDITIONAL(SIPE_MIME_GMIME, [test \"x$ac_have_gmime\" = xyes])\nAS_IF([test \"x$ac_have_gmime\" = xyes],\n\t[AC_DEFINE(HAVE_GMIME, 1, [Define if gmime should be used in sipe.])])\n\ndnl check for NSS\nAC_ARG_ENABLE(nss,\n\t[AS_HELP_STRING([--enable-nss],\n\t\t\t[use NSS as crypto backend @<:@default=yes@:>@])],\n\t[],\n\t[enable_nss=yes])\nAS_IF([test \"x$enable_nss\" != xno],\n\t[PKG_CHECK_MODULES(NSS, [nss],\n\t\t[],\n\t\t[PKG_CHECK_MODULES(NSS, [mozilla-nss],\n\t\t\t[],\n\t\t\t[PKG_CHECK_MODULES(NSS, [microb-engine-nss],\n\t\t\t\t[],\n\t\t\t\t[enable_nss=no])\n\t\t\t])\n\t\t])\n\t])\n\ndnl check for OpenSSL\nAC_ARG_ENABLE(openssl,\n\t[AS_HELP_STRING([--enable-openssl],\n\t\t\t[use OpenSSL as crypto backend @<:@default=yes@:>@])],\n\t[],\n\t[enable_openssl=yes])\nAS_IF([test \"x$enable_openssl\" != xno],\n\t[PKG_CHECK_MODULES(OPENSSL, [libcrypto],\n\t\t   [],\n\t\t   [enable_openssl=no])\n\t])\nAS_IF(\n\t[test \"x$enable_nss\" != xno],\n\t\t[ dnl NSS has priority over OpenSSL\n\t\t  enable_openssl=no\n\t\t  AC_MSG_NOTICE([using NSS as crypto backend.])],\n\t[test \"x$enable_openssl\" != xno],\n\t\t[AC_MSG_NOTICE([using OpenSSL as crypto backend.])],\n\t[AC_ERROR([nss, mozilla-nss, microb-engine-nss or libcrypto package is required])])\nAM_CONDITIONAL(SIPE_OPENSSL, [test \"x$enable_openssl\" != xno])\n\ndnl check for libxml2\nPKG_CHECK_MODULES(LIBXML2, [libxml-2.0])\n\ndnl assumption check: sizof(uuid_t) must be 16 (see uuid.c)\nAC_MSG_CHECKING([that sizeof(uuid_t) is 16])\nac_save_CFLAGS=\"$CFLAGS\"\ndnl NOTE: including $QUALITY_CFLAGS can lead to false negative configure checks!\nCFLAGS=\"$CFLAGS $GLIB_CFLAGS\"\ndnl note the [[[ quoting: our code contains []!\nAC_RUN_IFELSE(\n\t[AC_LANG_PROGRAM(\n\t\t[[\n#include <glib.h>\n#include <stdio.h>\n\n/* Copied from uuid.c */\ntypedef struct {\n   guint32 time_low;\n   guint16 time_mid;\n   guint16 time_hi_and_version;\n   guint8  clock_seq_hi_and_reserved;\n   guint8  clock_seq_low;\n   guint8  node[6];\n} uuid_t;\n\t\t]],\n\t\t[[if (sizeof(uuid_t) == 16) {\n\t\t\treturn(0);\n\t\t } else {\n\t\t\tprintf(\"\\n\\nOoops, sizeof(uuid_t) is %\" G_GSIZE_FORMAT \".\\n\\n\", sizeof(uuid_t));\n\t\t\treturn(1);\n\t\t }]])],\n\t[AC_MSG_RESULT(yes)],\n\t[AC_MSG_FAILURE([sizeof(uuid_t) is not 16\n\nPlease notify the SIPE developers.\n\nCopy & paste all lines starting with the line\n\n  checking that sizeof(uuid_t) is 16...\n\nto the report and attach the file \"config.log\".\n\nCompiler information:\n\n host:     $host\n build:    $build\n compiler: $CC\n])],\n\t[AC_MSG_WARN([cross compiling: not checking])])\nCFLAGS=\"$ac_save_CFLAGS\"\n\ndnl build option: OCS2005 client hack\nAC_ARG_ENABLE([ocs2005-message-hack],\n\t[AC_HELP_STRING([--enable-ocs2005-message-hack], [disable message timeout for OCS2005 clients\n\t\t\t\t\t\t\t  which causes \"false\" not delivered error messages\n\t\t\t\t\t\t\t  @<:@default=no@:>@])],\n\t[AC_DEFINE([ENABLE_OCS2005_MESSAGE_HACK], [1],\n\t           [Define to 1 to disable SIP MESSAGE timeout feature.\n\t\t    OCS2005 clients don't seem to acknowledge MESSAGEs and\n\t\t    disabling the timeout suppresses \"false\" error messages])])\n\ndnl build option: purple backend\nAC_ARG_ENABLE([purple],\n\t[AC_HELP_STRING([--enable-purple], [build purple plugin @<:@default=yes@:>@])],\n\t[],\n\t[enable_purple=yes])\nac_have_appshare=no\nac_have_appshare_server=no\nac_have_xdata=no\nwith_purple_vv=no\nAS_IF([test \"x$enable_purple\" != xno],\n\t[PKG_CHECK_MODULES(PURPLE, [purple-3],\n\t\t[purple_pkgconfig=purple-3],\n\t\t[PKG_CHECK_MODULES(PURPLE, [purple >= 2.7.0],\n\t\t\t[purple_pkgconfig=purple],\n\t\t\t[enable_purple=no])])\n\n\t AS_IF([test \"x$enable_purple\" != xno],\n\t\t[AC_MSG_NOTICE([using package \"$purple_pkgconfig\".])\n\n\t\t dnl unfortunately PURPLE_MAJOR_VERSION is not exported by purple.m4\n\t\t PURPLE_MAJOR_VERSION=`$PKG_CONFIG --modversion $purple_pkgconfig | cut -d. -f 1`\n\t\t AC_SUBST(PURPLE_MAJOR_VERSION)\n\n\t\t ac_save_CFLAGS=\"$CFLAGS\"\n\t\t ac_save_LIBS=\"$LIBS\"\n\t\t dnl NOTE: including $QUALITY_CFLAGS can lead to false negative configure checks!\n\t\t CFLAGS=\"$CFLAGS $PURPLE_CFLAGS\"\n\t\t LIBS=\"$LIBS $PURPLE_LIBS\"\n\n\t\t dnl check whether enable voice and video support\n\t\t AS_IF([test \"x$with_vv\" = xno], [], dnl disabled by user\n\t\t       [AC_MSG_CHECKING(for purple voice and video support)\n\t\t\tpurple_has_media=no\n\t\t\tAC_RUN_IFELSE(\n\t\t\t\t[AC_LANG_PROGRAM([[\n#include <media.h>\n\t\t\t\t\t]],\n\t\t\t\t\t[[return (purple_media_get_type() == G_TYPE_NONE ? 1 : 0);]]\n\t\t\t\t)],\n\t\t\t\t[purple_has_media=yes\n\t\t\t\t AC_MSG_RESULT(ok)\n\t\t\t\t],\n\t\t\t\t[AC_MSG_RESULT([no - your purple hasn't been compiled with voice and video support.])],\n\t\t\t\t[AS_IF([test \"x$with_vv\" = xyes],\n\t\t\t\t       [purple_has_media=yes\n\t\t\t\t        AC_MSG_RESULT([yes - enabling voice and video support for cross compiling on users' request.])],\n\t\t\t\t       [AC_MSG_RESULT([no - disabled for cross compiling.])])\n\t\t\t\t]\n\t\t        )\n\t\t\tAS_IF([test \"x$purple_has_media\" = xyes],\n\t\t\t\t[PKG_CHECK_MODULES(NICE, [nice >= 0.1.0],\n\t\t\t\t\tdnl sipe-media.c uses g_slist_free_full()\n\t\t\t\t\t[PKG_CHECK_MODULES(_SIPE_MEDIA_RECHECK_PLEASE_IGNORE, [$purple_pkgconfig >= 2.8.0],\n\t\t\t\t\t\tdnl check purple pkgconfig for gstreamer version\n\t\t\t\t\t\t[gstreamer_pkgconfig=`$PKG_CONFIG --variable=gstreamer $purple_pkgconfig`\n\t\t\t\t\t\tAS_IF([test \"x$gstreamer_pkgconfig\" == x],\n\t\t\t\t\t\t\t[AS_IF([test \"x$purple_pkgconfig\" == xpurple-3],\n\t\t\t\t\t\t\t\t[gstreamer_pkgconfig=1.0])])\n\t\t\t\t\t\tAS_IF([test \"x$gstreamer_pkgconfig\" == x1.0],\n\t\t\t\t\t\t\t[gstreamer_pkgconfig=\"gstreamer-$gstreamer_pkgconfig gstreamer-rtp-$gstreamer_pkgconfig\"\n\n\t\t\t\t\t\t\tAC_MSG_NOTICE([using packages \"$gstreamer_pkgconfig\".])\n\t\t\t\t\t\t\tPKG_CHECK_MODULES(GSTREAMER, [$gstreamer_pkgconfig],\n\t\t\t\t\t\t\t\t[PKG_CHECK_MODULES(FARSTREAM, [farstream-0.2],\n\t\t\t\t\t\t\t\t\t[with_purple_vv=yes\n\n\t\t\t\t\t\t\t\t\t AC_COMPILE_IFELSE(\n\t\t\t\t\t\t\t\t\t \t [AC_LANG_PROGRAM([[\n#include <media.h>\n\t\t\t\t\t\t\t\t\t\t\t]],\n\t\t\t\t\t\t\t\t\t\t\t[[return (PURPLE_MEDIA_NETWORK_PROTOCOL_TCP_PASSIVE);]]\n\t\t\t\t\t\t\t\t\t\t )],\n\t\t\t\t\t\t\t\t\t\t [AC_DEFINE(HAVE_PURPLE_NEW_TCP_ENUMS, 1, [Define if libpurple has new TCP enums in media backend.])]\n\t\t\t\t\t\t\t\t\t)],\n\t\t\t\t\t\t\t\t\t[AC_MSG_NOTICE(Farstream required: disabling purple voice and video support)])],\n\t\t\t\t\t\t\t\t[AC_MSG_NOTICE(GStreamer required: disabling purple voice and video support)])],\n\t\t\t\t\t\t\t[AC_MSG_NOTICE(your purple hasn't been compiled against GStreamer 1.0: disabling purple voice and video support)])],\n\t\t\t\t\t\t[AC_MSG_NOTICE(libpurple >= 2.8.0 required: disabling purple voice and video support)])],\n\t\t\t\t\t[AC_MSG_NOTICE(libnice required: disabling purple voice and video support)])\n\t\t\t\t])\n\t\t       ])\n\n\t\t dnl SRTP and XDATA require media backend\n\t\t AS_IF([test \"x$with_purple_vv\" != xno],\n\t\t\t[AC_LINK_IFELSE(\n\t\t\t\t[AC_LANG_PROGRAM([[\n#include <media.h>\n\t\t\t\t\t]],\n\t\t\t\t\t[[purple_media_set_encryption_parameters(NULL, \"\", \"\", \"\", \"\", 0);\n\t\t\t\t\t  purple_media_set_decryption_parameters(NULL, \"\", \"\", \"\", \"\", \"\", 0);]]\n\t\t\t\t )],\n\t\t\t\t [AC_DEFINE(HAVE_SRTP, 1, [Define if we have SRTP support in media backend.])]\n\t\t\t )\n\n\t\t\t AC_COMPILE_IFELSE(\n\t\t\t\t[AC_LANG_PROGRAM([[\n#include <media.h>\n\t\t\t\t\t]],\n\t\t\t\t\t[[return (PURPLE_MEDIA_APPLICATION);]]\n\t\t\t\t )],\n\t\t\t\t [dnl libpurple supports raw data RTP connections\n\t\t\t\t  ac_have_xdata=yes\n\n\t\t\t\t  dnl gio-2.0 is mandatory for application sharing support\n\t\t\t\t  PKG_CHECK_MODULES(GIO, [gio-2.0],\n\t\t\t\t\t[ac_have_appshare=yes\n\n\t\t\t\t\t dnl freerdp-shadow2 & winpr2 is mandatory for appshare server support\n\t\t\t\t\t PKG_CHECK_MODULES(FREERDP_SHADOW, [freerdp-shadow2 winpr2],\n\t\t\t\t\t\t[ac_have_appshare_server=yes],\n\t\t\t\t\t\t[ac_have_appshare_server=no])\n\t\t\t\t   ])\n\t\t\t\t ]\n\t\t\t )\n\t\t\t],\n\t\t\t[AS_IF([test \"x$with_vv\" = xyes], dnl explicitly requested by user\n\t\t\t\t[AC_ERROR([Voice and video support explicitly requested, but not available])]\n\t\t\t )]\n\t\t )\n\n\t\t CFLAGS=\"$ac_save_CFLAGS\"\n\t\t LIBS=\"$ac_save_LIBS\"])])\nAM_CONDITIONAL(SIPE_INCLUDE_PURPLE, [test \"x$enable_purple\" != xno])\nAM_CONDITIONAL(SIPE_PURPLE3, [test \"x$purple_pkgconfig\" = xpurple-3])\n\ndnl build option: telepathy backend\nAC_ARG_ENABLE([telepathy],\n\t[AC_HELP_STRING([--enable-telepathy], [build telepathy plugin @<:@default=yes@:>@])],\n\t[],\n\t[enable_telepathy=yes])\nAS_IF([test \"x$enable_telepathy\" != xno],\n\t[PKG_CHECK_MODULES(TELEPATHY_GLIB, [telepathy-glib >= 0.24.0],\n\t\t[dnl GMIME is a build requirement\n\t\t AS_IF([test \"x$ac_have_gmime\" = xyes],\n\t\t\t[],\n\t\t\t[AC_ERROR(GMIME package is required for telepathy plugin)])\n\n\t\t dnl telepathy is based on GObject & D-Bus GLib\n\t\t PKG_CHECK_MODULES(GOBJECT, [gobject-2.0])\n\t\t PKG_CHECK_MODULES(DBUS_GLIB, [dbus-glib-1])\n\n\t\t dnl telepathy uses from gio:\n\t\t dnl  - GIOStream      (>= 2.22.0)\n\t\t dnl  - GResolver      (>= 2.22.0)\n\t\t dnl  - GSocketClient  (>= 2.32.0)\n\t\t dnl  - GTlsConnection (>= 2.28.0)\n\t\t PKG_CHECK_MODULES(GIO, [gio-2.0 >= 2.32.0])\n\n\t\t],\n\t\t[enable_telepathy=no])])\nAM_CONDITIONAL(SIPE_INCLUDE_TELEPATHY, [test \"x$enable_telepathy\" != xno])\n\ndnl sanity check\nAS_IF([test \"x$enable_purple\" = xno -a \"x$enable_telepathy\" = xno],\n\t[AC_ERROR(at least one plugin must be selected\n\nIf you didn't use a --enable option then please check that you have\nthe headers for the packages \"purple\" or \"telepathy-glib\" installed.\n)],\n\t[])\n\ndnl enable voice & video support if any backend supports it\nAS_IF([test \"x$with_purple_vv\" != xno],\n\t[AC_DEFINE(HAVE_VV, 1, [Define if voice & video is enabled.])])\nAM_CONDITIONAL(SIPE_WITH_VV, [test \"x$with_purple_vv\" != xno])\n\ndnl raw data RTP streams enable Lync file transfer\nAM_CONDITIONAL(SIPE_HAVE_XDATA, [test \"x$ac_have_xdata\" == xyes])\nAS_IF([test \"x$ac_have_xdata\" == xyes],\n\t[AC_DEFINE(HAVE_XDATA, 1, [Define if we have raw data RTP in media backend.])])\n\ndnl enable appshare support\nAM_CONDITIONAL(SIPE_HAVE_APPSHARE, [test \"x$ac_have_appshare\" == xyes])\nAS_IF([test \"x$ac_have_appshare\" == xyes],\n\t[AC_DEFINE(HAVE_APPSHARE, 1, [Define to 1 if we have appshare support.])])\n\ndnl RDP server for sharing local desktop\nAM_CONDITIONAL(SIPE_HAVE_APPSHARE_SERVER, [test \"x$ac_have_appshare_server\" = xyes])\nAS_IF([test \"x$ac_have_appshare_server\" == xyes],\n\t[AC_DEFINE(HAVE_APPSHARE_SERVER, 1, [Define if appshare server is enabled.])])\n\ndnl libpurple API relies on GParameter (deprecated in glib-2.0 >= 2.62.0)\nAS_IF([test \"x$enable_purple\" != xno],\n\t[AC_DEFINE(GLIB_VERSION_MIN_REQUIRED, GLIB_VERSION_2_60,\n\t\t   [We need GParameter for which no replacement is available])\n\t])\ndnl telepathy code parts rely on interfaces that require GValueArray. This\ndnl type has been declared \"deprectated\" in glib-2.0 >= 2.32.0, but there\ndnl is no backward compatible replacement implementation possible\ndnl telepathy-glib API relies on GTimeVal (deprecated in glib-2.0 >= 2.62.0)\nAS_IF([test \"x$enable_telepathy\" != xno],\n\t[AC_DEFINE(GLIB_VERSION_MIN_REQUIRED, GLIB_VERSION_2_30,\n\t\t   [We need GValueArray for which no replacement is available])\n\t])\ndnl libpurple 2.x API relies on G_CONST_RETURN (deprecated in glib-2.0 >= 2.30.0)\nAS_IF([test \"x$purple_pkgconfig\" == xpurple],\n\t[AC_DEFINE(GLIB_VERSION_MIN_REQUIRED, GLIB_VERSION_2_28,\n\t\t   [libpurple 2.x API uses G_CONST_RETURN])\n\t])\n\ndnl i18n\nAC_MSG_CHECKING([locale_CPPFLAGS])\nLOCALE_CPPFLAGS='-DLOCALEDIR=\\\"$(datadir)/locale\\\"'\nAC_SUBST([LOCALE_CPPFLAGS])\nAC_MSG_RESULT([$LOCALE_CPPFLAGS])\nAM_GNU_GETTEXT([external])\nAM_GNU_GETTEXT_VERSION([0.19.8])\nAC_SUBST(GETTEXT_PACKAGE, \"${PACKAGE_NAME}\")\n\ndnl substitutions and generated files\nAC_CONFIG_HEADERS([config.h])\nAC_CONFIG_FILES([\n\tMakefile\n\tpixmaps/Makefile\n\tpo/Makefile.in\n\tpixmaps/16/Makefile\n\tpixmaps/22/Makefile\n\tpixmaps/24/Makefile\n\tpixmaps/32/Makefile\n\tpixmaps/48/Makefile\n\tpixmaps/scalable/Makefile\n\tsrc/Makefile\n\tsrc/core/Makefile\n\tsrc/api/Makefile\n\tsrc/purple/Makefile\n\tsrc/telepathy/Makefile\n\tsrc/telepathy/data/Makefile\n\t])\n\ndnl generate files\nAC_OUTPUT()\n\ndnl additional info for the user\nAS_ECHO()\nAS_IF([test \"x$enable_purple\" = xno],\n\t[AS_ECHO(\"Not building purple plugin\")],\n\t[AS_ECHO(\"Build purple plugin\")\n\t AS_ECHO(\"PURPLE_CFLAGS  : $PURPLE_CFLAGS\")\n\t AS_ECHO(\"PURPLE_LIBS    : $PURPLE_LIBS\")\n\t AS_ECHO_N(\"Voice and video: \")\n\t AS_IF([test \"x$with_purple_vv\" = xno],\n\t  [AS_ECHO(\"disabled\")],\n\t  [AS_ECHO(\"enabled\")])\n\t])\nAS_ECHO()\nAS_IF([test \"x$enable_telepathy\" = xno],\n\t[AS_ECHO(\"Not building telepathy plugin\")],\n\t[AS_ECHO(\"Build telepathy plugin\")\n\t AS_ECHO(\"TELEPATHY_GLIB_CFLAGS: $TELEPATHY_GLIB_CFLAGS\")\n\t AS_ECHO(\"TELEPATHY_GLIB_LIBS  : $TELEPATHY_GLIB_LIBS\")])\nAS_ECHO()\nAS_IF([test \"x$with_krb5\" = xno],\n\t[AS_ECHO(\"Not building with Kerberos 5 support\")],\n\t[AS_ECHO(\"Build with Kerberos 5 support\")\n\t AS_ECHO(\"KRB5_CFLAGS    : $KRB5_CFLAGS\")\n\t AS_ECHO(\"KRB5_LDFLAGS   : $KRB5_LDFLAGS\")])\nAS_ECHO()\nAS_IF([test \"x$enable_gssapi_only\" = xno],\n\t[AS_ECHO(\"Using internal authentication implementation\")],\n\t[AS_ECHO(\"Using only GSSAPI for authentication\")])\nAS_ECHO()\nAS_IF([test \"x$enable_debug\" = xno],\n\t[AS_ECHO(\"Debugging not enabled\")],\n\t[AS_ECHO(\"Build with debugging enabled\")\n\t AS_ECHO(\"DEBUG_CFLAGS   : $DEBUG_CFLAGS\")])\nAS_ECHO()\nAS_IF([test \"x$QUALITY_CFLAGS\" = x],\n\t[AS_ECHO(\"Compiler checks disabled\")],\n\t[AS_ECHO(\"Build with compiler checks enabled\")\n\t AS_ECHO(\"QUALITY_CFLAGS : $QUALITY_CFLAGS\")])\nAS_ECHO()\nAS_ECHO(\"configure complete. Now run 'make'\")\nAS_ECHO()\n\ndnl The End.\n"
  },
  {
    "path": "contrib/dbus/SipeHelper.pm",
    "content": "#!/usr/bin/perl -w\n#\n# @file SipeHelper.pm\n#\n# pidgin-sipe\n#\n# Copyright (C) 2017 SIPE Project <http://sipe.sourceforge.net/>\n#\n# This program is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, write to the Free Software\n# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n#\n#\n# Support code for D-Bus test scripts\n#\npackage SipeHelper;\nuse 5.024;\nuse strict;\nuse warnings;\n\nuse Carp;\nuse Net::DBus;\n\n# Connect to libpurple over the session bus\nmy $purple;\nsub init()\n{\n    eval {\n\tmy $bus     = Net::DBus->session;\n\tmy $service = $bus->get_service('im.pidgin.purple.PurpleService');\n\t$purple     = $service->get_object('/im/pidgin/purple/PurpleObject',\n\t\t\t\t\t   'im.pidgin.purple.PurpleInterface');\n    };\n    die \"ERROR: can't find any active libpurple D-Bus instance, Are you sure you started Pidgin/Finch?\\n\\n$@\"\n\tif $@;\n}\n\n# Call code reference for all active SIPE accounts\nsub forSipeAccounts($)\n{\n    my($code) = @_;\n    croak \"ERROR: ${code} should be code reference\"\n\tunless ref($code) eq \"CODE\";\n    croak \"ERROR: called without initializing\"\n\tunless $purple;\n\n    # Get list of enabled accounts\n    my $accounts = $purple->PurpleAccountsGetAllActive();\n    for my $accountId (@{ $accounts }) {\n\tmy $username     = $purple->PurpleAccountGetUsername($accountId);\n\tmy $protocolId   = $purple->PurpleAccountGetProtocolId($accountId);\n\tmy $protocolName = $purple->PurpleAccountGetProtocolName($accountId);\n\tmy $connectionId = $purple->PurpleAccountGetConnection($accountId);\n\tprint \"found account ${accountId}: ${username} (${protocolId}/${protocolName}, ${connectionId})\\n\";\n\n\t# Filter out SIPE accounts that are online\n\tif (($protocolId eq 'prpl-sipe') && ($connectionId != 0)) {\n\n\t    # Filter out SIPE accounts that are really connected\n\t    if ($purple->PurpleConnectionIsConnected($connectionId)) {\n\n\t\t# Call code reference\n\t\t$code->($purple, $accountId, $username);\n\t    }\n\t}\n    }\n}\n\n# modules need to return a true value\n1;\n"
  },
  {
    "path": "contrib/dbus/sipe-call-phone-number.pl",
    "content": "#!/usr/bin/perl -w\n#\n# @file sipe-call-phone-number.pl\n#\n# pidgin-sipe\n#\n# Copyright (C) 2017 SIPE Project <http://sipe.sourceforge.net/>\n#\n# This program is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, write to the Free Software\n# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n#\n#\n# Test code for D-Bus interface \"SipeCallPhoneNumber\"\n#\nuse 5.024;\nuse strict;\nuse warnings;\n\nuse FindBin;\nuse lib $FindBin::Bin;\nuse SipeHelper;\n\n# Check command line parameters\ndie \"usage: $0 <phone number>>\\n\"\n    unless @ARGV >= 1;\nmy($number) = @ARGV;\n\nSipeHelper::init();\nSipeHelper::forSipeAccounts(sub {\n    my($purple, $accountId, $username) = @_;\n    print \"Trying to call phone number '${number}' on SIPE account '${username}'...\\n\";\n    $purple->SipeCallPhoneNumber($accountId, $number);\n});\n\n# That's all folks...\nexit 0;\n"
  },
  {
    "path": "contrib/dbus/sipe-join-conference-with-organizer-and-id.pl",
    "content": "#!/usr/bin/perl -w\n#\n# @file sipe-join-conference-with-organizer-and-id.pl\n#\n# pidgin-sipe\n#\n# Copyright (C) 2017 SIPE Project <http://sipe.sourceforge.net/>\n#\n# This program is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, write to the Free Software\n# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n#\n#\n# Test code for D-Bus interface \"SipeJoinConferenceWithOrganizerAndId\"\n#\nuse 5.024;\nuse strict;\nuse warnings;\n\nuse FindBin;\nuse lib $FindBin::Bin;\nuse SipeHelper;\n\n# Check command line parameters\ndie \"usage: $0 <organizer account> <meeting ID>\\n\"\n    unless @ARGV >= 2;\nmy($organizer, $id) = @ARGV;\n\nSipeHelper::init();\nSipeHelper::forSipeAccounts(sub {\n    my($purple, $accountId, $username) = @_;\n    print \"Trying to join ${organizer}'s conference '${id}' on SIPE account '${username}'...\\n\";\n    $purple->SipeJoinConferenceWithOrganizerAndId($accountId, $organizer, $id);\n});\n\n# That's all folks...\nexit 0;\n"
  },
  {
    "path": "contrib/dbus/sipe-join-conference-with-uri.pl",
    "content": "#!/usr/bin/perl -w\n#\n# @file sipe-join-conference-with-uri.pl\n#\n# pidgin-sipe\n#\n# Copyright (C) 2017 SIPE Project <http://sipe.sourceforge.net/>\n#\n# This program is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, write to the Free Software\n# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n#\n#\n# Test code for D-Bus interface \"SipeJoinConferenceWithUri\"\n#\nuse 5.024;\nuse strict;\nuse warnings;\n\nuse FindBin;\nuse lib $FindBin::Bin;\nuse SipeHelper;\n\n# Check command line parameters\ndie \"usage: $0 <conference URI> [<conference URI> ...]\\n\"\n    unless @ARGV;\n\nSipeHelper::init();\nSipeHelper::forSipeAccounts(sub {\n    my($purple, $accountId, $username) = @_;\n    for my $uri (@ARGV) {\n\tprint \"Trying to join conference '${uri}' on SIPE account '${username}'...\\n\";\n\t$purple->SipeJoinConferenceWithUri($accountId, $uri);\n    }\n});\n\n# That's all folks...\nexit 0;\n"
  },
  {
    "path": "contrib/dbus/sipe-republish-calendar.pl",
    "content": "#!/usr/bin/perl -w\n#\n# @file sipe-republish-calendar.pl\n#\n# pidgin-sipe\n#\n# Copyright (C) 2017 SIPE Project <http://sipe.sourceforge.net/>\n#\n# This program is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, write to the Free Software\n# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n#\n#\n# Test code for D-Bus interface \"SipeRepublishCalendar\"\n#\nuse 5.024;\nuse strict;\nuse warnings;\n\nuse FindBin;\nuse lib $FindBin::Bin;\nuse SipeHelper;\n\nSipeHelper::init();\nSipeHelper::forSipeAccounts(sub {\n    my($purple, $accountId, $username) = @_;\n    print \"Trying to republish calendar data on SIPE account '${username}'...\\n\";\n    $purple->SipeRepublishCalendar($accountId);\n});\n\n# That's all folks...\nexit 0;\n"
  },
  {
    "path": "contrib/dbus/sipe-reset-status.pl",
    "content": "#!/usr/bin/perl -w\n#\n# @file sipe-reset-status.pl\n#\n# pidgin-sipe\n#\n# Copyright (C) 2017 SIPE Project <http://sipe.sourceforge.net/>\n#\n# This program is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, write to the Free Software\n# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n#\n#\n# Test code for D-Bus interface \"SipeResetStatus\"\n#\nuse 5.024;\nuse strict;\nuse warnings;\n\nuse FindBin;\nuse lib $FindBin::Bin;\nuse SipeHelper;\n\nSipeHelper::init();\nSipeHelper::forSipeAccounts(sub {\n    my($purple, $accountId, $username) = @_;\n    print \"Trying to reset status on SIPE account '${username}'...\\n\";\n    $purple->SipeResetStatus($accountId);\n});\n\n# That's all folks...\nexit 0;\n"
  },
  {
    "path": "contrib/debian/changelog",
    "content": "pidgin-sipe (1.25.0-1) unstable; urgency=low\n\n  * New version 1.25.0 \"Buddy Idle Time, RTF\" (2019-10-12)\n\t- Feature #107: Provide idle start time for a buddy (Stefan Becker)\n\t- Feature #77: RTF support (incoming) (Stefan Becker)\n\t  * the code only extracts plain text from incoming RTF\n\t- Fixed #358: FTBFS with glib-2.0 >= 2.62.0 (Stefan Becker)\n\t- Fixed #350: Inconsistent parsing of From:/To: headers (Stefan Becker)\n\t- raise BR telepathy-glib >= 0.24.0 (Stefan Becker)\n\t- switch from GPLv2+ to SPDX identifier GPL-2.0-or-later (Stefan Becker)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 12 Oct 2019 11:43:00 +0300\n\npidgin-sipe (1.24.0-1) unstable; urgency=low\n\n  * New version 1.24.0 \"Application Sharing II\" (2018-11-10)\n\t- Feature #104: Use user agent also for HTTP (Stefan Becker)\n\t- Feature #6: Application Sharing Server (Jakub Adam)\n\t  * requires freerdp-shadow2\n\t- Fixed #343: Build fails on FreeBSD\n\t- add timeout handling for media streams (Alaoui Youness)\n\t- update AppStream handling (Jakub Adam, Stefan Becker)\n\t- fix missing localisation in some code modules (Stefan Becker)\n\t- debug log improvements (Stefan Becker)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 10 Nov 2018 17:38:00 +0200\n\npidgin-sipe (1.23.3-1) unstable; urgency=low\n\n  * New version 1.23.3 \"Bug Fixes III\" (2018-08-20)\n\t- appshare: fix black screen with Remmina v1.2.0-rcgit.27 (Jakub Adam)\n\t- various minor fixes (Jakub Adam, Michael Olbrich)\n\t- fix compilation errors with libpurple 2.14.0 & GCC 8.0 (Jakub Adam, Stefan Becker)\n\t- mingw: update fetch script to Pidgin 2.13.0 (Stefan Becker)\n\n -- Stefan Becker <chemobejk@gmail.com>  Mon, 20 Aug 2018 16:56:00 +0300\n\npidgin-sipe (1.23.2-1) unstable; urgency=low\n\n  * New upstream version 1.23.2 \"Bug Fixes II\" (2018-03-10)\n\t- fix some HTTP requests that were not sent (Jakub Adam, Stefan Becker)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 10 Mar 2018 17:52:35 +0200\n\npidgin-sipe (1.23.1-1) unstable; urgency=low\n\n  * New upstream version 1.23.1 \"Bug Fixes I\" (2018-02-25)\n\t- Fixed #338: Incorrect port 0 for IPv6 socket on Windows (Stefan Becker)\n\t- Fixed #337: Duplicate candidates in SDP (Jakub Adam, Stefan Becker)\n\t- Fixed #336: Lync autodiscover does not follow user redirect (Stefan Becker)\n\t- media: unconditionally ignore multichannel codecs (Jakub Adam)\n\t- updated translations: Turkish (tr)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sun, 25 Feb 2018 15:05:00 +0200\n\npidgin-sipe (1.23.0-1) unstable; urgency=low\n\n  * New upstream version 1.23.0 \"D-Bus, IPv6, OS X 10.11+\" (2017-10-28)\n\t- Feature #101: Mac OS X 10.13 OpenSSL support (Stefan Becker)\n\t- Feature #100: Extend libpurple D-Bus interface (Stefan Becker)\n\t- Feature #99: IPv6 addresses in SIP & SDP messages (Stefan Becker)\n\t- Feature #96: Support for OS X 10.11+ SDK (Stefan Becker)\n\t- don't load buddy photos from unknown sites by default (Jakub Adam, Stefan Becker)\n\t  * custom web URIs pose a security risk as they may be abused\n\t  * users can override this behaviour in the account settings\n\t  * Office365 accounts should not be affected by this change\n\t- add support for GMime 3.0 API (Stefan Becker)\n\t- raise BR glib-2.0 >= 2.18.0 (Stefan Becker)\n\t- raise BR purple >= 2.7.0 (Stefan Becker)\n\t- drop support for GMime 2.4 (Stefan Becker)\n\t- drop support for gstreamer-0.10 (Stefan Becker)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 28 Oct 2017 18:16:00 +0300\n\npidgin-sipe (1.22.1-1) unstable; urgency=low\n\n  * New upstream version 1.22.1 \"Bug Fixes I\" (2017-06-11)\n\t- Fixed #320: Multiple client detection broken (Stefan Becker)\n\t- speed up Lync Autodiscover by using AccessLocation (Andrey Vaynberger)\n\t- adium: update build instructions for Xcode 7.x or newer (Stefan Becker)\n\t  * the build environment used for releases 1.22.0 or older (Xcode 6.x\n\t    on OS X 10.11) is no longer available to the project\n\t  * releases starting with 1.22.1 will use Xcode 8.x on macOS 10.12\n\t  * build target continues to be OS X 10.9\n\t- purple: avoid rare SSL read deadlock (Stefan Becker)\n\t- various minor fixes (Michael Olbrich)\n\t- crypto: make code compile with OpenSSL 1.1.0 (Stefan Becker)\n\t- drop references to Reuters Messaging (Stefan Becker)\n\t- updated translations: Lithuanian (lt), Russian (ru), Swedish (sv), Turkish (tr)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sun, 11 Jun 2017 18:38:00 +0300\n\npidgin-sipe (1.22.0-1) unstable; urgency=low\n\n  * New upstream version 1.22.0 \"Application Sharing, Lync Autodiscover & Logging\" (2017-02-01)\n\t- Feature #93: Support for Lync Autodiscover (Stefan Becker)\n\t- Feature #6: Application Sharing Viewer (Jakub Adam)\n\t  * requires libpurple >= 2.12.0\n\t  * needs an external RDP client - remmina and xfreerdp are supported\n\t- Fixed #315: Crash when contact list is empty (Stefan Becker)\n\t- Fixed #314: sipe login problems with long pw (Stefan Becker)\n\t- separate logging and debugging output (Stefan Becker)\n\t  * logging is always shown, e.g. in the Pidgin debug window\n\t  * full message debugging now requires PURPLE_UNSAFE_DEBUG=1\n\t- new translations: Greek (el), Lithuanian (lt)\n\n -- Stefan Becker <chemobejk@gmail.com>  Wed, 01 Feb 2017 18:57:00 +0200\n\npidgin-sipe (1.21.1-1) unstable; urgency=low\n\n  * New upstream version 1.21.1 \"Bug Fixes I\" (2016-05-28)\n\t- various bug fixes in media support (Jakub Adam)\n\t- configure no longer ignores CFLAGS/LDFLAGS/LIBS (Stefan Becker)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 28 May 2016 18:19:00 +0300\n\npidgin-sipe (1.21.0-1) unstable; urgency=low\n\n  * New upstream version 1.21.0 \"Lync File Transfer\" (2016-04-23)\n\t- Feature #91: Support embedded XML as buddy photo URL (Stefan Becker)\n\t- Feature #90: Add AppStream metadata file (Jiri Eischmann, Stefan Becker)\n\t- Feature #89: Improve \"Join scheduled conference\" dialog  (Stefan Becker)\n\t- Feature #87: Support multiple HTTP cookies (Stefan Becker)\n\t- Feature #85: XML raw extract should ignore name space (Stefan Becker)\n\t- Fixed #311: Crash when SIP transport becomes invalid (Stefan Becker)\n\t- Fixed #293: Mandatory wsa:MessageID node missing (Stefan Becker)\n\t- add support for Lync File Transfer protocol (Jakub Adam)\n\t  * requires libpurple >= 2.12.0\n\t  * Lync FT will be used for sending files when Lync 2013 is detected\n\t- add build options to \"About SIPE plugin\" message (Stefan Becker)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 23 Apr 2016 15:55:00 +0300\n\npidgin-sipe (1.20.1-1) unstable; urgency=low\n\n  * New upstream version 1.20.1 \"Bug Fixes I\" (2015-10-24)\n\t- add support for another type of ADFS response (Stefan Becker)\n\t- improve configure check for back-ported features (Stefan Becker, Jakub Adam)\n\t- updated translations: French (fr), Russian (ru)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 24 Oct 2015 15:20:00 +0300\n\npidgin-sipe (1.20.0-1) unstable; urgency=low\n\n  * New upstream version 1.20.0 \"SRTP, Conference URL & TLS-DSK Improvements\" (2015-08-29)\n\t- Feature #82: Parse HTML from Lync conference URL (Stefan Becker)\n\t- Feature #69: SRTP Support (Jakub Adam)\n\t  * requires libpurple >= 3.0.0\n\t- Fixed #285: Office365 rejects RC4 in TLS-DSK (Stefan Becker)\n\t  * added support for AES-128/256-CBC\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 29 Aug 2015 18:07:00 +0300\n\npidgin-sipe (1.19.1-1) unstable; urgency=low\n\n  * New upstream version 1.19.1 \"Bug Fixes I\" (2015-04-04)\n\t- Fixed #278: 488 error after libnice upgrade (Jakub Adam)\n\t- fix SIP re-authentication timeout to be max. 8 hours (Stefan Becker)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 04 Apr 2015 17:05:00 +0300\n\npidgin-sipe (1.19.0-1) unstable; urgency=low\n\n  * New upstream version 1.19.0 \"Auto Authentication, MFA & Search Improvements\" (2015-02-07)\n\t- Feature #80: Move parsing of login name (Stefan Becker)\n\t- Feature #79: support for Adium group chat bookmarks (David Matz, Stefan Becker)\n\t- Feature #78: Support searching for SIP ID (Stefan Becker)\n\t- Feature #76: ADFS can't always be used (Stefan Becker)\n\t  * for accounts that have Multi-Factor Authentication (MFA) enabled\n\t- Feature #73: Support buddy photos from contactCard (Stefan Becker)\n\t- Feature #65: Fall back from Kerberos to NTLM (Stefan Becker)\n\t- Fixed #277: Raised contact names (Stefan Becker)\n\t- Fixed #240: Corrupted HTTP response crashes SIPE (Stefan Becker)\n\t- fix calendar state machine when EWS URL is set (Stefan Becker)\n\t- fall back to [MS-DLX] BasicSearch to improve search experience (Stefan Becker, various)\n\t- implement search functionality for UCS (Stefan Becker)\n\t- adium: add chat room list UI (David Matz)\n\t- adium: fix duplicate debug log messages (Stefan Becker)\n\t- support for libnice TCP mode (Youness Alaoul, Jakub Adam)\n\t- refactor CCCP request code (Jakub Adam)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 07 Feb 2015 13:48:00 +0200\n\npidgin-sipe (1.18.5-1) unstable; urgency=low\n\n  * New upstream version 1.18.5 \"Bug Fixes V\" (2014-12-29)\n\t- Fixed #276: Redundant \"const\" breaks build with clang (Stefan Becker)\n\t- Fixed #269: purple idle-away converted to Away (Stefan Becker)\n\t- svc: use authuser for RealmInfo request (Stefan Becker)\n\t- adium: add release checking script (Stefan Becker)\n\t- mingw: update fetch script to Pidgin 2.10.11 (Stefan Becker)\n\t- updated translations: Italian (it), Swedish (sv)\n\n -- Stefan Becker <chemobejk@gmail.com>  Mon, 29 Dec 2014 21:04:00 +0200\n\npidgin-sipe (1.18.4-1) unstable; urgency=low\n\n  * New upstream version 1.18.4 \"Bug Fixes IV\" (2014-10-18)\n\t- Fixed #263: ADFS fails when user and login name differ (Stefan Becker)\n\t- Fixed #262: Adium: SIPE doesn't auto- or re-connect (Stefan Becker)\n\t- fixed memory leaks (Stefan Becker)\n\t- fixed processing of presence publish event response (John Zhang, Stefan Becker)\n\t  * fixes a longstanding issue that the Pidgin user status sometimes\n\t    didn't switch back to \"Available\" after the end of a meeting\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 18 Oct 2014 17:24:00 +0300\n\npidgin-sipe (1.18.3-1) unstable; urgency=low\n\n  * New upstream version 1.18.3 \"Bug Fixes III\" (2014-08-16)\n\t- Fixed #259: HTML response to EWS autodiscover triggers libxml2 assert (Stefan Becker)\n\t- Fixed #258: V&V call gets rejected when IPv6 is enabled (Stefan Becker, Jakub Adam)\n\t- Fixed #257: Windows 7: SIPE crashes after a minute (Stefan Becker)\n\t- mingw: improve crash information reporting (Stefan Becker)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 16 Aug 2014 14:31:00 +0300\n\npidgin-sipe (1.18.2-1) unstable; urgency=low\n\n  * New upstream version 1.18.2 \"Bug Fixes II\" (2014-06-07)\n\t- Fixed #255: Crash when PersistentChat sends BYE instead of response (Stefan Becker)\n\t- Fixed #248: Remove libpurple SSL configure check (Stefan Becker)\n\t- Fixed #245: \"Unable to resolve DNS SRV record\" error when joining conference (Stefan Becker)\n\t- Fixed #241: Adium filters \":\" from \"sip:\" (Stefan Becker)\n\t- Fixed #210: Conference call ends with error message (for real this time, Jakub Adam)\n\t- ews: extract settings also from type EXPR (Stefan Becker)\n\t- ucs: honor user specified email URL (Stefan Becker)\n\t- adium: fix compilation on OS X 10.7 (Stefan Becker)\n\t- updated Transifex URLs (Stefan Becker)\n\t- updated translations: Hindi (hi), Telugu (te)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 07 Jun 2014 12:29:00 +0300\n\npidgin-sipe (1.18.1-1) unstable; urgency=low\n\n  * New upstream version 1.18.1 \"Bug Fixes I\" (2014-04-12)\n\t- Fixed #238: False \"not delivered\" in conference (Stefan Becker)\n\t- Fixed #237: HTML escaping not removed from URL (Stefan Becker)\n\t- Fixed #210: Conference call ends with error message (Jakub Adam)\n\t- fix endless loop with failed HTTP Basic authentication (Stefan Becker)\n\t- fix crash when gstreamer nice plugin is missing (Stefan Becker, Jakub Adam)\n\t- fix EWS autodiscover for some Office 365 users (Stefan Becker)\n\t- purple: fix missing \"Copy to\" in buddy menu (Stefan Becker)\n\t- purple/adium: ignore empty search values (Stefan Becker)\n\t- adium: fix group chat UI (Stefan Becker)\n\t- adium: implement BEAST mitigations for 10.8.5 (Michael Lamb)\n\t- add indication when user is connected from a mobile device (Harris Kauffman)\n\t- updated translations: Chinese (zh_CN), Portuguese (pt)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 12 Apr 2014 17:54:00 +0300\n\npidgin-sipe (1.18.0-1) unstable; urgency=low\n\n  * New upstream version 1.18.0 \"Adium, GSS-NTLMSSP & OpenSSL\" (2014-01-11)\n\t- Feature #71: Add support for EWS Autodiscover redirection (Stefan Becker)\n\t- Feature #69: Add UI support for (group) chats (Michael Lamb)\n\t  * NOTE: Adium does not have an UI to fetch the room list\n\t- Feature #64: Add support for GSS-NTLMSSP (Stefan Becker)\n\t  * sip-sec-krb5.c module has been renamed to sip-sec-gssapi.c\n\t  * if gssapi/gssapi_ntlmssp.h is detected then sip-sec-ntlm.c will\n\t    be disabled and NTLM will be handled by sip-sec-gssapi.c instead\n\t  * NOTE: at the time of this writing the user has to set up\n\t          GSS-NTLMSSP by hand on his system, i.e. /etc/gss/mech\n\t- Fixed #227: Adium client doesn't save email option settings (Harris P. Kauffman)\n\t- Fixed #216: SIPE stops working on Mavericks (Stefan Becker, Michael Lamb)\n\t  * add an UI option to disable SSL BEAST mitigations\n\t  * NOTE: requires Adium 1.5.10\n\t- Fixed #197: Account stays in connecting stage (Harris P. Kauffman)\n\t- cleanup for sip-sec Kerberos & SSPI modules (Stefan Becker)\n\t  * replace old TGT hack with gss_acquire_cred_with_password()\n\t  * clean up Kerberos detection in configure\n\t  * remove special case handling; code is more straight-forward now\n\t  * thanks to David Woodhouse and Simo Sorce for the GSSAPI information\n\t- implement internal keepalive handling (Stefan Becker)\n\t- implement crypto backend based on OpenSSL (Stefan Becker)\n\t- adium: Xcode project files update (Michael Lamb)\n\t- adium: replace NSS crypto backend with OpenSSL (Stefan Becker)\n\t  * NOTE: please make sure to read the updated build instructions!\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 11 Jan 2014 16:10:00 +0200\n\npidgin-sipe (1.17.3-1) unstable; urgency=low\n\n  * New upstream version 1.17.3 \"Bug Fixes III\" (2013-12-11)\n\t- Fixed #225: HTTP re-authentication with NTLM fails (Stefan Becker)\n\t- Fixed #222: SIPE crashes when groupchat session expires (Stefan Becker)\n\t- fix UCS Persona key extraction (Stefan Becker)\n\n -- Stefan Becker <chemobejk@gmail.com>  Wed, 11 Dec 2013 21:18:00 +0200\n\npidgin-sipe (1.17.2-1) unstable; urgency=low\n\n  * New upstream version 1.17.2 \"Bug Fixes II\" (2013-11-30)\n\t- Fixed #214: Typing notification does not always work (Stefan Becker)\n\t  * reverted one change which caused problems for some users\n\t- Fixed #222: SIPE crashes when groupchat session expires (Stefan Becker)\n\t- updated translations: Romanian (ro)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 30 Nov 2013 17:51:00 +0200\n\npidgin-sipe (1.17.1-1) unstable; urgency=low\n\n  * New upstream version 1.17.1 \"Bug Fixes I\" (2013-11-16)\n\t- Fixed #215: Password not entity encoded in WSSE element (Stefan Becker)\n\t- Fixed #214: Typing notification does not always work (Stefan Becker)\n\t- accept alternatives for webticket timestamp/keydata (Stefan Becker)\n\t- adium: add \"don't publish calendar\" to account UI (Stefan Becker)\n\t- contrib: add SSL BEAST mitigation patch for Adium (Stefan Becker)\n\t- updated translations: French (fr)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 16 Nov 2013 16:21:00 +0200\n\npidgin-sipe (1.17.0-1) unstable; urgency=low\n\n  * New upstream version 1.17.0 \"Lync 2013\" (2013-09-21)\n\t- Feature #62: Support for Lync 2013 Unified Contact Store (Stefan Becker)\n\t- Feature #59: Support for Lync 2013 Persistent Chats (Stefan Becker)\n\t- Fixed #211: Status \"away\" or \"busy\" incorrectly mapped to \"Invisible\" (Michael Lamb)\n\t- Fixed #209: group chat doesn't like HTML (Stefan Becker)\n\t- Fixed #200: OCS archiving system blocks audio/video connection (Jakub Adam)\n\t- Fixed #187: Duplicate messages in group chat (Stefan Becker)\n\t- Fixed #184: Duplicate users showing in Group Chat (Stefan Becker)\n\t- fix EWS autodiscover for Office 365 (Stefan Becker)\n\t- add support for group chat history (Stefan Becker)\n\t- add support for buddy photos on Lync 2013 (Stefan Becker)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 21 Sep 2013 16:34:00 +0300\n\npidgin-sipe (1.16.1-1) unstable; urgency=low\n\n  * New upstream version 1.16.1 \"Bug Fixes I\" (2013-07-13)\n\t- Feature #66: Windows DLL version information (Stefan Becker)\n\t- fix call failure when host has multiple IP addresses (Jakub Adam)\n\t- fix buddy list handling after moving to Lync 2013 (Stefan Becker)\n\t  * Lync 2013 migrates buddy list to Unified Contact Store (UCS)\n\t  * NOTE: modifying the buddy list is *NOT* supported yet!\n\t- crash fixes for new HTTP stack (Stefan Becker)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 13 Jul 2013 16:20:00 +0300\n\npidgin-sipe (1.16.0-1) unstable; urgency=low\n\n  * New upstream version 1.16.0 \"HTTP Rewrite & Subscription Fixes\" (2013-06-14)\n\t- Feature #58: Implement Digest authentication scheme for SIP Proxy Authentication (Stefan Becker)\n\t- Fixed #196: Useragent value not forwarded to core (Michael Lamb)\n\t- Fixed #193: Pidgin Status changes stop working (Stefan Becker)\n\t- Fixed #186: Users appear offline when they are not (Stefan Becker)\n\t- fix kinit-less use case with krb5 >= 1.11 (Stefan Becker)\n\t- rewritten HTTP stack from scratch (Stefan Becker)\n\t  * cleaner, layered and hopefully less error-prone implementation\n\t  * HTTP stack internals no longer exposed to user code\n\t  * reduced network traffic and less SSL handshakes by utilizing HTTP/1.1\n\t    connection keep alive for multiple HTTP requests to the same host\n\t- switch purple backend to deferred destruction approach (Stefan Becker)\n\t  * Pidgin should no longer crash at connection close, even in corner cases\n\t- add menu entry to make a call with a phone number (Jakub Adam)\n\t- some progress on telepathy backend (Stefan Becker)\n\t  * add TLS certificate accept/reject user interaction\n\t  * add \"Single Sign-On\" & \"Don't Publish Calendar\" account options\n\n -- Stefan Becker <chemobejk@gmail.com>  Fri, 14 Jun 2013 19:57:00 +0300\n\npidgin-sipe (1.15.1-1) unstable; urgency=low\n\n  * New upstream version 1.15.1 \"Bug Fixes I\"\n\t- NOTE: SIPE SourceForge project got updated. Because of this all bug\n\t        and feature request numbers have changed.\n\t- Fixed #190: SIP 407 response rejected with invalid message signature (Stefan Becker)\n\t- Fixed #189: Adium SIPE plugin vs. libpurple linking issues (Michael Lamb)\n\t- fixed free-after-use issue that caused crashes for some users (Stefan Becker)\n\t- fixed broken NTLM fallback in Negotiate (Stefan Becker)\n\t- fixed subscriptions expiration by subscribing again after re-authentication (Stefan Becker)\n\t- allow different user name and login for Office 365 authentication (Stefan Becker)\n\t- add SIPE version & git commit ID to debug log (Stefan Becker)\n\t- added valgrind log analyzer script (Stefan Becker)\n\t- added NTLM message anaylzer (Stefan Becker)\n\t- updated translations: Hungarion (hu), Romanian (ro)\n\t- updated Adium port (Michael Lamb, Harris P. Kauffman)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sun, 07 Apr 2013 15:09:00 +0300\n\npidgin-sipe (1.15.0-1) unstable; urgency=low\n\n  * New upstream version 1.15.0 \"Authentication & Autodiscovery Update\"\n\t- Feature #3578135: Support Kerberos for HTTP(S) authentication w/o SSPI (Stefan Becker)\n\t  * effective for all platforms that support --with-krb5\n\t  * this triggered a series of cleanup & simplification changes and\n\t    functionality & memory leak fixes in the sip-sec modules\n\t  * special thanks to Jarek Polok for the logs and testing\n\t- Feature #3594094: Add HTTPS to autodiscover probe (Stefan Becker)\n\t- Feature #3607040: Simple button to disable calendar integration (Stefan Becker)\n\t- Fixed #3603228: Crash on 1.14.1 when connecting to server (Stefan Becker)\n\t- Fixed #3604671: sip uri with apostrophe is not valid (Stefan Becker)\n\t- fixed HTTP redirect crash (Stefan Becker)\n\t- unified Single Sign-On handling in all places (Stefan Becker)\n\t  * if SSO is enabled then \"Login\" & \"Password\" settings are ignored\n\t  * SSO is now off by default for new accounts\n\t  * NOTE: if you do *NOT* use SSO, then be sure to disable it in the\n\t          \"Advanced\" tab of the account settings after updating!\n\t- added implementation for HTTP \"WWW-Authenticate: Negotiate\" scheme (Stefan Becker)\n\t  * effective for all platforms that support --with-krb5\n\t  * it will try Kerberos first, then fall back to NTLM\n\t  * valid Kerberos Single Sign-On setup will be detected automatically\n\t  * setup for a mixed Kerberos/NTLM HTTP environment:\n\t    - login name:     DOMAIN\\account\n\t    - password:       domain password\n\t    - authentication: Kerberos\n\t    - Single Sign-On: OFF(!)          (see above)\n\t- enabled TLS-DSK support in Windows SSPI version\n\t- TLS-DSK: don't ask for password if SSPI or Kerberos are compiled in\n\t- Farstream 0.1.1 compatibility fix (Jakub Adam)\n\t- support conf:sip: meeting URIs (Jakub Adam)\n\t- updated Adium port (Michael Lamb)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sat, 09 Mar 2013 15:25:00 +0200\n\npidgin-sipe (1.14.1-1) unstable; urgency=low\n\n  * New upstream version version 1.14.1 \"Bug Fixes I\"\n\t- Feature #3578132: Kerberos configuration should be passwordless (Stefan Becker)\n\t  * purple: non Single Sign-on users are asked for the password again\n\t- bug & memory leak fixes in sipe-buddy.c (Jakub Adam)\n\n -- Stefan Becker <chemobejk@gmail.com>  Wed, 26 Dec 2012 16:23:00 +0200\n\npidgin-sipe (1.14.0-1) unstable; urgency=low\n\n  * New upstream version 1.14.0 \"Buddy photo & ADFS support, Web Ticket Optimizations\"\n\t- Feature #3585364: Add support for Web Ticket authentication using ADFS (Stefan Becker)\n\t  * special thanks to user bhakta79 for the hard work taking logs\n\t- Feature #3578132: Kerberos configuration should be passwordless (Stefan Becker)\n\t- Fixed #3580212: Connection drops after a few hours (Stefan Becker)\n        - add support for buddy photos (Jakub Adam)\n\t- add support for call to Audio Test Service (Jakub Adam)\n\t- initial implementation for telepathy backend (Stefan Becker)\n\t  * nothing much to see for end users yet...\n\t- reduce Web Ticket traffic by queueing requests & caching tickets (Stefan Becker)\n\t- update OBS packaging information for Debian (Stefan Becker)\n        - various minor bug & build fixes\n\n -- Stefan Becker <chemobejk@gmail.com>  Sun, 16 Dec 2012 16:28:00 +0200\n\npidgin-sipe (1.13.3-1) unstable; urgency=low\n\n  * New upstream version 1.13.3 \"Bug Fixes III\" (2012-08-19)\n\t- Fixed #3537084: OpenBSD build issue (Stefan Becker)\n\t- Fixed #3543294: Support Lync 2010 meet URLs (Jakub Adam)\n\t- revert to legacy MSOC protocol on Lync FT invitation (Jakub Adam)\n\t- fix broken busy->available status switch (Stefan Becker)\n\t- updated translations: Portuguese (pt)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sun, 19 Aug 2012 12:03:00 +0300\n\npidgin-sipe (1.13.2-1) unstable; urgency=low\n\n  * New upstream version 1.13.2 \"Bug Fixes II\" (2012-06-10)\n\t- tls: fix buffer overrun (Oleksandr Hryshchuk, Stefan Becker)\n\t- win32: fix TCP connections (Stefan Becker)\n\t- nsis: fix broken locale installation (Stefan Becker)\n\t- updated translations: French (fr)\n\t- various build fixes (Stefan Becker, Jakub Adam)\n\n -- Stefan Becker <chemobejk@gmail.com>  Sun, 10 Jun 2012 15:48:00 +0300\n\npidgin-sipe (1.13.1-1) unstable; urgency=low\n\n  * New upstream version 1.13.1 \"Bug Fixes I\"\n\t- detect incompatible encryption level with Lync (Jakub Adam)\n\t- purple: add URI validity check to Add Buddy callback (Stefan Becker)\n\t- new translations: Romanian (ro), Turkish (tr)\n\t- various build fixes (Stefan Becker)\n\n -- Stefan Becker <chemobejk@gmail.com>  Mon, 09 Apr 2012 12:29:42 +0300\n\npidgin-sipe (1.13.0-1) unstable; urgency=low\n\n  * New upstream version 1.13.0 \"Lync & Office365\"\n\t- added [MS-SIPAE] TLS-DSK authentication scheme (Stefan Becker)\n\t  * TLS-DSK has been introduced in Lync\n\t  * mandatory for Office365 accounts\n\t  * also works for non-public Lync installations\n\t  * does not work yet with SSPI on Windows\n\t- added [MS-DLX] based Get Info/Contact Search (Stefan Becker)\n\t  * [MS-PRES] SIP-Based Active Directory Search is disabled in Lync\n\t- added experimental media TCP transport (Jakub Adam)\n\t- make it compile against the latest purple 3.0.x API (Stefan Becker)\n\t- make it compile against the latest glib2 2.31.x API (Stefan Becker)\n\t- completed cleanup: core no longer requires libpurple (Stefan Becker)\n\t- refactored crypto code, ie. NSS can replaced if necessary (Stefan Becker)\n\t- sipe-domino.c is no longer built under UNIX to remove dead code (Stefan Becker)\n\t- restricted XXX_CFLAGS to modules that need them (Stefan Becker)\n\t- NSS is now a mandatory build requirement (Stefan Becker)\n\t- decoupled SSPI from HAVE_LIBKRB5 flag. New flag is HAVE_SSPI (Stefan Becker)\n\t- OBS mingw packages now use SSPI instead of NTLM (Stefan Becker)\n\t- added NSIS package generation to OBS mingw packages (Stefan Becker)\n\t- removed kopete backend. KDE is moving to telepathy (Stefan Becker)\n\t- added MinGW cross-compilation on Linux instructions (Stefan Becker)\n\n -- Stefan Becker <chemobejk@gmail.com>  Wed, 14 Mar 2012 19:30:23 +0200\n\npidgin-sipe (1.12.0-1) unstable; urgency=low\n\n  * New upstream version 1.12.0 \"Group Chat\"\n\t- Feature #3064877: Add support for OCS2007R2 Group Chat (Stefan Becker)\n\t- Feature #3311026: Support for HTTP/1.1 Transfer-Encoding: chunked (Stefan Becker)\n\t- Fixed #2834758: First NTLM signature check after startup fails (Stefan Becker) \n\t- Fixed #3082602: Crash on Autodiscover (Stefan Becker)\n\t- Fixed #3090663: Re-authentication fails (Stefan Becker)\n\t- Fixed #3092324: Core dump in \"make check\" (psfales)\n\t- Fixed #3130915: Failed to authenticate to server (Stefan Becker)\n\t- Fixed #3148124: sipe segfaults during login on Solaris (Jakub Adam)\n\t- Fixed #3150482: \"configure --with-vv\" test uses wrong include (Stefan Becker)\n\t- Fixed #3156430: Messages not Delivered (rwinchsf, Stefan Becker)\n\t- Fixed #3161273: Lost Connection Gives No Error Message (rwinchsf, Stefan Becker)\n\t- Fixed #3198585: Extra line breaks (Stefan Becker)\n\t- Fixed #3267073: False \"could not be delivered\" errors (sort of..., Stefan Becker)\n\t- Fixed #3399007: Crash when sipe_cal_working_hours->days_of_week is NULL (Stefan Becker)\n\t- Patch #3091490: Make 1.11.0 Compile on FreeBSD (jprather)\n\t- Patch #3108246: Patch for better windows installer (archrival, galiven)\n\t- add random Ms-Conversation-ID to INVITE (Jakub Adam)\n\t- fix parsing of P-Asserted-Identity header (Jakub Adam)\n\t- added MS TURN support (Jakub Adam)\n\t- fix crash on zero length password in NTLM (Vladimir Ushakov)\n\t- implement timeouts for SIP request. Used for REGISTER (Stefan Becker)\n\t- more work on Voice & Video call support (Jakub Adam)\n        - make it compile against the purple 2.8.x & 3.0.x APIs (Stefan Becker)\n\t- more internal changes to prepare for non-purple backends (Stefan Becker)\n\t- added integration for transifex.net update (Stefan Becker)\n\t- configure improvements for 64-bit: use libdir, gsize/size_t compatibility (Stefan Becker)\n\t- update compiler warnings configuration for all build platforms (Stefan Becker)\n\t- updated Adium port (Matthew Duggan)\n\t- mingw build updates (Harris P. Kauffman, Stefan Becker)\n\t- added miranda port (Jochen De Smet)\n\t- added mingw to OpenSUSE Build Service configuration (Stefan Becker)\n\n -- Anibal Avelar <aavelar@cofradia.org>  Mon, 29 Aug 2011 00:50:47 -0500\n\npidgin-sipe (1.11.2-1) unstable; urgency=low\n\n  * New upstream version 1.11.2 \"Hot fixes II\"\n        - Revert \"mingw: add missing purple-notify.c to build\"\n        - Sipe-sign: fix parsing of P-Asserted-Identity header\n        - Fixed memory leaks\n        - Fix #3090663: Re-authentication fails\n        - Fix #3090663: Re-authentication fails (2nd attempt)\n        - Fix #3090663: Re-authentication fails (3rd attempt)\n        - Fix #3090663: Re-authentication fails (4th attempt)\n        - Apply patch #3091490: Make 1.11.0 Compile on FreeBSD\n        - Fix #3092324: Core dump in \"make check\"\n\n -- Anibal Avelar <aavelar@cofradia.org>  Tue, 02 Nov 2010 23:48:33 -0600\n\npidgin-sipe (1.11.1-1) unstable; urgency=low\n\n  * New upstream version 1.11.1 \"Hot fixes\"\n        - mingw: add missing purple-notify.c to build\n        - Fix for bug #2834758: First NTLM signature check after startup fails\n        - purple: fix memory leak in sipe_backend_transport_connect() error path\n        - Fix for bug #3082602: Crash on Autodiscover\n        - configure: use libdir & datadir instead of prefix + path\n        - configure: update 32-bit vs. 64-bit header conflict test\n        - debian: build stability fix in post-install\n\n -- Anibal Avelar <aavelar@cofradia.org>  Sun, 24 Oct 2010 00:00:00 +0300\n\npidgin-sipe (1.11.0-1) unstable; urgency=low\n\n  * New upstream version\n        - Feature #2945346: Lotus Notes/Domino Calendar integration:\n          * Sipe can now retrieve calendar data (Meeting schedule/subject/\n            location) from a web-enabled Lotus Domino server and publish it to\n            OCS2007/LCS2005 as availability information.\n          * Example: \"Calendar: Currently Busy. Free at 11:30\".\n          * Team members (contacts with access level Team) will be able to see\n            information about our current meeting (subject & location) (OCS2007)\n          * First calendar update is scheduled 1 minute after connect,\n          * Subsequent calendar updates happen in 30 minute intervals.\n          * Manual calendar update can be triggered using the following menu:\n                   Accounts->{SIPE_ACCOUNT}->\"Republish Calendar\"\n          * Though Domino integration can work without any additional settings \n            in account configuration (on Windows), there are options to manually\n            provide Domino Services URL and email address/password if it's\n            different from SIP URI/Password settings on Basic tab.\n        - Fixed #2971422: idle check for OCS2005 presence case\n        - Fixed #2982424: krb5 build errors on FreeBSD\n        - Fixed #2997639: pidgin crash after accepting cert\n        - Fixed #3001523: Cancelling a long pending file transfer crashes Pidgin\n        - Fixed #3002993: Group Name issues with ampersand\n        - Fixed #3029228: Calendar published at/with incorrect time\n        - Fixed #3029929: Crash with outlook 2k3 Calendar\n        - Fix logout from OCS\n        - Implement workaround for buddy list menu memory leaks\n        - Dropped UDP transport support\n        - Rewrote TCP & TLS transport support\n        - HTTP improvements: GET, cookies\n        - Alternative crypt/digest implementation based on NSS\n        - Rewrote message debug log and implemented an analyzer script for it\n        - More internal changes to prepare for non-purple backends\n        - New translations: 'nl', 'sv', 'ar', 'hu', 'ja', 'ko', 'sv', 'zh_TW'\n  * Fixed pidgin-sipe: Kerberos authentication is broken (Closes: #597437)\n  * Fixed pidgin-sipe: no dependency on pidgin (Closes: #594882)\n  * Fixed pidgin-sipe: new upstream version is available (Closes: #596799)\n  * Fixed pidgin-sipe: FTBFS: sipe.c:10050: error: missing initializer \n    (Closes: #582998)\n  * Added dependency with the libxml2-dev package in debian/control\n  * Added dependency with libnss3-dev package in debian/control\n  * Updated with Standards-Version 3.9.1\n\n -- Anibal Avelar <aavelar@cofradia.org>  Sun, 03 Oct 2010 22:05:31 +0300\n\npidgin-sipe (1.10.1-1) unstable; urgency=low\n\n  * New upstream version\n        - Fix broken sipe_ht_equals_nick(); the broken code has been in the \n          1.10.0 release. As it affects the buddy list it could be the root \n          cause for some of the \"buddy appears offline\" reports.\n        - Make it compile against the final purple 2.7.0 API;\n\n -- Anibal Avelar <aavelar@cofradia.org>  Sun, 27 Jun 2010 11:46:59 -0600\n\npidgin-sipe (1.10.0-1) unstable; urgency=low\n\n  * New upstream version\n      - Feature #2823160: Access Levels (2007+ environment)\n      - Feature #2957811: add support for \"automaton\" class\n      - Feature #2972823: fail on in-line variable declarations\n      - Fixed #2971422: handle OCS 2005 idiosyncrasy of varying SIP URI case\n      - Fixed #2981563: Authentication protocol v4 - invalid signature of some \n        incoming messages containing P-Asserted-Identity or P-Preferred-Identity\n        with uppercased SIP or TEL in URI.\n      - Fixed publication/\"409 Conflict\" endless looping\n      - Prepare for Pidgin 2.7.0\n      - Added SVG icon artwork\n      - Many changes to configure script. Be sure to look at \"configure --help\"\n      - Many internal changes to prepare for non-purple backends\n      - New build requirements: libxml2, glib-2.0 >= 2.12.0\n      - New build option: gmime-2.4 >= 2.4.16 or gmime-2.6 >= 2.5.2 for \n        non-purple backends\n\n -- Anibal Avelar <aavelar@cofradia.org>  Sun, 04 Apr 2010 00:52:59 -0600\n\npidgin-sipe (1.9.1-1) unstable; urgency=low\n  * New upstream version (emergency release)\n      - Fixed #2969327: Kerberos authentication always fails on *nix platforms\n      - Fixed #2968287: Authentication failure in scenario when director server\n        is Office Communications Server 2007 or above and home server is \n        Live Communications Server 2005\n      - Send BYE when response to IM message is 408/480/481\n      - Re-enable offline status to be user settable\n\n -- Anibal Avelar <aavelar@cofradia.org>  Tue, 16 Mar 2010 02:13:59 -0600\n\npidgin-sipe (1.9.0-1) unstable; urgency=low\n\n  * New upstream version (Closes: #570735)\n    * File transfer functionality. File encryption is supported\n    * NTLMv2 and NTLMv2 Session Security support\n    * Implemented SIP Authentication Extensions protocol version 4 and 3\n    * Adoption for commercial UNIX - HP/UX, Irix, Solaris - big endian fixes\n    * Increased libpurple build requisite to >= 2.4.0 \n    * many crash fixes for error or corner cases in calendar integration\n    * more detailed code analysis with Coverity Prevent\n    * build fixes for older libpurple/glib2 versions\n    * OpenSUSE Build Service configuration files\n    * Fix NTLM crash if login setting is undefined\n    * Use of g_str_has_prefix() available since glib 2.2 and null-safe\n    * build fixes for older OS releases, e.g. Ubuntu older than 9.10.\n  * Removed the file libsipe.la from the package\n  * Removed the line dh_pidgin -ppidgin-sipe from debian/rules \n  * Added ./autogen.sh could be run from debian/rules\n  * Changed the Section from net to misc inside Source stanza in debian/control\n  * Changed the Section from net to misc inside Package stanza in debian/control\n  * Added the Priority header inside Package stanza in debian/control\n  * Updated the Description inside Package stanza in debian/control\n  * Updated the debian/copyright file with the new authors list.\n  * Updated the debian/copyright file with the correct PATH to license GPL2.\n  * Removed dependency with the libgtk2.0-dev package in debian/control\n  * Removed dependency with the comerr-dev package in debian/control\n  * Removed debian/README.debian file from the package\n  * Added dependency with the libzephyr-dev package in debian/control\n\n -- Anibal Avelar <aavelar@cofradia.org>  Wed, 10 Mar 2010 01:05:59 -0600\n\npidgin-sipe (1.8.0-1) unstable; urgency=low\n\n  * New upstream version (Closes: #536100)\n    * Simplifying the authentication process using only the Basic Settings\n      screen.\n    * Added integration with Exchange 2007/2010\n    * Added Windows Messenger 5.0 (RTC/1.2) compatibility.\n    * \"About SIPE plugin\" screen implemented.\n    * Added Kerberos support.\n    * Added Multiparty Chat support.\n    * Fixed many bugs.\n    * Fixed many potencial memory leaks.\n    * Fixed support for LCS2005 and OCS2007 (improvementsi and bugs fixed)\n    * Added \"Find on LinkedIn\" link on contact's User Info screen\n    * Updated translations: \"de\", \"pl\", \"ru\", \"cs\", \"da\", \"es\", \"fi\", \"fr, \"hi\",\n      \"it\", \"nb\", \"ta\", \"zh_CN\".\n    * Fixed for server auto-discovery \n    * Fixed for User Agent string.  \n    * Added integration with PBX (external phones) using CSTA protocol\n    * Fixed for CHOWA problems\n    * Fixed for spaces in Login's username \n    * Support for Reuters Messaging environment\n    * Support for message formatting\n    * Added notification support for undelivered messages\n    * Extended contact search implementation\n    * ... and more\n  * Fixed pidgin-sipe: urls appear w/ underscore prefix (Closes: #529523)\n  * Updated the debian/copyright file with the new authors list.\n  * Added DEB_CONFIGURE_EXTRA_FLAGS in debian/rules for extra compile flags\n  * Added dependency with the libkrb5-dev package\n  * Removed to delete the file libsipe.la from debian/rules.\n  * Removed DEB_AUTO_UPDATE_DEBIAN_CONTROL reference from debian/rules.\n  * Updated with Standards-Version 3.8.4\n\n -- Anibal Avelar <aavelar@cofradia.org>  Sun, 07 Feb 2010 04:48:35 -0500\n\npidgin-sipe (1.3.3-1) unstable; urgency=low\n\n  * New upstream version (Closes: #508221)\n    * Added support for OCS 2007, LCS 2003\n    * Full support for send/receive messages\n    * Full presence support (both sides)\n    * Full support for add/remove/move contacts\n    * TLS/SSL support\n    * Search contacts full support\n    * xBSD support\n  * Added the dependency with the libpurple-dev package\n  * Added the dependency with the intltool package\n  * Added the dependency with the comerr-dev package\n  * Removed the unnecessary debian/pidgin-sipe.dirs file\n  * Changed the package description inside debian/control \n    (Closes: #433920,#490923)\n  * Added the field Homepage inside Source stanza in debian/control file.\n  * Updated the debian/copyright file with the new authors list.\n  * Updated with Standards-Version 3.8.0\n\n -- Anibal Avelar <aavelar@cofradia.org>  Sun, 1 Mar 2009 12:15:35 -0500\n\npidgin-sipe (1.2-1) unstable; urgency=low\n\n  * Initial release (Closes: #418226)\n\n -- Anibal Avelar (Fixxxer) <aavelar@cofradia.org>  Wed, 13 Jun 2007 19:12:35 -0500\n\n"
  },
  {
    "path": "contrib/debian/compat",
    "content": "5\n"
  },
  {
    "path": "contrib/debian/control",
    "content": "Source: pidgin-sipe\nSection: misc\nPriority: optional\nMaintainer: Anibal Avelar <aavelar@cofradia.org>\nHomepage: http://sipe.sourceforge.net/\n# FYI: libnss3-dev can be replaced with libssl-dev\nBuild-Depends: cdbs (>= 0.4.23-1.1), autotools-dev, debhelper (>= 5), pkg-config, libglib2.0-dev (>= 2.18.0), libdbus-1-dev, libxml2-dev, libnss3-dev, pidgin-dev, libpurple-dev (>= 2.7.0), libtool, intltool, libkrb5-dev, libzephyr-dev\nStandards-Version: 3.9.1\n\nPackage: pidgin-sipe\nSection: net\nPriority: optional\nArchitecture: any\nDepends: ${shlibs:Depends}, ${misc:Depends}\nDescription: Pidgin protocol plugin to connect to MS Office Communicator\n A third-party plugin for the Pidgin multi-protocol instant messenger.\n It implements the extended version of SIP/SIMPLE used by various products:\n .\n     * Skype for Business\n     * Microsoft Office 365\n     * Microsoft Business Productivity Online Suite (BPOS)\n     * Microsoft Lync Server\n     * Microsoft Office Communications Server (OCS 2007/2007 R2)\n     * Microsoft Live Communications Server (LCS 2003/2005)\n .\n With this plugin you should be able to replace your Microsoft Office\n Communicator client with Pidgin.\n"
  },
  {
    "path": "contrib/debian/copyright",
    "content": "This work was packaged for Debian by:\n\n  Anibal Avelar <aavelar@cofradia.org> on Wed, 13 Jun 2007 19:12:35 -0500.\n\nIt was downloaded from:\n\n  <http://sourceforge.net/projects/sipe/files/>\n\nUpstream Authors:\n\n  Anibal Avelar <debianmx@gmail.com>\n  Stefan Becker <chemobejk@gmail.com>\n  Jakub Adam    <jakub.adam@ktknet.cz>\n  Tomáš Hrabčík <tomas.hrabcik@tieto.com> (retired)\n  pier11        <pier11@operamail.com> (retired)\n  Gabriel Burt  <gburt@novell.com> (retired)\n  Daniel Beichl <daniel_beichl@gmx.net> (retired)\n\n  Based on the initial SIP/SIMPLE gaim protocol plugin by:\n\n  Thomas Butter <butter@uni-mannheim.de>\n\nCopyright:\n\n  Copyright (C) 2010      Jakub Adam\n  Copyright (C) 2010      Tomáš Hrabčík\n  Copyright (C) 2009-2010 pier11\n  Copyright (C) 2008      Novell, Inc.\n  Copyright (C) 2007-2012 SIPE Project\n  Copyright (C) 2007-2010 Anibal Avelar\n  Copyright (C) 2005      Thomas Butter\n\nLicense:\n\n  This package is free software; you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation; either version 2 of the License, or\n  (at your option) any later version.\n\n  This package is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with this package; if not, write to the Free Software\n  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA\n\nOn Debian systems, the complete text of the GNU General Public\nLicense version 2 can be found in `/usr/share/common-licenses/GPL-2'.\n\nDebian packaging is:\n\n   Copyright (C) 2007 Anibal Avelar <aavelar@cofradia.org>\n\nYou can redistribute it and/or modify it under the terms of the\nGNU General Public License as published by Free Software Foundation;\neither version 2 of the License, or (at your option) any later version.\n"
  },
  {
    "path": "contrib/debian/docs",
    "content": "AUTHORS\nChangeLog\nNEWS\nREADME\nTODO\n"
  },
  {
    "path": "contrib/debian/rules",
    "content": "#!/usr/bin/make -f\n\ninclude /usr/share/cdbs/1/class/autotools.mk\ninclude /usr/share/cdbs/1/rules/debhelper.mk\n\nHAVE_APPSTREAM        := $(strip $(shell (/usr/bin/appstream-validate >/dev/null --version || /usr/bin/appstreamcli >/dev/null --version) && echo yes))\nHAVE_APPSTREAM_LEGACY := $(strip $(shell . /etc/os-release; echo $${ID}-$${VERSION_ID} | grep -q '^debian-8$$' && echo yes))\n\nDEB_CONFIGURE_EXTRA_FLAGS := --enable-purple\n# detect if package telepathy-glib is available\nifneq ($(shell pkg-config --exists telepathy-glib && echo FOUND),)\nDEB_CONFIGURE_EXTRA_FLAGS += --enable-telepathy\nelse\nDEB_CONFIGURE_EXTRA_FLAGS += --disable-telepathy\nendif\nifneq ($(shell pkg-config --exists nice && echo FOUND),)\nDEB_CONFIGURE_EXTRA_FLAGS += --with-vv\nelse\nDEB_CONFIGURE_EXTRA_FLAGS += --without-vv\nendif\nifeq ($(HAVE_APPSTREAM),)\nDEB_CONFIGURE_EXTRA_FLAGS += --without-appstream\nendif\n\n# run tests\nDEB_MAKE_CHECK_TARGET := check\n\n# don't run unnecessary ldconfig on postinst and postrm.\nDEB_DH_MAKESHLIBS_ARGS_pidgin-sipe=-n\n\nclean::\n\tdh_testdir\n\n# git snapshot does not contain a configure script\ndebian/stamp-autotools-files: $(DEB_CONFIGURE_SCRIPT)\n$(DEB_BUILDDIR)/config.status: $(DEB_CONFIGURE_SCRIPT)\n\n$(DEB_CONFIGURE_SCRIPT):\n\t./autogen.sh\n\nbinary-post-install/pidgin-sipe::\n\trm -f debian/pidgin-sipe/usr/share/doc/pidgin-sipe/README\n\trm -r debian/pidgin-sipe/usr/share/pixmaps/pidgin/protocols/24\n\trm -r debian/pidgin-sipe/usr/share/pixmaps/pidgin/protocols/32\n\trm debian/pidgin-sipe/usr/lib/purple-2/libsipe.la\nifeq ($(HAVE_APPSTREAM)-$(HAVE_APPSTREAM_LEGACY),yes-yes)\n\tmv debian/pidgin-sipe/usr/share/metainfo debian/pidgin-sipe/usr/share/appdata\nendif\n\n.PHONY: update-debian-control\n"
  },
  {
    "path": "contrib/debug/parse_log.pl",
    "content": "#!/usr/bin/perl -w\nuse 5.010;\nuse strict;\nuse warnings;\n\nuse File::Spec;\nuse Getopt::Long;\nuse Pod::Usage;\n\n# Command line option\nmy %Options = (\n\t       directory => \".\",\n\t      );\nGetOptions(\\%Options,\n\t   \"directory=s\",\n\t   \"callid\",\n\t   \"from\",\n\t   \"method\",\n\t   \"transport\",\n\t   \"filter\",\n\t   \"help|h|?\")\n  or pod2usage(2);\npod2usage(-verbose => 2) if $Options{help};\n\n###############################################################################\n#\n# Message parsing\n#\n###############################################################################\nmy %callid;\nmy %from;\nmy %method;\nmy %transport;\nsub AddMessage($$$$@)\n{\n  my($direction, $type, $transport, $time, @message) = @_;\n\n  # extract additional information from SIP messages\n  if ($type eq \"SIP\") {\n    my($index, $callid, $from, $method);\n    foreach my $line (@message) {\n      next if $index++ < 1;\n      last if $line =~ /^\\s+$/;\n\n      next unless my($keyword, $value) = $line =~ /^([^:]+):\\s+(.+)/;\n      $callid   = $value                     if $keyword =~ /^call-id$/i;\n      ($from)   = $value =~ /^<sip:([^;>]+)/ if $keyword =~ /^from$/i;\n      ($method) = $value =~ /^\\d+\\s+(\\S+)/   if $keyword =~ /^cseq$/i;\n    }\n    push(@{$callid{$callid}},     \\@message) if $Options{callid} && defined $callid;\n    push(@{$from{lc($from)}},     \\@message) if $Options{from}   && defined $from;\n    push(@{$method{uc($method)}}, \\@message) if $Options{method} && defined $method;\n  }\n\n  # information available for all message types\n  push(@{$transport{$transport}}, \\@message) if $Options{transport};\n}\n\nsub DumpMessages()\n{\n  foreach my $callid (keys %callid) {\n    if (open(my $fh, \">\",\n\t     File::Spec->catfile($Options{directory}, \"callid-${callid}.txt\"))) {\n      print $fh @{$_} foreach (@{$callid{$callid}});\n      close($fh);\n    }\n  }\n  foreach my $from (keys %from) {\n    if (open(my $fh, \">\",\n\t     File::Spec->catfile($Options{directory}, \"from-${from}.txt\"))) {\n      print $fh @{$_} foreach (@{$from{$from}});\n      close($fh);\n    }\n  }\n  foreach my $method (keys %method) {\n    if (open(my $fh, \">\",\n\t     File::Spec->catfile($Options{directory}, \"method-${method}.txt\"))) {\n      print $fh @{$_} foreach (@{$method{$method}});\n      close($fh);\n    }\n  }\n  foreach my $transport (keys %transport) {\n    if (open(my $fh, \">\",\n\t     File::Spec->catfile($Options{directory}, \"transport-${transport}.txt\"))) {\n      print $fh @{$_} foreach (@{$transport{$transport}});\n      close($fh);\n    }\n  }\n}\n\n###############################################################################\n#\n# Main program\n#\n###############################################################################\n\n# For all lines from command line files or STDIN\nmy @message;\nmy $counter;\nwhile (<>) {\n\n  # Start of message?\n  if (my ($direction, $type, $transport, $time) =\n      /^MESSAGE START\\s+([<>]+)\\s+([^(]+)\\((0x[\\da-f]+)\\)\\s+-\\s+(.+)/) {\n    push(@message,\n\t \"------------- NEXT MESSAGE: \" .\n\t (($direction =~ /^>/) ? \"outgoing\" : \"incoming\") .\n\t \" $type($transport) at $time\\n\");\n\n  # End of message?\n  } elsif (($direction, $type, $transport, $time) =\n\t   /^MESSAGE END\\s+([<>]+)\\s+([^(]+)\\((0x[\\da-f]+)\\)\\s+-\\s+(.+)/) {\n\n    if ($Options{filter}) {\n      print @message;\n    } else {\n      print STDERR \".\" if (++$counter % 10 == 0);\n      AddMessage($direction, $type, $transport, $time, @message);\n    }\n\n    # Done with the current message\n    undef @message;\n\n  # All other lines\n  } else {\n\n    # Collect message information\n    push(@message, $_) if @message;\n  }\n}\n\nunless ($Options{filter}) {\n  print STDERR \"\\n\" unless $Options{filter};\n  DumpMessages();\n}\n\n# That's all folks...\nexit 0;\n\n__END__\n\n=head1 NAME\n\nparse_log.pl - parse pidgin-sipe debug log\n\n=head1 SYNOPSIS\n\n[perl} parse_log.pl --help|-h|-?\n\n[perl} parse_log.pl --filter\n                    [file ...]\n\n[perl} parse_log.pl [--directory <dir>]\n                    [--callid]\n                    [--from]\n                    [--method]\n                    [--transport]\n                    [file ...]\n\n=head1 OPTIONS\n\n=over 8\n\n=item B<--callid>\n\nDump all SIP messages belonging to one Call-ID to the same file.\n\n=item B<--directory>\n\nDirectory for output files. Default is the current directory.\n\n=item B<--filter>\n\nEnable filter mode. Messages are simply printed to stdout.\n\n=item B<--from>\n\nDump all SIP messages sent from the same SIP URI to the same file.\n\n=item B<--help>\n\n=item B<--h>\n\n=item B<--?>\n\nPrint a brief help message and exits.\n\n=item B<--method>\n\nDump all SIP messages with the same method to the same file.\n\n=item B<--transport>\n\nDump all messages from one transport to the same file.\n\n=back\n\n=head1 DESCRIPTION\n\nB<This program> extracts SIP/HTTP messages from pidgin-sipe debug logs. If\nno file is specified then it reads from STDIN.\n\n=cut\n"
  },
  {
    "path": "contrib/debug/parse_valgrind.pl",
    "content": "#!/usr/bin/perl -w\nuse 5.010;\nuse strict;\nuse warnings;\n\n###############################################################################\n#\n# Build SIPE with:\n#\n#  CFLAGS=\"-g -O0\" ./configure\n#\n# Grab a log with:\n#\n#  G_DEBUG=\"gc-friendly\" G_SLICE=\"always-malloc\" valgrind --leak-check=yes \\\n#     /usr/bin/pidgin --debug 2>&1 | tee pidgin_debug.log\n#\n# Analyze log with:\n#\n#  perl contrib/debug/parse_valgrind.pl pidgin_debug.log\n#\n###############################################################################\nmy @heap_lines;\nmy @last_heap_lines;\nmy $invalid_lines;\nmy @all_invalid_lines;\nmy $other_lines;\n\n# For all lines from command line files or STDIN\nwhile (<>) {\n    next unless my($remainder) = /^==\\d+== (.*)/;\n\n    if ($remainder eq \"HEAP SUMMARY:\") {\n\t@heap_lines = ($remainder);\n\n\tundef $invalid_lines;\n\tundef $other_lines;\n\n    } elsif ($remainder =~ /^ERROR SUMMARY:/) {\n\t# keep only the last heap summary\n\t@last_heap_lines = @heap_lines;\n\n\tundef @heap_lines;\n\n    } elsif ($remainder =~ /^Invalid /) {\n\t# collect all invalid lines\n\tpush(@all_invalid_lines, $remainder);\n\n\tundef @heap_lines;\n\t$invalid_lines++;\n\tundef $other_lines;\n\n    } elsif ($remainder =~ /^Conditional/) {\n\tundef @heap_lines;\n\tundef $invalid_lines;\n\t$other_lines++\n\n    } elsif (@heap_lines) {\n\tpush(@heap_lines, $remainder);\n\n    } elsif (defined($invalid_lines)) {\n\tpush(@all_invalid_lines, $remainder);\n\n    } elsif (defined($other_lines)) {\n\tundef $other_lines if $remainder eq \"\";\n\n    } else {\n\t#print \"UNKNOWN: $remainder\\n\";\n    }\n}\n\nsub check_blocks($$$) {\n    my($label, $start, $lines) = @_;\n    my @block;\n    my $flagged;\n\n    print \"$label:\\n\\n\";\n    foreach (@{$lines}) {\n\tif (/$start/../^$/) {\n\t    push(@block, $_);\n\n\t    # matcher for SIPE code lines\n\t    $flagged++\n\t\tif /\\((?:sipe-|sip-|sdpmsg|sipmsg|http-|uuid|purple-|telepathy-)/;\n\n\t    if (length($_) == 0) {\n\t\tprint join(\"\\n\", @block), \"\\n\\n\" if $flagged;\n\t\tundef @block;\n\t\tundef $flagged;\n\t    }\n\t}\n    }\n}\n\ncheck_blocks(\"INVALID ACCESSES\", qr/^Invalid /, \\@all_invalid_lines);\ncheck_blocks(\"MEMORY LEAKS\", qr/^\\d+ bytes in \\d+ blocks/, \\@last_heap_lines);\n\n# That's all folks...\nexit 0;\n"
  },
  {
    "path": "contrib/mingw-cross-compile/README.txt",
    "content": "Introduction\n============\n\nWith these instructions you will be able to generate libsipe.dll on a Linux\nmachine that is compatible with the official Pidgin Windows releases.\n\nThe approach described here is based on this wiki page:\n\n   http://code.google.com/p/pidgin-privacy-please/wiki/HowToCrossCompileForWindowsAgainstLatestPidgin\n\nThe build has been verified to work at the time this text was written. When\nyou read this some things in Pidgin or MinGW might changed, so make sure to\ncheck the comments on that wiki page for updates.\n\n\nPreparation\n===========\n\nYou'll need a Linux machine with the following MinGW cross-compilation\npackages installed:\n\nUbuntu:\n   sudo apt-get install mingw32 mingw32-binutils mingw32-runtime\n\nFedora:\n   sudo yum install mingw32-gcc\n\nThis will most likely work also for other Linux distros, but you'll have\nto check what names the MinGW cross-compilation packages are for your\ndistro.\n\nIf you are trying to build the source code from the git repository then\nyou'll need additional tools installed, at least:\n\n   autoconf\n   automake\n   flex\n\nIf you want to build the NSIS installer package then you'll need to install:\n\n   mingw32-nsis\n\n\nBuild\n=====\n\n - [pidgin-sipe source code from git instead from a release tarball]\n   run the following commands inside the git work area:\n\n      ./autogen.sh\n      ./configure\n      make dist-gzip\n\n   This will generate pidgin-sipe-<VERSION>.tar.gz\n\n - create an empty directory and cd into it\n\n - run contrib/mingw-cross-compile/fetch.sh from pidgin-sipe source\n   * make sure to check for fetch & unpack errors before proceeding!\n\n - cd into build-<...REPLACE PIDGIN VERSION HERE...>/pidgin-<...REPLACE PIDGIN VERSION HERE...>\n\n - copy/unpack pidgin-sipe source code tree into into current directory\n\n - run\n\n     cp pidgin-sipe-<...REPLACE PIDGIN-SIPE VERSION HERE...>/contrib/mingw-cross-compile/local.mak .\n\n - run (this is one line on the command line!)\n\n     make -C pidgin-sipe-<...REPLACE PIDGIN-SIPE VERSION HERE...>/src/core\n          -f Makefile.mingw\n\n     (to compile without SSPI support add \" USE_SSPI=\" to the command line)\n\nIf everything goes well you should now have\n\n  pidgin-sipe-<...REPLACE PIDGIN-SIPE VERSION HERE...>/src/core/libsipe.dll\n\nwhich you can copy into your Pidgin Windows installation directory.\n\nNOTE: PLEASE make sure that there is NO OTHER libsipe.dll in that installation\n      or in your PATH!\n\n\nNSIS Installer Package\n======================\n\nAfter you have successfully executed the build:\n\n - run (this is one line on the command line!)\n\n     PIDGIN_TREE_TOP=.. make\n          -C pidgin-sipe-<...REPLACE PIDGIN-SIPE VERSION HERE...>\n          -f Makefile.mingw cross-compile-nsis\n\n     (to compile without SSPI support add \" USE_SSPI=\" to the command line)\n\nIf everything goes well you should now have\n\n  pidgin-sipe-<...REPLACE PIDGIN-SIPE VERSION HERE...>.exe\n\nwhich you now can execute on your Windows machine.\n"
  },
  {
    "path": "contrib/mingw-cross-compile/fetch.sh",
    "content": "#!/bin/bash\n#\n# Based on:\n#\n#   http://code.google.com/p/pidgin-privacy-please/wiki/HowToCrossCompileForWindowsAgainstLatestPidgin\n#\n# Latest Windows Pidgin build instractions:\n#\n#   https://developer.pidgin.im/wiki/BuildingWinPidgin\n#\n# Check these page for latest MinGW/Pidgin URLs if you get fetch errors!\n#\n# update Pidgin version here\nexport PIDGIN_VERSION=2.13.0\n\n# must be absolute path\nexport PIDGIN_DEV_ROOT=$(pwd -P)/build-${PIDGIN_VERSION}\nexport SOURCES_DIR=${PIDGIN_DEV_ROOT}/sources/\nexport DEV_DIR=${PIDGIN_DEV_ROOT}/win32-dev\nexport MINGW_DIR=${DEV_DIR}/mingw\nexport PIDGIN_DIR=${PIDGIN_DEV_ROOT}/pidgin-${PIDGIN_VERSION}\n\nexec >fetch-${PIDGIN_VERSION}.log\nset -e\n\necho 1>&2 create directory tree...\nrm -rf ${PIDGIN_DEV_ROOT}\nmkdir -p ${SOURCES_DIR}\nmkdir -p ${MINGW_DIR}\n\necho 1>&2 fetching mingw...\ncd ${SOURCES_DIR}\n#wget -nv https://sourceforge.net/projects/mingw/files/MinGW/Base/binutils/binutils-2.24/binutils-2.24-1-mingw32-bin.tar.xz\nwget -nv http://sourceforge.net/projects/mingw/files/MinGW/Base/mingwrt/mingwrt-3.20/mingwrt-3.20-2-mingw32-dev.tar.lzma\nwget -nv http://sourceforge.net/projects/mingw/files/MinGW/Base/mingwrt/mingwrt-3.20/mingwrt-3.20-2-mingw32-dll.tar.lzma\nwget -nv http://sourceforge.net/projects/mingw/files/MinGW/Base/w32api/w32api-3.17/w32api-3.17-2-mingw32-dev.tar.lzma\nwget -nv http://sourceforge.net/projects/mingw/files/MinGW/Base/gmp/gmp-5.0.1-1/gmp-5.0.1-1-mingw32-dev.tar.lzma\nwget -nv http://sourceforge.net/projects/mingw/files/MinGW/Base/libiconv/libiconv-1.14-2/libiconv-1.14-2-mingw32-dev.tar.lzma\nwget -nv http://sourceforge.net/projects/mingw/files/MinGW/Base/mpfr/mpfr-2.4.1-1/mpfr-2.4.1-1-mingw32-dev.tar.lzma\nwget -nv http://sourceforge.net/projects/mingw/files/MinGW/Base/pthreads-w32/pthreads-w32-2.9.0-pre-20110507-2/pthreads-w32-2.9.0-mingw32-pre-20110507-2-dev.tar.lzma\nwget -nv http://sourceforge.net/projects/mingw/files/MinGW/Base/gcc/Version4/gcc-4.7.2-1/gcc-core-4.7.2-1-mingw32-bin.tar.lzma\nwget -nv http://sourceforge.net/projects/mingw/files/MinGW/Base/gcc/Version4/gcc-4.7.2-1/libgcc-4.7.2-1-mingw32-dll-1.tar.lzma\n\necho 1>&2 unpacking mingw...\ncd ${MINGW_DIR}\nfor file in ${SOURCES_DIR}/*tar.lzma ; do tar xf ${file} ; done\n\necho 1>&2 fetching pidgin dev stuff...\ncd ${SOURCES_DIR}\nwget -nv http://ftp.gnome.org/pub/gnome/binaries/win32/gtk+/2.14/gtk+-bundle_2.14.7-20090119_win32.zip\nwget -nv http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/gettext-tools-0.17.zip\nwget -nv http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/gettext-runtime-0.17-1.zip\nwget -nv https://developer.pidgin.im/static/win32/libxml2-2.9.2_daa1.tar.gz\nwget -nv https://developer.pidgin.im/static/win32/gtkspell-2.0.16.tar.bz2\nwget -nv https://developer.pidgin.im/static/win32/enchant_1.6.0_win32.zip\nwget -nv https://developer.pidgin.im/static/win32/nss-3.24-nspr-4.12.tar.gz\nwget -nv https://developer.pidgin.im/static/win32/silc-toolkit-1.1.12.tar.gz\nwget -nv https://developer.pidgin.im/static/win32/meanwhile-1.0.2_daa3-win32.zip\nwget -nv https://developer.pidgin.im/static/win32/cyrus-sasl-2.1.26_daa1.tar.gz\nwget -nv http://ftp.acc.umu.se/pub/GNOME/binaries/win32/intltool/0.40/intltool_0.40.4-1_win32.zip\nwget -nv http://prdownloads.sourceforge.net/pidgin/pidgin-${PIDGIN_VERSION}.tar.bz2\n\necho 1>&2 unpacking pidgin dev stuff...\nunzip ${SOURCES_DIR}/gtk+-bundle_2.14.7-20090119_win32.zip -d ${DEV_DIR}/gtk_2_0-2.14\nunzip ${SOURCES_DIR}/gettext-tools-0.17.zip -d ${DEV_DIR}/gettext-0.17\nunzip ${SOURCES_DIR}/gettext-runtime-0.17-1.zip -d ${DEV_DIR}/gettext-0.17\nunzip ${SOURCES_DIR}/enchant_1.6.0_win32.zip -d ${DEV_DIR}/enchant_1.6.0_win32\nunzip ${SOURCES_DIR}/meanwhile-1.0.2_daa3-win32.zip -d ${DEV_DIR}\nunzip ${SOURCES_DIR}/intltool_0.40.4-1_win32.zip -d ${DEV_DIR}/intltool_0.40.4-1_win32\n\ncd ${DEV_DIR}\ntar xzf ${SOURCES_DIR}/libxml2-2.9.2_daa1.tar.gz\ntar xjf ${SOURCES_DIR}/gtkspell-2.0.16.tar.bz2\ntar xzf ${SOURCES_DIR}/nss-3.24-nspr-4.12.tar.gz\ntar xzf ${SOURCES_DIR}/silc-toolkit-1.1.12.tar.gz\ntar xzf ${SOURCES_DIR}/cyrus-sasl-2.1.26_daa1.tar.gz\n\ncd ${PIDGIN_DEV_ROOT}\ntar xjf ${SOURCES_DIR}/pidgin-${PIDGIN_VERSION}.tar.bz2\n\necho 1>&2 done\n"
  },
  {
    "path": "contrib/mingw-cross-compile/local.mak",
    "content": "#\n# Fedora 19+: upgrade to mingw32-gcc 4.8.x breaks backward compatibility.\n#             Fetch F18 packages of mingw32-gcc and set PIDGIN_MINGW_ROOT\n# \t      and LD_LIBRARY_PATH to the local install root.\n#\nifneq ($(wildcard $(PIDGIN_MINGW_ROOT)/bin/i686-w64-mingw32-*),)\n# Fedora 17+\nCC       := $(PIDGIN_MINGW_ROOT)/bin/i686-w64-mingw32-gcc\nSTRIP    := $(PIDGIN_MINGW_ROOT)/bin/i686-w64-mingw32-strip\nWINDRES  := $(PIDGIN_MINGW_ROOT)/bin/i686-w64-mingw32-windres\nEXTUTILS := /usr/share/perl5/ExtUtils\nelse ifneq ($(wildcard $(PIDGIN_MINGW_ROOT)/usr/bin/i686-pc-mingw32-*),)\n# Fedora\nCC       := $(PIDGIN_MINGW_ROOT)/usr/bin/i686-pc-mingw32-gcc\nSTRIP    := $(PIDGIN_MINGW_ROOT)/usr/bin/i686-pc-mingw32-strip\nWINDRES  := $(PIDGIN_MINGW_ROOT)/usr/bin/i686-pc-mingw32-windres\nEXTUTILS := /usr/share/perl5/ExtUtils\nelse\n# Ubuntu\nCC       := /usr/bin/i586-mingw32msvc-cc\nSTRIP    := /usr/bin/i586-mingw32msvc-strip\nWINDRES  := /usr/bin/i586-mingw32msvc-windres\nEXTUTILS := /usr/share/perl/5.10/ExtUtils\nendif\n\n# common\nGMSGFMT := msgfmt\nMAKENSIS := /usr/bin/makensis\nPERL := /usr/bin/perl\n\nINCLUDE_PATHS := -I\\$(PIDGIN_TREE_TOP)/../win32-dev/w32api/include\nLIB_PATHS := -L\\$(PIDGIN_TREE_TOP)/../win32-dev/w32api/lib\n"
  },
  {
    "path": "contrib/opensuse-build-service/PKGBUILD",
    "content": "# Maintainer: SIPE Project <http://sipe.sourceforge.net/>\n\npkgname=pidgin-sipe\npkgver=1.25.0\npkgrel=1\npkgdesc=\"Libpurple protocol plugin to connect to MS Office Communicator\"\narch=('x86_64')\nlicense=('GPL-2.0-or-later')\nurl=\"https://sipe.sourceforge.net/\"\ndepends=('gmime' 'libpurple')\nmakedepends=('intltool')\noptdepends=('freerdp: Desktop sharing' 'krb5: Kerberos support')\nsource=( ${pkgname}-${pkgver}.tar.gz )\nsha256sums=( '@@SHA256SUM@@' )\n\nbuild() {\n  cd \"${pkgname}-${pkgver}\"\n\n  ./configure --prefix=/usr --with-vv\n\n  make\n}\n\npackage() {\n  cd \"${pkgname}-${pkgver}\"\n\n  make DESTDIR=\"${pkgdir}\" install\n}\n"
  },
  {
    "path": "contrib/opensuse-build-service/generate_debian.sh",
    "content": "#!/bin/bash\nabort() {\n    echo \"$0: $1 - Aborting\"\n    exit 1\n}\ncleanup() {\n    rm -rf debian\n    abort \"$1\"\n}\n\n# Sanity checks\nversion=$(ls pidgin-sipe-*.tar.gz | sed 's/^pidgin-sipe-//;s/.tar.gz$//')\n[ -z \"${version}\" ] && abort \"can't find pidgin-sipe archive\"\n[ -e debian ]       && abort \"directory 'debian' - already exists\"\n\n# Copy latest source archive\ncp pidgin-sipe-${version}.tar.gz pidgin-sipe_${version}.orig.tar.gz\n\n# Extract contrib/debian directory from release\ntar --strip-components=2 --wildcards -xvf \\\n    pidgin-sipe-${version}.tar.gz \\\n    \"*/contrib/debian\" || cleanup \"tar failed\"\n[ -e debian ]          || cleanup \"directory 'debian' - does not exist\"\n\n# Strip libnss3-dev from debian/control: build setup is controlled by .dsc's\nsed -i.ORIG -e 's/libnss3-dev, //' debian/control\ntouch -r debian/control.ORIG debian/control\nrm debian/control.ORIG\n\n# Have the contents changed?\nif tar 2>/dev/null -df pidgin-sipe_${version}-1.debian.tar.gz; then\n    echo \"contrib/debian is unchanged - not updating .debian.tar.gz.\"\nelse\n    # Update debian archive\n    tar cfz pidgin-sipe_${version}-1.debian.tar.gz debian || cleanup \"can't create tar archive\"\nfi\nrm -rf debian\n\n# Update .dsc files\nfor p in \\\n    \"Checksums-Sha1=sha1sum\" \\\n    \"Checksums-Sha256=sha256sum\" \\\n    \"Files=md5sum\";\ndo \\\n    label=${p%=*}; \\\n    program=${p#*=}; \\\n    echo \"${label}:\"\n    for t in \\\n\tpidgin-sipe_${version}.orig.tar.gz \\\n\tpidgin-sipe_${version}-1.debian.tar.gz; \\\n    do \\\n\techo \" $(${program} ${t} | cut -d' ' -f1) $(wc -c ${t})\"; \\\n    done \\\ndone >checksums.txt\nfor d in *.dsc; do cat checksums.txt >>${d}; done\nrm checksums.txt\n\n# Newer platforms have support for freerdp2 - use only default .dsc\ncp pidgin-sipe-freerdp2.dsc pidgin-sipe.dsc\n# All other platforms at least support for gstreamer1.0 - override those\nfor os in \\\n    Debian_9.0 \\\n    xUbuntu_16.04 \\\n; do \\\n    cp pidgin-sipe-gstreamer1.dsc pidgin-sipe-${os}.dsc; \\\ndone\n# All other platforms at least support telepathy - override those\nfor os in \\\n    Debian_8.0 \\\n; do \\\n    cp pidgin-sipe-telepathy.dsc pidgin-sipe-${os}.dsc; \\\ndone\n\n# Update SHA-2 256 checksum in Arch Linux PKGBUILD\nsed -i -e \"s/@@SHA256SUM@@/$(sha256sum pidgin-sipe-${version}.tar.gz | cut -d' ' -f1)/\" PKGBUILD\n\n# That's all folks...\necho \"Done.\"\nosc status\nexit 0\n"
  },
  {
    "path": "contrib/opensuse-build-service/generate_nsi.pl",
    "content": "#!/usr/bin/perl\nuse 5.008;\nuse strict;\nuse warnings;\n\n# check commandline arguments\ndie \"Usage: $0 <LINGUAS file> < nsi-template > nsi-output\\n\"\n    if @ARGV < 1;\n\n# process LINGUAS file\nopen(my $fh, \"<\", $ARGV[0])\n    or die \"$0: can't open LINGUAS file '$ARGV[0]': $!\\n\";\nmy %languages = map { ($_, 1) } map { chomp; s/^\\s+//; s/\\s+$//; $_ } <$fh>;\nclose($fh)\n    or die \"$0: error while reading LINGUAS file '$ARGV[0]': $!\\n\";\nprint STDERR \"Found \", scalar(keys %languages), \" language(s): \",\n                       join(\" \", sort keys %languages), \"\\n\";\n\n# read .nsi template from STDIN\n# write .nsi file to STDOUT\nwhile (<STDIN>) {\n    if (/^;;; INSTALL_FILES_LOCALE/) {\n\tprint map({\n\t           (\"SetOutPath \\\"\\$INSTDIR\\\\locale\\\\$_\\\\LC_MESSAGES\\\"\\n\",\n\t\t    \"File \\\"\\${MINGW_DATADIR}\\\\locale\\\\$_\\\\LC_MESSAGES\\\\pidgin-sipe.mo\\\"\\n\")\n\t\t  } sort keys %languages);\n    } elsif (/^;;; DELETE_FILES_LOCALE/) {\n\tprint map({\n\t           \"Delete \\\"\\$INSTDIR\\\\locale\\\\$_\\\\LC_MESSAGES\\\\pidgin-sipe.mo\\\"\\n\"\n\t\t  } sort keys %languages);\n    } else {\n\tprint;\n    }\n}\n\n# That's all folks...\nexit 0;\n"
  },
  {
    "path": "contrib/opensuse-build-service/pidgin-sipe-freerdp2.dsc",
    "content": "Format: 3.0 (quilt)\nSource: pidgin-sipe\nVersion: 1.25.0-1\nBinary: pidgin-sipe\nMaintainer: pidgin-sipe <jduser@noreply.com>\nArchitecture: any\nStandards-Version: 3.9.1\nBuild-Depends: cdbs (>= 0.4.23-1.1), autotools-dev, debhelper (>= 5), pkg-config, libglib2.0-dev (>= 2.28.0), libdbus-1-dev, libxml2-dev, libssl-dev, pidgin-dev, libpurple-dev (>= 2.8.0), appstream, libtool, intltool, libkrb5-dev, libzephyr-dev, libnice-dev (>= 0.1.0), libgstreamer1.0-dev, libgstreamer-plugins-base1.0-dev, libfarstream-0.2-dev, freerdp2-dev, libtelepathy-glib-dev (>= 0.24.0), libgmime-2.6-dev, gss-ntlmssp-dev (>= 0.5.0)\nHomepage: http://sipe.sourceforge.net/\n"
  },
  {
    "path": "contrib/opensuse-build-service/pidgin-sipe-gstreamer1.dsc",
    "content": "Format: 3.0 (quilt)\nSource: pidgin-sipe\nVersion: 1.25.0-1\nBinary: pidgin-sipe\nMaintainer: pidgin-sipe <jduser@noreply.com>\nArchitecture: any\nStandards-Version: 3.9.1\nBuild-Depends: cdbs (>= 0.4.23-1.1), autotools-dev, debhelper (>= 5), pkg-config, libglib2.0-dev (>= 2.28.0), libdbus-1-dev, libxml2-dev, libssl-dev, pidgin-dev, libpurple-dev (>= 2.8.0), appstream, libtool, intltool, libkrb5-dev, libzephyr-dev, libnice-dev (>= 0.1.0), libgstreamer1.0-dev, libgstreamer-plugins-base1.0-dev, libfarstream-0.2-dev, libtelepathy-glib-dev (>= 0.24.0), libgmime-2.6-dev, gss-ntlmssp-dev (>= 0.5.0)\nHomepage: http://sipe.sourceforge.net/\n"
  },
  {
    "path": "contrib/opensuse-build-service/pidgin-sipe-telepathy.dsc",
    "content": "Format: 3.0 (quilt)\nSource: pidgin-sipe\nVersion: 1.25.0-1\nBinary: pidgin-sipe\nMaintainer: pidgin-sipe <jduser@noreply.com>\nArchitecture: any\nStandards-Version: 3.9.1\nBuild-Depends: cdbs (>= 0.4.23-1.1), autotools-dev, debhelper (>= 5), pkg-config, libglib2.0-dev (>= 2.28.0), libdbus-1-dev, libxml2-dev, libssl-dev, pidgin-dev, libpurple-dev (>= 2.8.0), appstream-index, libtool, intltool, libkrb5-dev, libzephyr-dev, libtelepathy-glib-dev (>= 0.24.0), libgmime-2.6-dev\nHomepage: http://sipe.sourceforge.net/\n"
  },
  {
    "path": "contrib/opensuse-build-service/pidgin-sipe.changes",
    "content": "-------------------------------------------------------------------\nSat Oct 12 08:44:00 UTC 2019 - chemobejk@gmail.com\n\n- Update to version 1.25.0 \"Buddy Idle Time, RTF\" (2019-10-12)\n    - Feature #107: Provide idle start time for a buddy (Stefan Becker)\n    - Feature #77: RTF support (incoming) (Stefan Becker)\n      * the code only extracts plain text from incoming RTF\n    - Fixed #358: FTBFS with glib-2.0 >= 2.62.0 (Stefan Becker)\n    - Fixed #350: Inconsistent parsing of From:/To: headers (Stefan Becker)\n    - raise BR telepathy-glib >= 0.24.0 (Stefan Becker)\n    - switch from GPLv2+ to SPDX identifier GPL-2.0-or-later (Stefan Becker)\n\n-------------------------------------------------------------------\nSat Nov 10 15:40:00 UTC 2018 - chemobejk@gmail.com\n\n- Update to version 1.24.0 \"Application Sharing II\" (2018-11-10)\n    - Feature #104: Use user agent also for HTTP (Stefan Becker)\n    - Feature #6: Application Sharing Server (Jakub Adam)\n      * requires freerdp-shadow2\n    - Fixed #343: Build fails on FreeBSD\n    - add timeout handling for media streams (Alaoui Youness)\n    - update AppStream handling (Jakub Adam, Stefan Becker)\n    - fix missing localisation in some code modules (Stefan Becker)\n    - debug log improvements (Stefan Becker)\n\n-------------------------------------------------------------------\nMon Aug 20 14:47:00 UTC 2018 - chemobejk@gmail.com\n\n- Update to version 1.23.3 \"Bug Fixes III\" (2018-08-20)\n    - appshare: fix black screen with Remmina v1.2.0-rcgit.27 (Jakub Adam)\n    - various minor fixes (Jakub Adam, Michael Olbrich)\n    - fix compilation errors with libpurple 2.14.0 & GCC 8.0 (Jakub Adam, Stefan Becker)\n    - mingw: update fetch script to Pidgin 2.13.0 (Stefan Becker)\n\n-------------------------------------------------------------------\nSat Mar 10 15:54:29 UTC 2018 - chemobejk@gmail.com\n\n- Update to version 1.23.2 \"Bug Fixes II\" (2018-03-10)\n    - fix some HTTP requests that were not sent (Jakub Adam, Stefan Becker)\n\n-------------------------------------------------------------------\nSun Feb 25 13:05:00 UTC 2018 - chemobejk@gmail.com\n\n- Update to version 1.23.1 \"Bug Fixes I\" (2018-02-25)\n     - Fixed #338: Incorrect port 0 for IPv6 socket on Windows (Stefan Becker)\n     - Fixed #337: Duplicate candidates in SDP (Jakub Adam, Stefan Becker)\n     - Fixed #336: Lync autodiscover does not follow user redirect (Stefan Becker)\n     - media: unconditionally ignore multichannel codecs (Jakub Adam)\n     - updated translations: Turkish (tr)\n\n-------------------------------------------------------------------\nSat Oct 28 15:18:00 UTC 2017 - chemobejk@gmail.com\n\n- Update to version 1.23.0 \"D-Bus, IPv6, OS X 10.11+\" (2017-10-28)\n    - Feature #101: Mac OS X 10.13 OpenSSL support (Stefan Becker)\n    - Feature #100: Extend libpurple D-Bus interface (Stefan Becker)\n    - Feature #99: IPv6 addresses in SIP & SDP messages (Stefan Becker)\n    - Feature #96: Support for OS X 10.11+ SDK (Stefan Becker)\n    - don't load buddy photos from unknown sites by default (Jakub Adam, Stefan Becker)\n      * custom web URIs pose a security risk as they may be abused\n      * users can override this behaviour in the account settings\n      * Office365 accounts should not be affected by this change\n    - add support for GMime 3.0 API (Stefan Becker)\n    - raise BR glib-2.0 >= 2.18.0 (Stefan Becker)\n    - raise BR purple >= 2.7.0 (Stefan Becker)\n    - drop support for GMime 2.4 (Stefan Becker)\n    - drop support for gstreamer-0.10 (Stefan Becker)\n\n-------------------------------------------------------------------\nSun Jun 11 15:38:00 UTC 2017 - chemobejk@gmail.com\n\n- Update to version 1.22.1:\n    - Fixed #320: Multiple client detection broken (Stefan Becker)\n    - speed up Lync Autodiscover by using AccessLocation (Andrey Vaynberger)\n    - adium: update build instructions for Xcode 7.x or newer (Stefan Becker)\n      * the build environment used for releases 1.22.0 or older (Xcode 6.x\n        on OS X 10.11) is no longer available to the project\n      * releases starting with 1.22.1 will use Xcode 8.x on macOS 10.12\n      * build target continues to be OS X 10.9\n    - purple: avoid rare SSL read deadlock (Stefan Becker)\n    - various minor fixes (Michael Olbrich)\n    - crypto: make code compile with OpenSSL 1.1.0 (Stefan Becker)\n    - drop references to Reuters Messaging (Stefan Becker)\n    - updated translations: Lithuanian (lt), Russian (ru), Swedish (sv), Turkish (tr)\n\n-------------------------------------------------------------------\nWed Feb  1 16:58:00 UTC 2017 - chemobejk@gmail.com\n\n- Update to version 1.22.0:\n    - Feature #93: Support for Lync Autodiscover (Stefan Becker)\n    - Feature #6: Application Sharing Viewer (Jakub Adam)\n      * requires libpurple >= 2.12.0\n      * needs an external RDP client - remmina and xfreerdp are supported\n    - Fixed #315: Crash when contact list is empty (Stefan Becker)\n    - Fixed #314: sipe login problems with long pw (Stefan Becker)\n    - separate logging and debugging output (Stefan Becker)\n      * logging is always shown, e.g. in the Pidgin debug window\n      * full message debugging now requires PURPLE_UNSAFE_DEBUG=1\n    - new translations: Greek (el), Lithuanian (lt)\n\n-------------------------------------------------------------------\nSat May 28 16:50:00 UTC 2016 - chemobejk@gmail.com\n\n- Update to version 1.21.1:\n    - various bug fixes in media support (Jakub Adam)\n    - configure no longer ignores CFLAGS/LDFLAGS/LIBS (Stefan Becker)\n\n-------------------------------------------------------------------\nSat Apr 23 14:16:00 UTC 2016 - chemobejk@gmail.com\n\n- Update to version 1.21.0:\n    - Feature #91: Support embedded XML as buddy photo URL (Stefan Becker)\n    - Feature #90: Add AppStream metadata file (Jiri Eischmann, Stefan Becker)\n    - Feature #89: Improve \"Join scheduled conference\" dialog  (Stefan Becker)\n    - Feature #87: Support multiple HTTP cookies (Stefan Becker)\n    - Feature #85: XML raw extract should ignore name space (Stefan Becker)\n    - Fixed #311: Crash when SIP transport becomes invalid (Stefan Becker)\n    - Fixed #293: Mandatory wsa:MessageID node missing (Stefan Becker)\n    - add support for Lync File Transfer protocol (Jakub Adam)\n      * requires libpurple >= 2.12.0\n      * Lync FT will be used for sending files when Lync 2013 is detected\n    - add build options to \"About SIPE plugin\" message (Stefan Becker)\n\n-------------------------------------------------------------------\nSat Oct 24 13:36:00 UTC 2015 - chemobejk@gmail.com\n\n- Update to version 1.20.1:\n    - add support for another type of ADFS response (Stefan Becker)\n    - improve configure check for back-ported features (Stefan Becker, Jakub Adam)\n    - updated translations: French (fr), Russian (ru)\n\n-------------------------------------------------------------------\nSat Aug 29 16:41:00 UTC 2015 - chemobejk@gmail.com\n\n- Update to version 1.20.0:\n    - Feature #82: Parse HTML from Lync conference URL (Stefan Becker)\n    - Feature #69: SRTP Support (Jakub Adam)\n      * requires libpurple >= 3.0.0\n    - Fixed #285: Office365 rejects RC4 in TLS-DSK (Stefan Becker)\n      * added support for AES-128/256-CBC\n\n-------------------------------------------------------------------\nSat Apr  4 15:13:00 UTC 2015 - chemobejk@gmail.com\n\n- Update to version 1.19.1:\n    - Fixed #278: 488 error after libnice upgrade (Jakub Adam)\n    - fix SIP re-authentication timeout to be max. 8 hours (Stefan Becker)\n\n-------------------------------------------------------------------\nSat Feb  7 11:48:00 UTC 2015 - chemobejk@gmail.com\n\n- Update to version 1.19.0:\n    - Feature #80: Move parsing of login name (Stefan Becker)\n    - Feature #79: support for Adium group chat bookmarks (David Matz, Stefan Becker)\n    - Feature #78: Support searching for SIP ID (Stefan Becker)\n    - Feature #76: ADFS can't always be used (Stefan Becker)\n      * for accounts that have Multi-Factor Authentication (MFA) enabled\n    - Feature #73: Support buddy photos from contactCard (Stefan Becker)\n    - Feature #65: Fall back from Kerberos to NTLM (Stefan Becker)\n    - Fixed #277: Raised contact names (Stefan Becker)\n    - Fixed #240: Corrupted HTTP response crashes SIPE (Stefan Becker)\n    - fix calendar state machine when EWS URL is set (Stefan Becker)\n    - fall back to [MS-DLX] BasicSearch to improve search experience (Stefan Becker, various)\n    - implement search functionality for UCS (Stefan Becker)\n    - adium: add chat room list UI (David Matz)\n    - adium: fix duplicate debug log messages (Stefan Becker)\n    - support for libnice TCP mode (Youness Alaoul, Jakub Adam)\n    - refactor CCCP request code (Jakub Adam)\n\n-------------------------------------------------------------------\nTue Dec 29 23:52:00 UTC 2014 - chemobejk@gmail.com\n\n- Update to new upstream version, 1.18.5:\n    - Fixed #276: Redundant \"const\" breaks build with clang (Stefan Becker)\n    - Fixed #269: purple idle-away converted to Away (Stefan Becker)\n    - svc: use authuser for RealmInfo request (Stefan Becker)\n    - adium: add release checking script (Stefan Becker)\n    - mingw: update fetch script to Pidgin 2.10.11 (Stefan Becker)\n    - updated translations: Italian (it), Swedish (sv)\n\n-------------------------------------------------------------------\nSat Oct 18 15:42:00 UTC 2014 - chemobejk@gmail.com\n\n- Update to new upstream version, 1.18.4:\n    - Fixed #263: ADFS fails when user and login name differ (Stefan Becker)\n    - Fixed #262: Adium: SIPE doesn't auto- or re-connect (Stefan Becker)\n    - fixed memory leaks (Stefan Becker)\n    - fixed processing of presence publish event response (John Zhang, Stefan Becker)\n      * fixes a longstanding issue that the Pidgin user status sometimes\n        didn't switch back to \"Available\" after the end of a meeting\n\n-------------------------------------------------------------------\nSat Aug 16 12:50:00 UTC 2014 - chemobejk@gmail.com\n\n- Update to new upstream version, 1.18.3:\n    - Fixed #259: HTML response to EWS autodiscover triggers libxml2 assert (Stefan Becker)\n    - Fixed #258: V&V call gets rejected when IPv6 is enabled (Stefan Becker, Jakub Adam)\n    - Fixed #257: Windows 7: SIPE crashes after a minute (Stefan Becker)\n    - mingw: improve crash information reporting (Stefan Becker)\n\n-------------------------------------------------------------------\nSat Jun  7 18:08:00 UTC 2014 - chemobejk@gmail.com\n\n- Update to new upstream version, 1.18.2:\n    - Fixed #255: Crash when PersistentChat sends BYE instead of response (Stefan Becker)\n    - Fixed #248: Remove libpurple SSL configure check (Stefan Becker)\n    - Fixed #245: \"Unable to resolve DNS SRV record\" error when joining conference (Stefan Becker)\n    - Fixed #241: Adium filters \":\" from \"sip:\" (Stefan Becker)\n    - Fixed #210: Conference call ends with error message (for real this time, Jakub Adam)\n    - ews: extract settings also from type EXPR (Stefan Becker)\n    - ucs: honor user specified email URL (Stefan Becker)\n    - adium: fix compilation on OS X 10.7 (Stefan Becker)\n    - updated Transifex URLs (Stefan Becker)\n    - updated translations: Hindi (hi), Telugu (te)\n\n-------------------------------------------------------------------\nSat Apr 12 18:08:00 UTC 2014 - chemobejk@gmail.com\n\n- Update to new upstream version, 1.18.1:\n    - Fixed #238: False \"not delivered\" in conference (Stefan Becker)\n    - Fixed #237: HTML escaping not removed from URL (Stefan Becker)\n    - Fixed #210: Conference call ends with error message (Jakub Adam)\n    - fix endless loop with failed HTTP Basic authentication (Stefan Becker)\n    - fix crash when gstreamer nice plugin is missing (Stefan Becker, Jakub Adam)\n    - fix EWS autodiscover for some Office 365 users (Stefan Becker)\n    - purple: fix missing \"Copy to\" in buddy menu (Stefan Becker)\n    - purple/adium: ignore empty search values (Stefan Becker)\n    - adium: fix group chat UI (Stefan Becker)\n    - adium: implement BEAST mitigations for 10.8.5 (Michael Lamb)\n    - add indication when user is connected from a mobile device (Harris Kauffman)\n    - updated translations: Chinese (zh_CN), Portuguese (pt)\n\n-------------------------------------------------------------------\nSat Jan 11 15:43:00 UTC 2014 - chemobejk@gmail.com\n\n- Update to new upstream version, 1.18.0:\n    - Feature #71: Add support for EWS Autodiscover redirection (Stefan Becker)\n    - Feature #69: Add UI support for (group) chats (Michael Lamb)\n      * NOTE: Adium does not have an UI to fetch the room list\n    - Feature #64: Add support for GSS-NTLMSSP (Stefan Becker)\n      * sip-sec-krb5.c module has been renamed to sip-sec-gssapi.c\n      * if gssapi/gssapi_ntlmssp.h is detected then sip-sec-ntlm.c will\n        be disabled and NTLM will be handled by sip-sec-gssapi.c instead\n      * NOTE: at the time of this writing the user has to set up\n              GSS-NTLMSSP by hand on his system, i.e. /etc/gss/mech\n    - Fixed #227: Adium client doesn't save email option settings (Harris P. Kauffman)\n    - Fixed #216: SIPE stops working on Mavericks (Stefan Becker, Michael Lamb)\n      * add an UI option to disable SSL BEAST mitigations\n      * NOTE: requires Adium 1.5.10\n    - Fixed #197: Account stays in connecting stage (Harris P. Kauffman)\n    - cleanup for sip-sec Kerberos & SSPI modules (Stefan Becker)\n      * replace old TGT hack with gss_acquire_cred_with_password()\n      * clean up Kerberos detection in configure\n      * remove special case handling; code is more straight-forward now\n      * thanks to David Woodhouse and Simo Sorce for the GSSAPI information\n    - implement internal keepalive handling (Stefan Becker)\n    - implement crypto backend based on OpenSSL (Stefan Becker)\n    - adium: Xcode project files update (Michael Lamb)\n    - adium: replace NSS crypto backend with OpenSSL (Stefan Becker)\n      * NOTE: please make sure to read the updated build instructions!\n\n-------------------------------------------------------------------\nWed Dec 11 19:40:00 UTC 2013 - chemobejk@gmail.com\n\n- Update to new upstream version, 1.17.3:\n    - Fixed #225: HTTP re-authentication with NTLM fails (Stefan Becker)\n    - Fixed #222: SIPE crashes when groupchat session expires (Stefan Becker)\n    - fix UCS Persona key extraction (Stefan Becker)\n\n-------------------------------------------------------------------\nSat Nov 30 16:49:00 UTC 2013 - chemobejk@gmail.com\n\n- Update to new upstream version, 1.17.2:\n    - Fixed #214: Typing notification does not always work (Stefan Becker)\n      * reverted one change which caused problems for some users\n    - Fixed #222: SIPE crashes when groupchat session expires (Stefan Becker)\n    - updated translations: Romanian (ro)\n\n-------------------------------------------------------------------\nSat Nov 16 14:46:00 UTC 2013 - chemobejk@gmail.com\n\n- Update to new upstream version, 1.17.1:\n    - Fixed #215: Password not entity encoded in WSSE element (Stefan Becker)\n    - Fixed #214: Typing notification does not always work (Stefan Becker)\n    - accept alternatives for webticket timestamp/keydata (Stefan Becker)\n    - adium: add \"don't publish calendar\" to account UI (Stefan Becker)\n    - contrib: add SSL BEAST mitigation patch for Adium (Stefan Becker)\n    - updated translations: French (fr)\n\n-------------------------------------------------------------------\nSat Sep 21 14:06:00 UTC 2013 - chemobejk@gmail.com\n\n- Update to new upstream version, 1.17.0:\n    - Feature #62: Support for Lync 2013 Unified Contact Store (Stefan Becker)\n    - Feature #59: Support for Lync 2013 Persistent Chats (Stefan Becker)\n    - Fixed #211: Status \"away\" or \"busy\" incorrectly mapped to \"Invisible\" (Michael Lamb)\n    - Fixed #209: group chat doesn't like HTML (Stefan Becker)\n    - Fixed #200: OCS archiving system blocks audio/video connection (Jakub Adam)\n    - Fixed #187: Duplicate messages in group chat (Stefan Becker)\n    - Fixed #184: Duplicate users showing in Group Chat (Stefan Becker)\n    - fix EWS autodiscover for Office 365 (Stefan Becker)\n    - add support for group chat history (Stefan Becker)\n    - add support for buddy photos on Lync 2013 (Stefan Becker)\n\n-------------------------------------------------------------------\nSat Jul 13 14:29:00 UTC 2013 - chemobejk@gmail.com\n\n- Update to new upstream version, 1.16.1:\n    - Feature #66: Windows DLL version information (Stefan Becker)\n    - fix call failure when host has multiple IP addresses (Jakub Adam)\n    - fix buddy list handling after moving to Lync 2013 (Stefan Becker)\n      * Lync 2013 migrates buddy list to Unified Contact Store (UCS)\n      * NOTE: modifying the buddy list is *NOT* supported yet!\n    - crash fixes for new HTTP stack (Stefan Becker)\n\n-------------------------------------------------------------------\nSat Jun  8 16:58:00 UTC 2013 - chemobejk@gmail.com\n\n- Update to new upstream version, 1.16.0:\n    - Feature #58: Implement Digest authentication scheme for SIP Proxy Authentication (Stefan Becker)\n    - Fixed #196: Useragent value not forwarded to core (Michael Lamb)\n    - Fixed #193: Pidgin Status changes stop working (Stefan Becker)\n    - Fixed #186: Users appear offline when they are not (Stefan Becker)\n    - fix kinit-less use case with krb5 >= 1.11 (Stefan Becker)\n    - rewritten HTTP stack from scratch (Stefan Becker)\n      * cleaner, layered and hopefully less error-prone implementation\n      * HTTP stack internals no longer exposed to user code\n      * reduced network traffic and less SSL handshakes by utilizing HTTP/1.1\n        connection keep alive for multiple HTTP requests to the same host\n    - switch purple backend to deferred destruction approach (Stefan Becker)\n      * Pidgin should no longer crash at connection close, even in corner cases\n    - add menu entry to make a call with a phone number (Jakub Adam)\n    - some progress on telepathy backend (Stefan Becker)\n      * add TLS certificate accept/reject user interaction\n      * add \"Single Sign-On\" & \"Don't Publish Calendar\" account options\n\n-------------------------------------------------------------------\nSun Apr  7 12:44:00 UTC 2013 - chemobejk@gmail.com\n\n- Update to new upstream version, 1.15.1:\n    - NOTE: SIPE SourceForge project got updated. Because of this all bug and feature request numbers have changed.\n    - Fixed #190: SIP 407 response rejected with invalid message signature (Stefan Becker)\n    - Fixed #189: Adium SIPE plugin vs. libpurple linking issues (Michal Lamb)\n    - fixed free-after-use issue that caused crashes for some users (Stefan Becker)\n    - fixed broken NTLM fallback in Negotiate (Stefan Becker)\n    - fixed subscriptions expiration by subscribing again after re-authentication (Stefan Becker)\n    - allow different user name and login for Office 365 authentication (Stefan Becker)\n    - add SIPE version & git commit ID to debug log (Stefan Becker)\n    - added valgrind log analyzer script (Stefan Becker)\n    - added NTLM message anaylzer (Stefan Becker)\n    - updated translations: Hungarion (hu), Romanian (ro)\n    - updated Adium port (Michael Lamb, Harris P. Kauffman)\n\n-------------------------------------------------------------------\nMon Apr  1 13:42:00 UTC 2013 - chemobejk@gmail.com\n\n- New project maintainer\n- Fast forward files to prepare for upcoming 1.15.1 release\n- Replace old Debian packaging files with new 3.0 (quilt) ones\n- Add repository specific Debian .dsc to enable V&V where possible\n\n-------------------------------------------------------------------\nWed Aug  8 11:57:14 UTC 2012 - john@redux.org.uk\n\n- Update to new upstream version, 1.13.2:\n    - tls: fix buffer overrun (Oleksandr Hryshchuk, Stefan Becker)\n    - win32: fix TCP connections (Stefan Becker)\n    - nsis: fix broken locale installation (Stefan Becker)\n    - updated translations: French (fr)\n    - various build fixes (Stefan Becker, Jakub Adam) \n\n-------------------------------------------------------------------\nWed May 16 10:56:37 UTC 2012 - john@redux.org.uk\n\n- Update to new upstream version, 1.13.1:\n    - detect incompatible encryption level with Lync (Jakub Adam)\n    - purple: add URI validity check to Add Buddy callback (Stefan Becker)\n    - new translations: Romanian (ro), Turkish (tr)\n    - various build fixes (Stefan Becker)\n    - added [MS-SIPAE] TLS-DSK authentication scheme (Stefan Becker)\n      * TLS-DSK has been introduced in Lync\n      * mandatory for Office365 accounts\n      * also works for non-public Lync installations\n      * does not work yet with SSPI on Windows\n    - added [MS-DLX] based Get Info/Contact Search (Stefan Becker)\n      * [MS-PRES] SIP-Based Active Directory Search is disabled in Lync\n    - added experimental media TCP transport (Jakub Adam)\n    - make it compile against the latest purple 3.0.x API (Stefan Becker)\n    - make it compile against the latest glib2 2.31.x API (Stefan Becker)\n    - completed cleanup: core no longer requires libpurple (Stefan Becker)\n    - refactored crypto code, ie. NSS can replaced if necessary (Stefan Becker)\n    - sipe-domino.c is no longer built under UNIX to remove dead code (Stefan Becker)\n    - restricted XXX_CFLAGS to modules that need them (Stefan Becker)\n    - NSS is now a mandatory build requirement (Stefan Becker)\n    - decoupled SSPI from HAVE_LIBKRB5 flag. New flag is HAVE_SSPI (Stefan Becker)\n    - OBS mingw packages now use SSPI instead of NTLM (Stefan Becker)\n    - added NSIS package generation to OBS mingw packages (Stefan Becker)\n    - removed kopete backend. KDE is moving to telepathy (Stefan Becker)\n    - added MinGW cross-compilation on Linux instructions (Stefan Becker)\n\n-------------------------------------------------------------------\nTue Sep 20 20:27:56 UTC 2011 - john@redux.org.uk\n\n- Update to version 1.12.0\n + Feature #3064877: Add support for OCS2007R2 Group Chat (Stefan Becker)\n + Feature #3311026: Support for HTTP/1.1 Transfer-Encoding: chunked (Stefan Becker)\n + Fixed #2834758: First NTLM signature check after startup fails (Stefan Becker) \n + Fixed #3082602: Crash on Autodiscover (Stefan Becker)\n + Fixed #3090663: Re-authentication fails (Stefan Becker)\n + Fixed #3092324: Core dump in \"make check\" (psfales)\n + Fixed #3130915: Failed to authenticate to server (Stefan Becker)\n + Fixed #3148124: sipe segfaults during login on Solaris (Jakub Adam)\n + Fixed #3150482: \"configure --with-vv\" test uses wrong include (Stefan Becker)\n + Fixed #3156430: Messages not Delivered (rwinchsf, Stefan Becker)\n + Fixed #3161273: Lost Connection Gives No Error Message (rwinchsf, Stefan Becker)\n + Fixed #3198585: Extra line breaks (Stefan Becker)\n + Fixed #3267073: False \"could not be delivered\" errors (sort of..., Stefan Becker)\n + Fixed #3399007: Crash when sipe_cal_working_hours->days_of_week is NULL (Stefan Becker)\n + Patch #3091490: Make 1.11.0 Compile on FreeBSD (jprather)\n + Patch #3108246: Patch for better windows installer (archrival, galiven)\n + add random Ms-Conversation-ID to INVITE (Jakub Adam)\n + fix parsing of P-Asserted-Identity header (Jakub Adam)\n + added MS TURN support (Jakub Adam)\n + fix crash on zero length password in NTLM (Vladimir Ushakov)\n + implement timeouts for SIP request. Used for REGISTER (Stefan Becker)\n + more work on Voice & Video call support (Jakub Adam)\n + make it compile against the purple 2.8.x & 3.0.x APIs (Stefan Becker)\n + more internal changes to prepare for non-purple backends (Stefan Becker)\n + added integration for transifex.net update (Stefan Becker)\n + configure improvements for 64-bit: use libdir, gsize/size_t compatibility (Stefan Becker)\n + update compiler warnings configuration for all build platforms (Stefan Becker)\n + updated Adium port (Matthew Duggan)\n + mingw build updates (Harris P. Kauffman, Stefan Becker)\n + added miranda port (Jochen De Smet)\n + added mingw to OpenSUSE Build Service configuration (Stefan Becker) \n\n-------------------------------------------------------------------\nFri Feb  4 20:24:34 UTC 2011 - john@redux.org.uk\n\n- Update to version 1.11.2\n  + fix parsing of P-Asserted-Identity header\n  + Fixed memory leaks\n  + Fixed bug #3090663: Re-authentication failures\n  + Fixed bug #3092324: Core dump in \"make check\"\n  + Fixed bug #2834758: First NTLM signature check after starup\n    fails\n  + Fix memory leak in sipe_backend_transport_connect() error path\n  + Fixed bug #3082602: Crash on Autodiscover\n  + Configure now uses libdir and datadir\n  + configure: update 32-bit vs. 64-bit header conflict test\n  + debian: build stability fix in post-install\n\n-------------------------------------------------------------------\nWed Oct  6 08:36:02 UTC 2010 - john@redux.org.uk\n\n- Update to version 1.11.0\n\n-------------------------------------------------------------------\nMon Jun 28 08:43:10 UTC 2010 - john@redux.org.uk\n\n- Update to version 1.10.1\n  + Fixed bug in the SIPE buddy list hash table functionality\n    reported by a RHEL5 user.\n  + Fixed Pidgin 2.7.0 API compatibility.\n\n-------------------------------------------------------------------\nThu Feb 11 01:15:00 CET 2010 - pier11@operamail.com\n\n- Update to version 1.8.1:\n  + many crash fixes for error or corner cases in calendar\n    integration\n  + more detailed code analysis with Coverity Prevent\n  + OpenSUSE Build Service configuration files\n  + Fix NTLM crash if login setting is undefined\n  + Use of g_str_has_prefix() available since glib 2.2 and\n    null-safe\n  + build fixes for older OS releases, e.g. Ubuntu older than 9.10\n- Changed source from .bz2 to .gz. Seems OBS for Debian doesn't\n  understand .bz2 source file.\n\n-------------------------------------------------------------------\nThu Feb 11 01:15:00 CET 2010 - vuntz@opensuse.org\n\n- Update to version 1.8.0:\n  + Added integration with Exchange 2007/2010.\n  + Added Calendar information to contact's tooltip.\n  + 2005 presence engine has been completely rewritten, with new\n    supported status.\n  + Added \"Accounts->{SIPE_ACCOUNT}->Status Reset\" menu option to\n    clean User Status set manually.\n  + Added \"Find on LinkedIn\" link on contact's User Info screen.\n  + Enhanced custom NTLM security provider to pass\n    connection-oriented authentication.\n  + Added Negotiate authentication scheme (Windows only).\n  + Contributed code for Adium port.\n  + Added Windows Messenger 5.0 (RTC/1.2) compatibility.\n  + New BusyIdle status.\n  + Fix memory leaks.\n  + Fixed localization on Windows platform.\n  + Fix bad rendering with html markup.\n  + Fix broken federated contacts.\n  + Fix for server auto-discovery\n  + Fix for xdg-email invocation.\n  + Fix for User Agent string.\n  + Code: Take PURPLE_INIT_PLUGIN into use.\n  + Various other fixes, including crashes and build fixes.\n  + Updated translations.\n\n-------------------------------------------------------------------\nSun Dec 27 00:30:08 CET 2009 - vuntz@opensuse.org\n\n- Clean up packaging.\n- Remove gconf_schemas_prereq macro, since there's nothing\n  involving gconf.\n- Rename purple-sipe subpackage to libpurple-plugin-sipe.\n- Add pidgin BuildRequires for directory ownership.\n- Add pidgin Requires for pidgin-sipe.\n- Add libpurple Enhances for libpurple-plugin-sipe.\n\n-------------------------------------------------------------------\nThu Nov 26 09:54:24 UTC 2009 - john@redux.org.uk\n\n- Update to version 1.7.1:\n  + See ChangeLog for the full list of changes since version 1.3.3.\n  + Support for Reuters Messaging environment.\n  + Support for message formatting.\n  + Invisible mode.\n  + Full support for presence.\n  + Better support of protocol.\n  + New security framework.\n  + Multi-party conversation.\n  + Add telepathy-haze support.\n  + Add integration with PBX (external phones).\n  + New Idle status.\n  + Many improvements and bug fixes.\n  + Fix crashes.\n  + Build fixes.\n  + Updated translations.\n- Split the package into pidgin-sipe and purple-sipe packages.\n- Add gettext-devel, libtool BuildRequires.\n- Remove pidgin, pidgin-devel, zlib-devel BuildRequires.\n- Pass --with-krb5 to configure.\n- Enable parallel build.\n\n-------------------------------------------------------------------\nThu Sep 17 00:13:39 CEST 2009 - crrodriguez@suse.de\n\n- use find_lang macro \n\n-------------------------------------------------------------------\nMon Feb  2 17:04:37 CST 2009 - gburt@suse.de\n\n- Fix total loss of functionality if user was logged on in more than\n  one location (bnc#459117)\n\n-------------------------------------------------------------------\nThu Jan 22 16:38:11 CST 2009 - gburt@suse.de\n\n- Patch fixing support for LCS 2005 buddy auth/blocking\n- Fix logging in with TCP when no SRV records found\n- Fix several crasher bugs\n\n-------------------------------------------------------------------\nMon Jan  5 11:37:47 CST 2009 - gburt@suse.de\n\n- Update to 1.3.3 which includes fixes for translation support,\n  typos, crashes, and error handling.\n\n-------------------------------------------------------------------\nTue Dec  9 17:42:50 CST 2008 - gburt@suse.de\n\n- Remove -lang package, too late for package splits\n\n-------------------------------------------------------------------\nSun Dec  7 17:42:13 CST 2008 - gburt@suse.de\n\n- Create -lang package\n\n-------------------------------------------------------------------\nSun Dec  7 15:38:42 CST 2008 - gburt@suse.de\n\n- Fix a segfault, fix compatibility bug with OCS 2005 (not handling\n  180 Ringing responses properly).\n\n-------------------------------------------------------------------\nFri Dec  5 12:13:58 CST 2008 - gburt@suse.de\n\n- Fix automatic support (redirecting) for LCS/OCS proxy servers, \n  and show the user the error when 403 forbidden is received.\n\n-------------------------------------------------------------------\nThu Dec  4 17:47:08 CST 2008 - gburt@suse.de\n\n- Fix bugs with ability to set status, add support for setting a\n  note (at least against some servers), fix OCS 2005 support, and\n  improve account editing dialog to be more friendly, and improve\n  error messages.\n\n-------------------------------------------------------------------\nWed Dec  3 18:40:14 CST 2008 - gburt@suse.de\n\n- Fix bugs with ability to add, modify, and remove contacts and\n  groups.  Fix support for detecting contacts' away status, and\n  to send them ours.  Fix support for saving and reading buddy\n  aliases to/from the server.  Fix many crashes.\n\n-------------------------------------------------------------------\nThu Nov 20 19:16:41 CST 2008 - gburt@suse.de\n\n- Fix compatibility with Microsoft OCS 2007; 2-way IMing working\n\n-------------------------------------------------------------------\nFri Nov  7 12:33:37 CST 2008 - gburt@suse.de\n\n- Replace gz with bz2 \n\n-------------------------------------------------------------------\nFri Nov  7 12:22:30 CST 2008 - gburt@suse.de\n\n- Update tarball with latest code from git plus a patch to get\n    NTLM signing of messages working (eco#5322)\n\n-------------------------------------------------------------------\nTue Sep  2 10:21:53 CDT 2008 - gburt@suse.de\n\n- Clarify and simplify the package description\n\n-------------------------------------------------------------------\nMon Aug 11 11:21:48 CDT 2008 - gburt@suse.de\n\n- Initial package for pidgin-sipe\n- SIPE 1.2\n- http://sipe.sourceforge.net/\n\n"
  },
  {
    "path": "contrib/opensuse-build-service/pidgin-sipe.nsi.template",
    "content": ";NSIS Modern User Interface\n;Basic Example Script\n;Written by Joost Verburg\n\n;--------------------------------\n;Include Modern UI\n\n!include \"MUI.nsh\"\n\n;--------------------------------\n;General\n\n;Name and file\nName \"Pidgin SIPE Plugin\"\nOutFile \"pidgin-sipe-${VERSION}.exe\"\n\n;Default installation folder\nInstallDir \"$PROGRAMFILES\\Pidgin\"\n\n;Get installation folder from registry if available\nInstallDirRegKey HKLM \"Software\\pidgin\" \"\"\n\n;\nSetCompressor /FINAL /SOLID lzma\nSetCompressorDictSize 64\n\n;--------------------------------\n;Interface Settings\n\n!define MUI_ABORTWARNING\n\n;--------------------------------\n;Pages\n\n;!insertmacro MUI_PAGE_LICENSE \"Basic.nsi\"\n;!insertmacro MUI_PAGE_COMPONENTS\n!insertmacro MUI_PAGE_DIRECTORY\n!insertmacro MUI_PAGE_INSTFILES\n\n!insertmacro MUI_UNPAGE_CONFIRM\n!insertmacro MUI_UNPAGE_INSTFILES\n\n;--------------------------------\n;Languages\n\n!insertmacro MUI_LANGUAGE \"English\"\n\n;--------------------------------\n;Installer Sections\n\nSection \"PidginSIPE\" SecPidginSIPE\nSetOutPath \"$INSTDIR\\plugins\"\nFile \"${MINGW_LIBDIR}\\purple-2\\libsipe.dll\"\nSetOutPath \"$INSTDIR\\pidgin-${PIDGIN_VERSION}-dbgsym\\plugins\"\nFile \"${MINGW_LIBDIR}\\purple-2\\libsipe.dll.dbgsym\"\nSetOutPath \"$INSTDIR\\pixmaps\\pidgin\\protocols\\16\"\nFile \"${MINGW_DATADIR}\\pixmaps\\pidgin\\protocols\\16\\sipe.png\"\nSetOutPath \"$INSTDIR\\pixmaps\\pidgin\\protocols\\22\"\nFile \"${MINGW_DATADIR}\\pixmaps\\pidgin\\protocols\\22\\sipe.png\"\nSetOutPath \"$INSTDIR\\pixmaps\\pidgin\\protocols\\48\"\nFile \"${MINGW_DATADIR}\\pixmaps\\pidgin\\protocols\\48\\sipe.png\"\nSetOutPath \"$INSTDIR\\pixmaps\\pidgin\\protocols\\scalable\"\nFile \"${MINGW_DATADIR}\\pixmaps\\pidgin\\protocols\\scalable\\sipe.svg\"\n;;; INSTALL_FILES_LOCALE\n\n;Create uninstaller\nWriteUninstaller \"$INSTDIR\\Uninstall-pidgin-sipe.exe\"\n\nSectionEnd\n\n;--------------------------------\n;Descriptions\n\n;Language strings\nLangString DESC_SecPidginSIPE ${LANG_ENGLISH} \"The Pidgin SIPE Plugin.\"\n\n;Assign language strings to sections\n;!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN\n;\t!insertmacro MUI_DESCRIPTION_TEXT ${SecPidginPP} $(DESC_SecPidginPP)\n;!insertmacro MUI_FUNCTION_DESCRIPTION_END\n\n;--------------------------------\n;Uninstaller Section\n\nSection \"Uninstall\"\n\n;ADD YOUR OWN FILES HERE...\n\nDelete \"$INSTDIR\\Uninstall-pidgin-sipe.exe\"\nDelete \"$INSTDIR\\plugins\\libsipe.dll\"\nDelete \"$INSTDIR\\pidgin-${PIDGIN_VERSION}-dbgsym\\plugins\\libsipe.dll.dbgsym\"\nDelete \"$INSTDIR\\pixmaps\\pidgin\\protocols\\16\\sipe.png\"\nDelete \"$INSTDIR\\pixmaps\\pidgin\\protocols\\22\\sipe.png\"\nDelete \"$INSTDIR\\pixmaps\\pidgin\\protocols\\48\\sipe.png\"\nDelete \"$INSTDIR\\pixmaps\\pidgin\\protocols\\scalable\\sipe.svg\"\n;;; DELETE_FILES_LOCALE\n\nSectionEnd\n\n"
  },
  {
    "path": "contrib/opensuse-build-service/pidgin-sipe.spec",
    "content": "#\n# OBS SPEC file to generate a RPM for pidgin-sipe.\n#\n# It has support for:\n#\n#     RedHat family (CentOS, Fedora, RHEL, ScientificLinux)\n#     SUSE family (openSUSE, SLED, SLES)\n#     Mageia\n#     Windows (mingw32, mingw64)\n#\n\n# Build options\n%undefine build_telepathy\n\n# Check for mingw32 cross compilation build\n#\n# Manually add this repository to your private OBS project:\n#\n#  <repository name=\"mingw32\">\n#    <path repository=\"openSUSE_13.2\" project=\"windows:mingw:win32\"/>\n#    <arch>i586</arch>\n#  </repository>\n#\n%if \"%{_repository}\" == \"mingw32\"\n%define purple_sipe_mingw32 1\n%define mingw_prefix        mingw32-\n%define mingw_cache         %{_mingw32_cache}\n%define mingw_configure     %{_mingw32_configure}\n%define mingw_datadir       %{_mingw32_datadir}\n%define mingw_debug_package %{_mingw32_debug_package}\n%define mingw_ldflags       MINGW32_LDFLAGS\n%define mingw_libdir        %{_mingw32_libdir}\n%define mingw_make          %{_mingw32_make}\n%define mingw_makeinstall   %{_mingw32_makeinstall}\n%define __strip             %{_mingw32_strip}\n%define __objdump           %{_mingw32_objdump}\n%define _use_internal_dependency_generator 0\n%define __find_requires     %{_mingw32_findrequires}\n%define __find_provides     %{_mingw32_findprovides}\n%define __os_install_post   %{_mingw32_debug_install_post} \\\n                            %{_mingw32_install_post}\n%endif\n\n# Check for mingw64 cross compilation build\n#\n# Manually add this repository to your private OBS project:\n#\n#  <repository name=\"mingw64\">\n#    <path repository=\"openSUSE_13.2\" project=\"windows:mingw:win64\"/>\n#    <arch>i586</arch>\n#  </repository>\n#\n%if \"%{_repository}\" == \"mingw64\"\n%define purple_sipe_mingw64 1\n%define mingw_prefix        mingw64-\n%define mingw_cache         %{_mingw64_cache}\n%define mingw_configure     %{_mingw64_configure}\n%define mingw_datadir       %{_mingw64_datadir}\n%define mingw_debug_package %{_mingw64_debug_package}\n%define mingw_ldflags       MINGW64_LDFLAGS\n%define mingw_libdir        %{_mingw64_libdir}\n%define mingw_make          %{_mingw64_make}\n%define mingw_makeinstall   %{_mingw64_makeinstall}\n%define __strip             %{_mingw64_strip}\n%define __objdump           %{_mingw64_objdump}\n%define _use_internal_dependency_generator 0\n%define __find_requires     %{_mingw64_findrequires}\n%define __find_provides     %{_mingw64_findprovides}\n%define __os_install_post   %{_mingw64_debug_install_post} \\\n                            %{_mingw64_install_post}\n%endif\n\n%define purple_plugin    %{?mingw_prefix:%{mingw_prefix}}libpurple-plugin-sipe\n%define telepathy_plugin %{?mingw_prefix:%{mingw_prefix}}telepathy-plugin-sipe\n%define nsis_package     %{?mingw_prefix:%{mingw_prefix}}pidgin-sipe-nsis\n%define common_files     sipe-common\n%define empathy_files    empathy-sipe\n%define ktp_files        ktp-accounts-kcm-sipe\n\n\n%if 0%{?mageia}\n%if %{mageia} > 6\n%define has_freerdp 1\n%define has_gssntlmssp 1\n%else\n%define has_appstream_legacy 1\n%endif\n%define has_appstream 1\n%define has_gstreamer 1\n%endif\n\n%if 0%{?suse_version}\n%if 0%{?is_opensuse}\n%define has_appstream 1\n%define has_appstream_legacy 1\n%if 0%{?suse_version} >= 1500\n%define has_freerdp 1\n%else\n%define build_empathy 1\n%endif\n%endif\n%define has_gstreamer 1\n%define build_telepathy 1\n%endif\n\n%if 0%{?suse_version}\n%define pkg_group Productivity/Networking/Instant Messenger\n%else\n%define pkg_group Applications/Communications\n%endif\n\n# workaround for Fedora Rawhide\n%if 0%{?fedora_version}\n%if 0%{?fedora}\n%else\n%define fedora %{?fedora_version}\n%endif\n%endif\n\n%if 0%{?fedora}\n%define has_appstream 1\n%if %{fedora} <= 29\n%define build_empathy 1\n%endif\n%if %{fedora} <= 26\n%define has_appstream_legacy 1\n%endif\n%if %{fedora} > 25\n%define has_freerdp 1\n%endif\n%define has_gssntlmssp 1\n%define has_gstreamer 1\n%define build_telepathy 1\n%define build_ktp 1\n%endif\n\n%if 0%{?centos_version} || 0%{?scientificlinux_version}\n%define has_krb5devel 1\n%define rhel_base_version %{?centos_version}%{?scientificlinux_version}\n%if %{rhel_base_version} >= 800\n%define has_gstreamer 1\n%endif\n%endif\n\n%if 0%{?purple_sipe_mingw32}\nName:           mingw32-pidgin-sipe\n%else\n%if 0%{?purple_sipe_mingw64}\nName:           mingw64-pidgin-sipe\n%else\nName:           pidgin-sipe\n%endif\n%endif\nSummary:        Pidgin protocol plugin to connect to MS Office Communicator\nVersion:        1.25.0\nRelease:        1\nSource:         pidgin-sipe-%{version}.tar.gz\nGroup:          %{pkg_group}\nLicense:        GPL-2.0-or-later\nURL:            http://sipe.sourceforge.net/\n\nBuildRoot:      %{_tmppath}/%{name}-%{version}-build\n\n%if 0%{?mingw_prefix:1}\n#\n# Windows cross-compilation build setup\n#\nBuildArch:      noarch\n#!BuildIgnore:   post-build-checks\n\nBuildRequires:  libtool\nBuildRequires:  intltool\nBuildRequires:  %{mingw_prefix}filesystem >= 23\nBuildRequires:  %{mingw_prefix}cross-gcc\nBuildRequires:  %{mingw_prefix}cross-binutils\nBuildRequires:  %{mingw_prefix}gettext-runtime\nBuildRequires:  %{mingw_prefix}cross-pkg-config\nBuildRequires:  %{mingw_prefix}glib2-devel >= 2.18.0\nBuildRequires:  %{mingw_prefix}libxml2-devel\nBuildRequires:  %{mingw_prefix}mozilla-nss-devel\nBuildRequires:  %{mingw_prefix}libpurple-devel >= 2.7.0\nBuildRequires:  %{mingw_prefix}cross-nsis\n\n# For directory ownership\nBuildRequires:  %{mingw_prefix}pidgin\n\n# Make sure telepathy is disabled for Windows builds\n%undefine build_telepathy\n\n%else\n#\n# Standard Linux build setup\n#\nBuildRequires:  gcc\nBuildRequires:  libtool\nBuildRequires:  intltool\nBuildRequires:  pkgconfig(dbus-1)\nBuildRequires:  pkgconfig(glib-2.0) >= 2.18.0\nBuildRequires:  pkgconfig(gmodule-2.0) >= 2.18.0\nBuildRequires:  pkgconfig(libxml-2.0)\nBuildRequires:  pkgconfig(nss)\nBuildRequires:  pkgconfig(purple) >= 2.7.0\n%if 0%{?mageia}\n# It seems linking against -lpurple is severely broken on Mageia...\nBuildRequires:  pkgconfig(libgadu)\n%if %{mageia} > 7\n# -lpurple depends on this but doesn't have a dependency in -devel?\nBuildRequires:  pkgconfig(libnm)\n%endif\n%endif\n%if 0%{?has_appstream:1}\n%if 0%{?suse_version}\nBuildRequires:  AppStream\n%else\nBuildRequires:  appstream\n%endif\n%endif\n%if 0%{?has_gstreamer:1}\nBuildRequires:  pkgconfig(farstream-0.2)\nBuildRequires:  pkgconfig(gio-2.0)\nBuildRequires:  pkgconfig(gstreamer-1.0)\nBuildRequires:  pkgconfig(gstreamer-rtp-1.0)\nBuildRequires:  pkgconfig(nice) >= 0.1.0\n# Requirements for appshare server\n%if 0%{?has_freerdp:1}\nBuildRequires:  pkgconfig(freerdp-shadow2)\n%endif\n%endif\n# Requirements for telepathy backend\n%if 0%{?build_telepathy:1}\nBuildRequires:  gmime-devel\nBuildRequires:  pkgconfig(dbus-glib-1)\nBuildRequires:  pkgconfig(gio-2.0) >= 2.32.0\nBuildRequires:  pkgconfig(glib-2.0) >= 2.32.0\nBuildRequires:  pkgconfig(gobject-2.0)\nBuildRequires:  pkgconfig(telepathy-glib) >= 0.24.0\n%endif\n\n# Configurable components\n# Use \"--without kerberos\" to disable krb5\n%if !0%{?_without_kerberos:1}\n%if 0%{?has_krb5devel:1}\nBuildRequires:  krb5-devel\n%else\nBuildRequires:  pkgconfig(krb5)\n%endif\n%if 0%{?has_gssntlmssp:1}\nBuildRequires:  gssntlmssp-devel >= 0.5.0\nRequires:       gssntlmssp >= 0.5.0\n%endif\n%endif\n\n# For directory ownership\nBuildRequires:  pidgin\nRequires:       pidgin\n%if 0%{?build_telepathy:1}\n%if 0%{?build_empathy:1}\nBuildRequires:  empathy\n%endif\n%endif\n\n# End Windows cross-compilation/Linux build setup\n%endif\n\nRequires:       %{purple_plugin} = %{?epoch:%{epoch}:}%{version}-%{release}\n\n\n%description\nA third-party plugin for the Pidgin multi-protocol instant messenger.\nIt implements the extended version of SIP/SIMPLE used by various products:\n\n    * Skype for Business\n    * Microsoft Office 365\n    * Microsoft Business Productivity Online Suite (BPOS)\n    * Microsoft Lync Server\n    * Microsoft Office Communications Server (OCS 2007/2007 R2)\n    * Microsoft Live Communications Server (LCS 2003/2005)\n\nWith this plugin you should be able to replace your Microsoft Office\nCommunicator client with Pidgin.\n\nThis package provides the icon set for Pidgin.\n\n\n%package -n %{purple_plugin}\nSummary:        Libpurple protocol plugin to connect to MS Office Communicator\nGroup:          %{pkg_group}\nLicense:        GPL-2.0-or-later\nObsoletes:      purple-sipe\n%if 0%{?build_telepathy:1}\nRequires:       %{common_files} = %{?epoch:%{epoch}:}%{version}-%{release}\n%endif\n\n%description -n %{purple_plugin}\nA third-party plugin for the Pidgin multi-protocol instant messenger.\nIt implements the extended version of SIP/SIMPLE used by various products:\n\n    * Skype for Business\n    * Microsoft Office 365\n    * Microsoft Business Productivity Online Suite (BPOS)\n    * Microsoft Lync Server\n    * Microsoft Office Communications Server (OCS 2007/2007 R2)\n    * Microsoft Live Communications Server (LCS 2003/2005)\n\nThis package provides the protocol plugin for libpurple clients.\n\n\n%if 0%{?build_telepathy:1}\n%if 0%{?build_empathy:1}\n%package -n %{empathy_files}\nSummary:        Telepathy connection manager to connect to MS Office Communicator\nGroup:          %{pkg_group}\nLicense:        GPL-2.0-or-later\nRequires:       empathy\nRequires:       %{telepathy_plugin} = %{?epoch:%{epoch}:}%{version}-%{release}\n\n%description -n %{empathy_files}\nA Telepathy connection manager that implements the extended version of\nSIP/SIMPLE used by various products:\n\n    * Skype for Business\n    * Microsoft Office 365\n    * Microsoft Business Productivity Online Suite (BPOS)\n    * Microsoft Lync Server\n    * Microsoft Office Communications Server (OCS 2007/2007 R2)\n    * Microsoft Live Communications Server (LCS 2003/2005)\n\nThis package provides the icon set for Empathy.\n%endif\n\n\n%if 0%{?build_ktp:1}\n%package -n %{ktp_files}\nSummary:        Telepathy connection manager to connect to MS Office Communicator\nGroup:          %{pkg_group}\nLicense:        GPL-2.0-or-later\nRequires:       %{telepathy_plugin} = %{?epoch:%{epoch}:}%{version}-%{release}\n\n%description -n %{ktp_files}\nA Telepathy connection manager that implements the extended version of\nSIP/SIMPLE used by various products:\n\n    * Skype for Business\n    * Microsoft Office 365\n    * Microsoft Business Productivity Online Suite (BPOS)\n    * Microsoft Lync Server\n    * Microsoft Office Communications Server (OCS 2007/2007 R2)\n    * Microsoft Live Communications Server (LCS 2003/2005)\n\nThis package provides the profile for KTP account manager.\n%endif\n\n\n%package -n %{telepathy_plugin}\nSummary:        Telepathy connection manager to connect to MS Office Communicator\nGroup:          %{pkg_group}\nLicense:        GPL-2.0-or-later\nRequires:       %{common_files} = %{?epoch:%{epoch}:}%{version}-%{release}\n\n%description -n %{telepathy_plugin}\nA Telepathy connection manager that implements the extended version of\nSIP/SIMPLE used by various products:\n\n    * Skype for Business\n    * Microsoft Office 365\n    * Microsoft Business Productivity Online Suite (BPOS)\n    * Microsoft Lync Server\n    * Microsoft Office Communications Server (OCS 2007/2007 R2)\n    * Microsoft Live Communications Server (LCS 2003/2005)\n\nThis package provides the protocol support for Telepathy clients.\n\n\n%package -n %{common_files}\nSummary:        Common files for SIPE protocol plugins\nGroup:          %{pkg_group}\nLicense:        GPL-2.0-or-later\nBuildArch:      noarch\n\n%description -n %{common_files}\nThis package provides common files for the SIPE protocol plugins:\n\n    * Localisation\n%endif\n\n\n%if 0%{?mingw_prefix:1}\n%package -n %{nsis_package}\nSummary:        Windows Pidgin protocol plugin to connect to MS Office Communicator\nGroup:          %{pkg_group}\nLicense:        GPL-2.0-or-later\n\n%description -n %{nsis_package}\nA third-party plugin for the Pidgin multi-protocol instant messenger.\nIt implements the extended version of SIP/SIMPLE used by various products:\n\n    * Skype for Business\n    * Microsoft Office 365\n    * Microsoft Business Productivity Online Suite (BPOS)\n    * Microsoft Lync Server\n    * Microsoft Office Communications Server (OCS 2007/2007 R2)\n    * Microsoft Live Communications Server (LCS 2003/2005)\n\nThis package contains the NSIS installer package of the protocol plugin\nfor Pidgin on Windows.\n%endif\n\n\n%{mingw_debug_package}\n\n\n%prep\n%setup -q -n pidgin-sipe-%{version}\n\n%build\n%if 0%{?mingw_prefix:1}\n#\n# Windows cross-compilation build\n#\n%{?env_options}\necho \"lt_cv_deplibs_check_method='pass_all'\" >>%{mingw_cache}\nautoreconf --verbose --install --force\n%{mingw_ldflags}=\"-Wl,--exclude-libs=libintl.a -Wl,--exclude-libs=libiconv.a -lws2_32\"\n%{mingw_configure} \\\n    --enable-purple \\\n%if 0%{?build_telepathy:1}\n    --enable-telepathy\n%else\n    --disable-telepathy\n%endif\n%{mingw_make} %{?_smp_mflags} || %{mingw_make}\n\n%else\n#\n# Standard Linux build\n#\n# Special case handling for Mageia\n%if 0%{?mageia}\n%configure2_5x \\\n    --with-krb5 \\\n    --with-vv \\\n    --disable-telepathy\n%make_build\n%make_build check\n\n# All other Linuxes\n%else\n%configure \\\n%if !0%{?has_appstream:1}\n    --without-appstream \\\n%endif\n%if !0%{?_without_kerberos:1}\n    --with-krb5 \\\n%endif\n%if 0%{?has_gstreamer:1}\n    --with-vv \\\n%endif\n    --enable-purple \\\n%if 0%{?build_telepathy:1}\n    --enable-telepathy\n%else\n    --disable-telepathy\n%endif\nmake %{?_smp_mflags}\nmake %{?_smp_mflags} check\n%endif\n\n# End Windows cross-compilation/Linux build setup\n%endif\n\n\n%install\n%if 0%{?mingw_prefix:1}\n#\n# Windows cross-compilation install\n#\n%{mingw_makeinstall}\nrm -f %{buildroot}%{mingw_libdir}/purple-2/*.dll.a\n\n# generate .dbgsym file\nrm -f %{buildroot}%{mingw_libdir}/purple-2/libsipe.dll.dbgsym\nmv \\\n    %{buildroot}%{mingw_libdir}/purple-2/libsipe.dll \\\n    %{buildroot}%{mingw_libdir}/purple-2/libsipe.dll.dbgsym\n%{__strip} --strip-unneeded \\\n    %{buildroot}%{mingw_libdir}/purple-2/libsipe.dll.dbgsym \\\n    -o %{buildroot}%{mingw_libdir}/purple-2/libsipe.dll \\\n\n# generate NSIS installer package\nperl contrib/opensuse-build-service/generate_nsi.pl po/LINGUAS \\\n    <contrib/opensuse-build-service/pidgin-sipe.nsi.template \\\n    >%{buildroot}/pidgin-sipe.nsi\n( \\\n    set -e; \\\n    cd %{buildroot}; \\\n    makensis \\\n        -DPIDGIN_VERSION=UNKNOWN \\\n        -DVERSION=%{version} \\\n        -DMINGW_LIBDIR=%{buildroot}%{mingw_libdir} \\\n        -DMINGW_DATADIR=%{buildroot}%{mingw_datadir} \\\n        pidgin-sipe.nsi \\\n)\nrm -f %{buildroot}/pidgin-sipe.nsi\n\n%else\n#\n# Standard Linux install\n#\n%make_install\n\n# End Windows cross-compilation/Linux build setup\n%endif\n\nfind %{buildroot} -type f -name \"*.la\" -delete -print\n# Pidgin doesn't have 24 or 32 pixel icons\nrm -f \\\n   %{buildroot}%{_datadir}/pixmaps/pidgin/protocols/24/sipe.png \\\n   %{buildroot}%{_datadir}/pixmaps/pidgin/protocols/32/sipe.png\n%if 0%{?has_appstream_legacy:1}\nmv %{buildroot}/%{_datadir}/metainfo %{buildroot}/%{_datadir}/appdata\n%endif\n%if 0%{?build_telepathy:1}\n%if !0%{?build_empathy:1}\nrm -r %{buildroot}%{_datadir}/empathy\n%endif\n%if !0%{?build_ktp:1}\nrm -r %{buildroot}%{_datadir}/telepathy\n%endif\n%endif\n%find_lang pidgin-sipe\n\n\n%if 0%{?build_telepathy:1}\n%files -n %{purple_plugin}\n%else\n%files -n %{purple_plugin} -f pidgin-sipe.lang\n%endif\n%defattr(-,root,root,-)\n%doc AUTHORS ChangeLog COPYING NEWS README TODO\n%if 0%{?mingw_prefix:1}\n%{mingw_libdir}/purple-2/libsipe.dll\n%{mingw_libdir}/purple-2/libsipe.dll.dbgsym\n%else\n%{_libdir}/purple-2/libsipe.so\n%endif\n\n\n%if 0%{?build_telepathy:1}\n%if 0%{?build_empathy:1}\n%files -n %{empathy_files}\n%defattr(-,root,root,-)\n%{_datadir}/empathy/icons/hicolor/*/apps/im-sipe.png\n%{_datadir}/empathy/icons/hicolor/*/apps/im-sipe.svg\n%endif\n\n\n%if 0%{?build_ktp:1}\n%files -n %{ktp_files}\n%defattr(-,root,root,-)\n%doc AUTHORS COPYING\n%{_datadir}/telepathy/profiles/sipe.profile\n%endif\n\n\n%files -n %{telepathy_plugin}\n%defattr(-,root,root,-)\n%doc AUTHORS ChangeLog COPYING NEWS README TODO\n%{_datadir}/dbus-1/services/*.sipe.service\n%{_libexecdir}/telepathy-sipe\n\n\n%files -n %{common_files} -f pidgin-sipe.lang\n%defattr(-,root,root,-)\n%endif\n\n\n%files\n%defattr(-,root,root,-)\n%doc AUTHORS COPYING\n%if 0%{?mingw_prefix:1}\n%if 0%{?has_appstream:1}\n%{mingw_datadir}/metainfo/pidgin-sipe.metainfo.xml\n%endif\n%{mingw_datadir}/pixmaps/pidgin/protocols/*/sipe.png\n%{mingw_datadir}/pixmaps/pidgin/protocols/*/sipe.svg\n%else\n%if 0%{?has_appstream:1}\n%if 0%{?has_appstream_legacy:1}\n%{_datadir}/appdata/%{name}.metainfo.xml\n%else\n%{_datadir}/metainfo/%{name}.metainfo.xml\n%endif\n%endif\n%{_datadir}/pixmaps/pidgin/protocols/*/sipe.png\n%{_datadir}/pixmaps/pidgin/protocols/*/sipe.svg\n%endif\n\n\n%if 0%{?mingw_prefix:1}\n%files -n %{nsis_package}\n%defattr(-, root, root)\n/pidgin-sipe-%{version}.exe\n%endif\n\n\n%changelog\n* Tue Oct 15 2019 J. D. User <jduser@noreply.com> 1.25.0-*git*\n- make sure V&V features are really enabled when requested\n\n* Sat Oct 12 2019 J. D. User <jduser@noreply.com> 1.25.0\n- update to 1.25.0\n\n* Fri Oct 04 2019 J. D. User <jduser@noreply.com> 1.24.0-*git*\n- add BR libnm for Mageia 8+\n\n* Tue Jul 02 2019 J. D. User <jduser@noreply.com> 1.24.0-*git*\n- add freerdp & gssntlmssp for Mageia 7+\n\n* Sun Jun 30 2019 J. D. User <jduser@noreply.com> 1.24.0-*git*\n- switch to SPDX identifier GPL-2.0-or-later\n\n* Sun Jun 30 2019 J. D. User <jduser@noreply.com> 1.24.0-*git*\n- newer distros no longer package empathy\n\n* Sun Jun 30 2019 J. D. User <jduser@noreply.com> 1.24.0-*git*\n- raise BR telepathy-glib >= 0.24.0\n\n* Sat Nov 10 2018 J. D. User <jduser@noreply.com> 1.24.0\n- update to 1.24.0\n\n* Sat Sep 01 2018 J. D. User <jduser@noreply.com> 1.23.3-*git*\n- update support for CentOS & Scientific Linux 7\n\n* Mon Aug 27 2018 J. D. User <jduser@noreply.com> 1.23.3-*git*\n- add BR freerdp-shadow2\n\n* Mon Aug 20 2018 J. D. User <jduser@noreply.com> 1.23.3\n- update to 1.23.3\n\n* Sat Mar 10 2018 J. D. User <jduser@noreply.com> 1.23.2\n- update to 1.23.2\n\n* Sun Feb 25 2018 J. D. User <jduser@noreply.com> 1.23.1\n- update to 1.23.1\n\n* Sun Feb 18 2018 J. D. User <jduser@noreply.com> 1.23.0-*git*\n- remove obsolete clean section\n\n* Sun Feb 18 2018 J. D. User <jduser@noreply.com> 1.23.0-*git*\n- add BR gcc\n\n* Mon Nov 06 2017 J. D. User <jduser@noreply.com> 1.23.0-*git*\n- add BR appstream\n\n* Sun Nov 05 2017 J. D. User <jduser@noreply.com> 1.23.0-*git*\n- add support for new AppStream metadata file location\n\n* Sat Oct 28 2017 J. D. User <jduser@noreply.com> 1.23.0\n- update to 1.23.0\n- raise BR glib-2.0 >= 2.18.0\n- raise BR purple >= 2.7.0\n\n* Fri Aug 11 2017 J. D. User <jduser@noreply.com> 1.22.1-*git*\n- add BR dbus-1\n- fix incorrect BR gstreamer-0.10 when gstreamer-1.0 is selected\n\n* Sun Jun 11 2017 J. D. User <jduser@noreply.com> 1.22.1\n- update to 1.22.1\n\n* Wed Feb 01 2017 J. D. User <jduser@noreply.com> 1.22.0\n- update to 1.22.0\n\n* Sun Dec 18 2016 J. D. User <jduser@noreply.com> 1.21.1-*git*\n- add BR gio-2.0\n\n* Wed Jun 15 2016 J. D. User <jduser@noreply.com> 1.21.1-*git*\n- add BR farstream-0.2\n\n* Sat May 28 2016 J. D. User <jduser@noreply.com> 1.21.1\n- update to 1.21.1\n\n* Sat Apr 23 2016 J. D. User <jduser@noreply.com> 1.21.0\n- update to 1.21.0\n\n* Tue Apr 05 2016 J. D. User <jduser@noreply.com> 1.20.1-*git*\n- align with Fedora SPEC file\n\n* Fri Jan 01 2016 J. D. User <jduser@noreply.com> 1.20.1-*git*\n- add AppStream metadata file\n\n* Sun Nov 08 2015 J. D. User <jduser@noreply.com> 1.20.1-*git*\n- add dependency on pkgconfig(gstreamer-1.0) for F22+ & Leap 42.1+\n\n* Sat Oct 24 2015 J. D. User <jduser@noreply.com> 1.20.1\n- update to 1.20.1\n\n* Thu Sep 03 2015 J. D. User <jduser@noreply.com> 1.20.0-*git*\n- we also support \"Skype for Business\"\n\n* Sat Aug 29 2015 J. D. User <jduser@noreply.com> 1.20.0\n- update to 1.20.0\n\n* Sat Apr 04 2015 J. D. User <jduser@noreply.com> 1.19.1\n- update to 1.19.1\n\n* Sat Feb 07 2015 J. D. User <jduser@noreply.com> 1.19.0\n- update to 1.19.0\n\n* Tue Jan 06 2015 J. D. User <jduser@noreply.com> 1.18.5-*git*\n- add dependency on gssntlmssp(-devel) >= 0.5.0 for F21+\n\n* Mon Jan 05 2015 J. D. User <jduser@noreply.com> 1.18.5-*git*\n- remove support for obsolete distributions\n    - Fedora < 19\n    - Mandriva\n    - OpenSUSE < 13.x\n\n* Mon Dec 29 2014 J. D. User <jduser@noreply.com> 1.18.5\n- update to 1.18.5\n\n* Thu Dec 18 2014 J. D. User <jduser@noreply.com> 1.18.4-*git*\n- improve support for CentOS & Scientific Linux\n\n* Sat Oct 18 2014 J. D. User <jduser@noreply.com> 1.18.4\n- update to 1.18.4\n\n* Sat Aug 16 2014 J. D. User <jduser@noreply.com> 1.18.3\n- update to 1.18.3\n\n* Sat Jun 07 2014 J. D. User <jduser@noreply.com> 1.18.2\n- update to 1.18.2\n\n* Sat Apr 12 2014 J. D. User <jduser@noreply.com> 1.18.1\n- update to 1.18.1\n\n* Tue Mar 04 2014 J. D. User <jduser@noreply.com> 1.18.0-*git*\n- F20+/openSUSE 12.2+ require libnice gstreamer-0.10 plugin\n\n* Sat Jan 11 2014 J. D. User <jduser@noreply.com> 1.18.0\n- update to 1.18.0\n\n* Wed Dec 11 2013 J. D. User <jduser@noreply.com> 1.17.3\n- update to 1.17.3\n\n* Sat Nov 30 2013 J. D. User <jduser@noreply.com> 1.17.2\n- update to 1.17.2\n\n* Sat Nov 16 2013 J. D. User <jduser@noreply.com> 1.17.1\n- update to 1.17.1\n\n* Sat Sep 21 2013 J. D. User <jduser@noreply.com> 1.17.0\n- update to 1.17.0\n\n* Sat Jul 13 2013 J. D. User <jduser@noreply.com> 1.16.1\n- update to 1.16.1\n\n* Fri Jun 14 2013 J. D. User <jduser@noreply.com> 1.16.0\n- update to 1.16.0\n\n* Sun Apr 07 2013 J. D. User <jduser@noreply.com> 1.15.1\n- update to 1.15.1\n\n* Fri Mar 29 2013 J. D. User <jduser@noreply.com> 1.15.0-*git*\n- update package description texts\n\n* Sat Mar 09 2013 J. D. User <jduser@noreply.com> 1.15.0\n- update to 1.15.0\n\n* Wed Dec 26 2012 J. D. User <jduser@noreply.com> 1.14.1\n- update to 1.14.1\n\n* Sun Dec 16 2012 J. D. User <jduser@noreply.com> 1.14.0\n- update to 1.14.0\n\n* Tue Sep 25 2012 J. D. User <jduser@noreply.com> 1.13.3-*git*\n- change BR gstreamer-devel to pkgconfig(gstreamer-0.10)\n\n* Sun Sep 09 2012 J. D. User <jduser@noreply.com> 1.13.3-*git*\n- BR telepathy-glib-devel >= 0.18.0\n\n* Wed Sep 05 2012 J. D. User <jduser@noreply.com> 1.13.3-*git*\n- BR telepathy-glib-devel >= 0.14.0\n\n* Sun Sep 02 2012 J. D. User <jduser@noreply.com> 1.13.3-*git*\n- really disable telepathy for Windows cross-compilation builds\n\n* Thu Aug 30 2012 J. D. User <jduser@noreply.com> 1.13.3-*git*\n- updates to enable telepathy build\n\n* Sun Aug 19 2012 J. D. User <jduser@noreply.com> 1.13.3\n- update to 1.13.3\n\n* Sun Jun 10 2012 J. D. User <jduser@noreply.com> 1.13.2\n- update to 1.13.2\n\n* Mon Apr 09 2012 J. D. User <jduser@noreply.com> 1.13.1\n- update to 1.13.1\n\n* Wed Mar 14 2012 J. D. User <jduser@noreply.com> 1.13.0\n- update to 1.13.0\n\n* Mon Dec 12 2011 J. D. User <jduser@noreply.com> 1.12.0-*git*\n- we do support Microsoft Lync Server 2010 now.\n\n* Tue Dec 06 2011 J. D. User <jduser@noreply.com> 1.12.0-*git*\n- update GPL2 license name\n\n* Sat Nov 12 2011 J. D. User <jduser@noreply.com> 1.12.0-*git*\n- add BR gmime-devel for Fedora to have at least one verification platform\n\n* Sun Nov 06 2011 J. D. User <jduser@noreply.com> 1.12.0-*git*\n- fix Mandriva 2011 unresolvable BR\n\n* Mon Oct 31 2011 J. D. User <jduser@noreply.com> 1.12.0-*git*\n- add BR nss-devel\n\n* Sat Oct 01 2011 J. D. User <jduser@noreply.com> 1.12.0-*git*\n- add NSIS package for mingw builds\n\n* Sat Oct 01 2011 J. D. User <jduser@noreply.com> 1.12.0-*git*\n- add mingw64 build\n\n* Wed Sep 28 2011 J. D. User <jduser@noreply.com> 1.12.0-*git*\n- remove BR mingw32-mozilla-nss-devel, not needed for SSPI.\n\n* Mon Sep 19 2011 J. D. User <jduser@noreply.com> 1.12.0-*git*\n- update mingw32 build\n- update descriptions\n\n* Mon Aug 29 2011 J. D. User <jduser@noreply.com> 1.12.0\n- update to 1.12.0\n\n* Wed Jun 22 2011 J. D. User <jduser@noreply.com> 1.11.2-*git*\n- add gstreamer-devel to enable Voice & Video features\n\n* Sat Dec 11 2010 J. D. User <jduser@noreply.com> 1.11.2-*git*\n- add optional subpackage for telepathy connection manager\n\n* Tue Nov 02 2010 J. D. User <jduser@noreply.com> 1.11.2\n- update to 1.11.2\n\n* Sun Oct 24 2010 J. D. User <jduser@noreply.com> 1.11.1\n- update to 1.11.1\n\n* Fri Oct 15 2010 J. D. User <jduser@noreply.com> 1.11.0-*git*\n- add mingw32 build configuration\n\n* Sun Oct 03 2010 J. D. User <jduser@noreply.com> 1.11.0\n- update to 1.11.0\n\n* Thu Sep 02 2010 J. D. User <jduser@noreply.com> pre-1.11.0-*git*\n- Mandriva config for OBS has changed\n\n* Tue May 04 2010 J. D. User <jduser@noreply.com> 1.10.0-*git*\n- add libnice build information discovered through OBS testing\n\n* Mon Apr 12 2010 J. D. User <jduser@noreply.com> 1.10.0-*git*\n- add NSS build information discovered through OBS testing\n\n* Sun Apr 04 2010 pier11 <pier11@operamail.com> 1.10.0\n- release\n\n* Fri Apr 02 2010 J. D. User <jduser@noreply.com> pre-1.10.0-*git*\n- Mandriva has too old libtool version\n\n* Fri Apr 02 2010 J. D. User <jduser@noreply.com> pre-1.10.0-*git*\n- SLE11, openSUSE 11.0/1 don't have pidgin/protocols/scalable directory\n\n* Thu Apr 01 2010 pier11 <pier11@operamail.com> pre-1.10.0-*git*\n- OBS tests of pre-1.10.0 git-snapshot 4fa20cd65e5be0e469d4aa55d861f11c5b08b816\n\n* Sun Mar 28 2010 J. D. User <jduser@noreply.com> 1.9.1-*git*\n- added --enable/--disable build options\n\n* Sun Mar 28 2010 J. D. User <jduser@noreply.com> 1.9.1-*git*\n- removed --with-krb5 configure option as it is autodetected now\n\n* Tue Mar 23 2010 J. D. User <jduser@noreply.com> 1.9.1-*git*\n- add SVG icon\n\n* Sat Mar 20 2010 J. D. User <jduser@noreply.com> 1.9.1-*git*\n- add BR glib2-devel >= 2.12.0\n\n* Wed Mar 17 2010 J. D. User <jduser@noreply.com> 1.9.1-*git*\n- add tests to build\n\n* Tue Mar 16 2010 J. D. User <jduser@noreply.com> 1.9.1\n- update to 1.9.1\n\n* Thu Mar 11 2010 J. D. User <jduser@noreply.com> 1.9.0-*git*\n- add BR libxml2-devel\n\n* Wed Mar 10 2010 pier11 <pier11@operamail.com> 1.9.0\n- release\n- dropped SLE 10 due to libpurple min version increase\n- updated target distros in comment line\n\n* Mon Mar 08 2010 J. D. User <jduser@noreply.com> 1.9.0-*git*\n- increased libpurple build requisite to >= 2.4.0\n\n* Sun Mar 07 2010 pier11 <pier11@operamail.com> pre-1.9.0-*git*\n- OBS tests of pre-1.9.0 git-snapshot 61ea0856855483b9e18f23a87afe47437e526f0e\n\n* Sun Mar 07 2010 J. D. User <jduser@noreply.com> 1.8.1-*git*\n- sync with RPM SPEC from contrib/rpm\n\n* Mon Feb 08 2010 pier11 <pier11@operamail.com> 1.8.0\n- source is an original 1.8.0 with patch: git(upstream) 9c34cc3557daa3d61a002002492c71d0343c8cae\n- temp hack - renamed source in spec from .bz2 to .gz as the latter was prepared with the patch. \n\n* Sun Nov 22 2009 pier11 <pier11@operamail.com> 1.7.1\n- reinstated enable-quality-check\n\n* Wed Nov 04 2009 John Beranek <john@redux.org.uk> 1.7.0\n- Spec file modifications to allow SLES/D 10 and Mandriva 2009.1 builds\n\n* Tue Nov 03 2009 John Beranek <john@redux.org.uk> 1.7.0\n- Spec file modifications for openSUSE build service\n\n* Sun Oct 11 2009 J. D. User <jduser@noreply.com> 1.6.3-*git*\n- move non-Pidgin files to new sub-package purple-sipe\n\n* Sun Oct 11 2009 J. D. User <jduser@noreply.com> 1.6.3-*git*\n- remove directory for emoticon theme icons\n\n* Sun Oct 11 2009 J. D. User <jduser@noreply.com> 1.6.3-*git*\n- libpurple protocol plugins are located under %%{_libdir}/purple-2\n\n* Mon Sep 28 2009 J. D. User <jduser@noreply.com> 1.6.3-*git*\n- added directory for emoticon theme icons\n\n* Wed Sep 09 2009 J. D. User <jduser@noreply.com> 1.6.3\n- update to 1.6.3\n\n* Fri Aug 28 2009 J. D. User <jduser@noreply.com> 1.6.2-*git*\n- reduce libpurple-devel requirement to >= 2.3.1\n\n* Mon Aug 24 2009 J. D. User <jduser@noreply.com> 1.6.2\n- update to 1.6.2\n\n* Fri Aug 21 2009 J. D. User <jduser@noreply.com> 1.6.1-*git*\n- reduce libpurple-devel requirement to >= 2.4.1\n\n* Mon Aug 17 2009 J. D. User <jduser@noreply.com> 1.6.1-*git*\n- com_err.h only required for kerberos\n\n* Tue Aug 11 2009 J. D. User <jduser@noreply.com> 1.6.0-*git*\n- require libpurple-devel >= 2.5.0\n\n* Sun Aug 09 2009 J. D. User <jduser@noreply.com> 1.6.0-*git*\n- refactor configure parameters\n- make kerberos configurable\n- don't hard code prefix for git builds\n\n* Sun Aug 09 2009 J. D. User <jduser@noreply.com> 1.6.0-*git*\n- removed unnecessary zlib-devel\n\n* Sat Aug 08 2009 J. D. User <jduser@noreply.com> 1.6.0-*git*\n- fix prefix for git builds\n\n* Sat Aug 01 2009 J. D. User <jduser@noreply.com> 1.6.0-*git*\n- append -Wno-unused-parameter for GCC <4.4 compilation errors\n\n* Thu Jul 30 2009 J. D. User <jduser@noreply.com> 1.6.0-*git*\n- remove duplicate GPL2\n\n* Thu Jul 30 2009 J. D. User <jduser@noreply.com> 1.6.0-*git*\n- use \"--with git\" to build from git\n- corrected download URL for release archive\n- add missing BR gettext-devel\n\n* Wed Jul 29 2009 J. D. User <jduser@noreply.com> 1.6.0-*git*\n- use default rpmbuild CFLAGS also for git builds\n- merge with SPEC files created by mricon & jberanek\n\n* Tue Jul 28 2009 J. D. User <jduser@noreply.com> 1.6.0-*git*\n- initial RPM SPEC example generated\n"
  },
  {
    "path": "contrib/rpm/pidgin-sipe.spec",
    "content": "#\n# Example SPEC file to generate a RPM for pidgin-sipe.\n# It should work out-of-the-box for any current Fedora or RHEL release.\n#\n%if 0%{?_with_git:1}\n#------------------------------- BUILD FROM GIT -------------------------------\n# Add \"--with git\" to the rpmbuild command line to build from git\n#\n# Instructions how to access the repository: http://sipe.sourceforge.net/git/\n#\n# Run \"./git-snapshot.sh .\" in your local repository.\n# Then update the following line from the generated archive name\n%define git       20180827git1297745c\n# Increment when you generate several RPMs on the same day...\n%define gitcount  0\n#------------------------------- BUILD FROM GIT -------------------------------\n%endif\n\n%define purple_plugin    purple-sipe\n%define telepathy_plugin telepathy-sipe\n%define common_files     sipe-common\n%define empathy_files    empathy-sipe\n%define ktp_files        ktp-accounts-kcm-sipe\n%define pkg_group        Applications/Communications\n\nName:           pidgin-sipe\nSummary:        Pidgin protocol plugin to connect to MS Office Communicator\nVersion:        1.25.0\n%if 0%{?_with_git:1}\nRelease:        %{gitcount}.%{git}%{?dist}\nSource0:        %{name}-%{git}.tar.bz2\n# git package overrides official released package\nEpoch:          1\n%else\nRelease:        1%{?dist}\nSource0:        https://downloads.sourceforge.net/project/sipe/sipe/%{name}-%{version}/%{name}-%{version}.tar.bz2\n%endif\nGroup:          %{pkg_group}\nLicense:        GPL-2.0-or-later\nURL:            http://sipe.sourceforge.net/\n\nBuildRequires:  pkgconfig(dbus-1)\nBuildRequires:  pkgconfig(glib-2.0) >= 2.18.0\nBuildRequires:  pkgconfig(gmodule-2.0) >= 2.18.0\nBuildRequires:  pkgconfig(libxml-2.0)\nBuildRequires:  pkgconfig(nss)\nBuildRequires:  pkgconfig(purple) >= 2.7.0\n%if 0%{?_with_git:1}\nBuildRequires:  autoconf\nBuildRequires:  automake\nBuildRequires:  flex\n%endif\nBuildRequires:  appstream\nBuildRequires:  gcc\nBuildRequires:  gettext\nBuildRequires:  intltool\nBuildRequires:  libtool\n# Use \"--without vv\" to disable Voice & Video features\n%if !0%{?_without_vv:1}\nBuildRequires:  pkgconfig(purple) >= 2.8.0\nBuildRequires:  pkgconfig(farstream-0.2)\nBuildRequires:  pkgconfig(freerdp-shadow2)\nBuildRequires:  pkgconfig(gio-2.0)\nBuildRequires:  pkgconfig(gstreamer-1.0)\nBuildRequires:  pkgconfig(gstreamer-rtp-1.0)\nBuildRequires:  pkgconfig(nice) >= 0.1.0\n%endif\n# Use \"--without telepathy\" to disable telepathy\n%if !0%{?_without_telepathy:1}\nBuildRequires:  gmime-devel\nBuildRequires:  pkgconfig(dbus-glib-1)\nBuildRequires:  pkgconfig(gio-2.0) >= 2.32.0\nBuildRequires:  pkgconfig(glib-2.0) >= 2.32.0\nBuildRequires:  pkgconfig(gobject-2.0)\nBuildRequires:  pkgconfig(telepathy-glib) >= 0.24.0\n%endif\n\n# Configurable components\n# Use \"--without kerberos\" to disable krb5\n%if !0%{?_without_kerberos:1}\nBuildRequires:  pkgconfig(krb5)\n%if 0%{?fedora} || 0%{?rhel} >= 7\nBuildRequires:  gssntlmssp-devel >= 0.5.0\n%define         requires_gssntlmssp 1\n%endif\n%endif\n\nRequires:       %{purple_plugin} = %{?epoch:%{epoch}:}%{version}-%{release}\n\n\n%description\nA third-party plugin for the Pidgin multi-protocol instant messenger.\nIt implements the extended version of SIP/SIMPLE used by various products:\n\n    * Skype for Business\n    * Microsoft Office 365\n    * Microsoft Business Productivity Online Suite (BPOS)\n    * Microsoft Lync Server\n    * Microsoft Office Communications Server (OCS 2007/2007 R2)\n    * Microsoft Live Communications Server (LCS 2003/2005)\n\nWith this plugin you should be able to replace your Microsoft Office\nCommunicator client with Pidgin.\n\nThis package provides the icon set for Pidgin.\n\n\n%package -n %{purple_plugin}\nSummary:        Libpurple protocol plugin to connect to MS Office Communicator\nGroup:          %{pkg_group}\nLicense:        GPL-2.0-or-later\nRequires:       %{common_files} = %{?epoch:%{epoch}:}%{version}-%{release}\n\n%if 0%{?requires_gssntlmssp}\nRequires:       gssntlmssp >= 0.5.0\n%endif\n\n%description -n %{purple_plugin}\nA third-party plugin for the Pidgin multi-protocol instant messenger.\nIt implements the extended version of SIP/SIMPLE used by various products:\n\n    * Skype for Business\n    * Microsoft Office 365\n    * Microsoft Business Productivity Online Suite (BPOS)\n    * Microsoft Lync Server\n    * Microsoft Office Communications Server (OCS 2007/2007 R2)\n    * Microsoft Live Communications Server (LCS 2003/2005)\n\nThis package provides the protocol plugin for libpurple clients.\n\n\n%if !0%{?_without_telepathy:1}\n%package -n %{empathy_files}\nSummary:        Telepathy connection manager to connect to MS Office Communicator\nGroup:          %{pkg_group}\nLicense:        GPL-2.0-or-later\nRequires:       %{telepathy_plugin} = %{?epoch:%{epoch}:}%{version}-%{release}\n\n%description -n %{empathy_files}\nA Telepathy connection manager that implements the extended version of\nSIP/SIMPLE used by various products:\n\n    * Skype for Business\n    * Microsoft Office 365\n    * Microsoft Business Productivity Online Suite (BPOS)\n    * Microsoft Lync Server\n    * Microsoft Office Communications Server (OCS 2007/2007 R2)\n    * Microsoft Live Communications Server (LCS 2003/2005)\n\nThis package provides the icon set for Empathy.\n\n\n%package -n %{ktp_files}\nSummary:        Telepathy connection manager to connect to MS Office Communicator\nGroup:          %{pkg_group}\nLicense:        GPL-2.0-or-later\nRequires:       %{telepathy_plugin} = %{?epoch:%{epoch}:}%{version}-%{release}\n\n%description -n %{ktp_files}\nA Telepathy connection manager that implements the extended version of\nSIP/SIMPLE used by various products:\n\n    * Skype for Business\n    * Microsoft Office 365\n    * Microsoft Business Productivity Online Suite (BPOS)\n    * Microsoft Lync Server\n    * Microsoft Office Communications Server (OCS 2007/2007 R2)\n    * Microsoft Live Communications Server (LCS 2003/2005)\n\nThis package provides the profile for KTP account manager.\n\n\n%package -n %{telepathy_plugin}\nSummary:        Telepathy connection manager to connect to MS Office Communicator\nGroup:          %{pkg_group}\nLicense:        GPL-2.0-or-later\nRequires:       %{common_files} = %{?epoch:%{epoch}:}%{version}-%{release}\n\n%if 0%{?requires_gssntlmssp}\nRequires:       gssntlmssp >= 0.5.0\n%endif\n\n%description -n %{telepathy_plugin}\nA Telepathy connection manager that implements the extended version of\nSIP/SIMPLE used by various products:\n\n    * Skype for Business\n    * Microsoft Office 365\n    * Microsoft Business Productivity Online Suite (BPOS)\n    * Microsoft Lync Server\n    * Microsoft Office Communications Server (OCS 2007/2007 R2)\n    * Microsoft Live Communications Server (LCS 2003/2005)\n\nThis package provides the protocol support for Telepathy clients.\n%endif\n\n\n%package -n %{common_files}\nSummary:        Common files for SIPE protocol plugins\nGroup:          %{pkg_group}\nLicense:        GPL-2.0-or-later\nBuildArch:      noarch\n\n%description -n %{common_files}\nThis package provides common files for the SIPE protocol plugins:\n\n    * Localisation\n\n\n%prep\n%if 0%{?_with_git:1}\n%setup -q -n %{name}-%{git}\n%else\n%setup -q\n%endif\n\n\n%build\n%if 0%{?_with_git:1}\n./autogen.sh\n%endif\n%configure \\\n%if 0%{?_without_vv:1}\n    --without-vv \\\n%else\n    --with-vv \\\n%endif\n%if !0%{?_without_kerberos:1}\n    --with-krb5 \\\n%endif\n    --enable-purple \\\n%if !0%{?_without_telepathy:1}\n    --enable-telepathy\n%else\n    --disable-telepathy\n%endif\nmake %{?_smp_mflags}\n\n\n%install\n%make_install\nfind %{buildroot} -type f -name \"*.la\" -delete -print\n# Pidgin doesn't have 24 or 32 pixel icons\nrm -f \\\n   %{buildroot}%{_datadir}/pixmaps/pidgin/protocols/24/sipe.png \\\n   %{buildroot}%{_datadir}/pixmaps/pidgin/protocols/32/sipe.png\n%find_lang %{name}\n\n\n%check\nmake %{?_smp_mflags} check\n\n\n%files -n %{purple_plugin}\n%defattr(-,root,root,-)\n%doc AUTHORS ChangeLog COPYING NEWS README TODO\n%{_libdir}/purple-2/libsipe.so\n\n\n%if !0%{?_without_telepathy:1}\n%files -n %{empathy_files}\n%defattr(-,root,root,-)\n%{_datadir}/empathy/icons/hicolor/*/apps/im-sipe.png\n%{_datadir}/empathy/icons/hicolor/*/apps/im-sipe.svg\n\n\n%files -n %{ktp_files}\n%defattr(-,root,root,-)\n%doc AUTHORS COPYING\n%{_datadir}/telepathy/profiles/sipe.profile\n\n\n%files -n %{telepathy_plugin}\n%defattr(-,root,root,-)\n%doc AUTHORS ChangeLog COPYING NEWS README TODO\n%{_datadir}/dbus-1/services/*.sipe.service\n%{_libexecdir}/telepathy-sipe\n%endif\n\n\n%files -n %{common_files} -f %{name}.lang\n%defattr(-,root,root,-)\n\n\n%files\n%defattr(-,root,root,-)\n%{_datadir}/metainfo/%{name}.metainfo.xml\n%{_datadir}/pixmaps/pidgin/protocols/*/sipe.png\n%{_datadir}/pixmaps/pidgin/protocols/*/sipe.svg\n\n\n%changelog\n* Tue Oct 15 2019 J. D. User <jduser@noreply.com> 1.25.0-*git*\n- make sure V&V features are really enabled when requested\n\n* Sat Oct 12 2019 J. D. User <jduser@noreply.com> 1.25.0\n- update to 1.25.0\n\n* Sun Jun 30 2019 J. D. User <jduser@noreply.com> 1.24.0-*git*\n- switch to SPDX identifier GPL-2.0-or-later\n\n* Sun Jun 30 2019 J. D. User <jduser@noreply.com> 1.24.0-*git*\n- raise BR telepathy-glib >= 0.24.0\n\n* Fri Dec 28 2018 J. D. User <jduser@noreply.com> 1.24.0-*git*\n- add BR flex for git builds\n\n* Sat Nov 10 2018 J. D. User <jduser@noreply.com> 1.24.0\n- update to 1.24.0\n\n* Mon Aug 27 2018 J. D. User <jduser@noreply.com> 1.23.3-*git*\n- add BR freerdp-shadow2\n\n* Mon Aug 20 2018 J. D. User <jduser@noreply.com> 1.23.3\n- update to 1.23.3\n\n* Sat Mar 10 2018 J. D. User <jduser@noreply.com> 1.23.2\n- update to 1.23.2\n\n* Sun Feb 25 2018 J. D. User <jduser@noreply.com> 1.23.1\n- update to 1.23.1\n\n* Sun Feb 18 2018 J. D. User <jduser@noreply.com> 1.23.0-*git*\n- remove obsolete clean section\n\n* Sun Feb 18 2018 J. D. User <jduser@noreply.com> 1.23.0-*git*\n- change source URL to https://\n\n* Sun Feb 18 2018 J. D. User <jduser@noreply.com> 1.23.0-*git*\n- add BR gcc\n\n* Mon Nov 06 2017 J. D. User <jduser@noreply.com> 1.23.0-*git*\n- add BR appstream\n\n* Sun Nov 05 2017 J. D. User <jduser@noreply.com> 1.23.0-*git*\n- add support for new AppStream metadata file location\n\n* Sat Oct 28 2017 J. D. User <jduser@noreply.com> 1.23.0\n- update to 1.23.0\n- raise BR glib-2.0 >= 2.18.0\n- raise BR purple >= 2.7.0\n\n* Fri Aug 11 2017 J. D. User <jduser@noreply.com> 1.22.1-*git*\n- add BR dbus-1\n\n* Sun Jun 11 2017 J. D. User <jduser@noreply.com> 1.22.1\n- update to 1.22.1\n\n* Wed Feb 01 2017 J. D. User <jduser@noreply.com> 1.22.0\n- update to 1.22.0\n\n* Sun Dec 18 2016 J. D. User <jduser@noreply.com> 1.21.1-*git*\n- add BR gio-2.0\n\n* Wed Jun 15 2016 J. D. User <jduser@noreply.com> 1.21.1-*git*\n- add BR farstream-0.2\n\n* Sat May 28 2016 J. D. User <jduser@noreply.com> 1.21.1\n- update to 1.21.1\n\n* Sat Apr 23 2016 J. D. User <jduser@noreply.com> 1.21.0\n- update to 1.21.0\n\n* Tue Apr 05 2016 J. D. User <jduser@noreply.com> 1.20.1-*git*\n- align with Fedora SPEC file\n\n* Fri Jan 01 2016 J. D. User <jduser@noreply.com> 1.20.1-*git*\n- add AppStream metadata file\n\n* Sun Nov 08 2015 J. D. User <jduser@noreply.com> 1.20.1-*git*\n- add dependency on pkgconfig(gstreamer-1.0) for F22+\n\n* Sat Oct 24 2015 J. D. User <jduser@noreply.com> 1.20.1\n- update to 1.20.1\n\n* Thu Sep 03 2015 J. D. User <jduser@noreply.com> 1.20.0-*git*\n- we also support \"Skype for Business\"\n\n* Sat Aug 29 2015 J. D. User <jduser@noreply.com> 1.20.0\n- update to 1.20.0\n\n* Sat Apr 04 2015 J. D. User <jduser@noreply.com> 1.19.1\n- update to 1.19.1\n\n* Sat Feb 07 2015 J. D. User <jduser@noreply.com> 1.19.0\n- update to 1.19.0\n\n* Tue Jan 06 2015 J. D. User <jduser@noreply.com> 1.18.5-*git*\n- add dependency on gssntlmssp(-devel) >= 0.5.0 for F21+\n- enable Voice & Video features by default\n- move dependency on libnice-gstreamer to correct packages\n\n* Mon Dec 29 2014 J. D. User <jduser@noreply.com> 1.18.5\n- update to 1.18.5\n\n* Sat Oct 18 2014 J. D. User <jduser@noreply.com> 1.18.4\n- update to 1.18.4\n\n* Sat Aug 16 2014 J. D. User <jduser@noreply.com> 1.18.3\n- update to 1.18.3\n\n* Sat Jun 07 2014 J. D. User <jduser@noreply.com> 1.18.2\n- update to 1.18.2\n\n* Sat Apr 12 2014 J. D. User <jduser@noreply.com> 1.18.1\n- update to 1.18.1\n\n* Sat Mar 08 2014 J. D. User <jduser@noreply.com> 1.18.0-*git*\n- New Fedora packaging guidelines suggest to use pkgconfig() for BRs\n\n* Tue Mar 04 2014 J. D. User <jduser@noreply.com> 1.18.0-*git*\n- F20+ require libnice-gstreamer for correct operation\n\n* Sat Jan 11 2014 J. D. User <jduser@noreply.com> 1.18.0\n- update to 1.18.0\n\n* Wed Dec 11 2013 J. D. User <jduser@noreply.com> 1.17.3\n- update to 1.17.3\n\n* Sat Nov 30 2013 J. D. User <jduser@noreply.com> 1.17.2\n- update to 1.17.2\n\n* Sat Nov 16 2013 J. D. User <jduser@noreply.com> 1.17.1\n- update to 1.17.1\n\n* Sat Sep 21 2013 J. D. User <jduser@noreply.com> 1.17.0\n- update to 1.17.0\n\n* Sat Jul 13 2013 J. D. User <jduser@noreply.com> 1.16.1\n- update to 1.16.1\n\n* Fri Jun 14 2013 J. D. User <jduser@noreply.com> 1.16.0\n- update to 1.16.0\n\n* Thu May 16 2013 J. D. User <jduser@noreply.com> 1.15.1-*git*\n- BR glib-2.0 >= 2.28.0 no longer required for Voice & Video features\n\n* Sun Apr 07 2013 J. D. User <jduser@noreply.com> 1.15.1\n- update to 1.15.1\n\n* Fri Mar 29 2013 J. D. User <jduser@noreply.com> 1.15.0-*git*\n- update package description texts\n\n* Sat Mar 09 2013 J. D. User <jduser@noreply.com> 1.15.0\n- update to 1.15.0\n\n* Wed Dec 26 2012 J. D. User <jduser@noreply.com> 1.14.1\n- update to 1.14.1\n\n* Sun Dec 16 2012 J. D. User <jduser@noreply.com> 1.14.0\n- update to 1.14.0\n\n* Sun Sep 09 2012 J. D. User <jduser@noreply.com> 1.13.3-*git*\n- BR telepathy-glib-devel >= 0.18.0\n\n* Wed Sep 05 2012 J. D. User <jduser@noreply.com> 1.13.3-*git*\n- BR telepathy-glib-devel >= 0.14.0\n\n* Mon Aug 27 2012 J. D. User <jduser@noreply.com> 1.13.3-*git*\n- add ktp-accounts-kcm-sipe package\n\n* Sun Aug 26 2012 J. D. User <jduser@noreply.com> 1.13.3-*git*\n- telepathy now requires glib-2.0 >= 2.22.0\n- use \"--without telepathy\" to disable telepathy packages\n\n* Fri Aug 24 2012 J. D. User <jduser@noreply.com> 1.13.3-*git*\n- add empathy-sipe package\n\n* Wed Aug 22 2012 J. D. User <jduser@noreply.com> 1.13.3-*git*\n- add telepathy-sipe & sipe-common packages\n\n* Sun Aug 19 2012 J. D. User <jduser@noreply.com> 1.13.3\n- update to 1.13.3\n\n* Sun Jun 10 2012 J. D. User <jduser@noreply.com> 1.13.2\n- update to 1.13.2\n\n* Mon Apr 09 2012 J. D. User <jduser@noreply.com> 1.13.1\n- update to 1.13.1\n\n* Wed Mar 14 2012 J. D. User <jduser@noreply.com> 1.13.0\n- update to 1.13.0\n\n* Mon Dec 12 2011 J. D. User <jduser@noreply.com> 1.12.0-*git*\n- we do support Microsoft Lync Server 2010 now.\n\n* Tue Dec 06 2011 J. D. User <jduser@noreply.com> 1.12.0-*git*\n- update GPL2 license name\n\n* Sat Nov 12 2011 J. D. User <jduser@noreply.com> 1.12.0-*git*\n- add BR gmime-devel\n\n* Mon Oct 31 2011 J. D. User <jduser@noreply.com> 1.12.0-*git*\n- add BR nss-devel\n\n* Mon Aug 29 2011 J. D. User <jduser@noreply.com> 1.12.0\n- update to 1.12.0\n\n* Wed Jun 22 2011 J. D. User <jduser@noreply.com> 1.11.2-*git*\n- add \"--with vv\" option to enable Voice & Video features\n\n* Tue Nov 02 2010 J. D. User <jduser@noreply.com> 1.11.2\n- update to 1.11.2\n\n* Sun Oct 24 2010 J. D. User <jduser@noreply.com> 1.11.1\n- update to 1.11.1\n\n* Mon Oct 04 2010 J. D. User <jduser@noreply.com> 1.11.0\n- update to 1.11.0\n\n* Thu Sep 02 2010 J. D. User <jduser@noreply.com> 1.10.1-*git*\n- add (commented out) BR libnice-devel\n\n* Sun Jun 27 2010 J. D. User <jduser@noreply.com> 1.10.1\n- update to 1.10.1\n\n* Mon Apr 12 2010 J. D. User <jduser@noreply.com> 1.10.0-*git*\n- add (commented out) BR nss-devel\n\n* Sun Apr 04 2010 J. D. User <jduser@noreply.com> 1.10.0\n- update to 1.10.0\n\n* Sun Mar 28 2010 J. D. User <jduser@noreply.com> 1.9.1-*git*\n- changed --with/--without options to --enable/--disable\n\n* Sun Mar 28 2010 J. D. User <jduser@noreply.com> 1.9.1-*git*\n- removed --with-krb5 configure option as it is autodetected now\n\n* Tue Mar 23 2010 J. D. User <jduser@noreply.com> 1.9.1-*git*\n- add SVG icon\n\n* Sat Mar 20 2010 J. D. User <jduser@noreply.com> 1.9.1-*git*\n- add BR glib2-devel >= 2.12.0\n\n* Wed Mar 17 2010 J. D. User <jduser@noreply.com> 1.9.1-*git*\n- add tests to build\n\n* Tue Mar 16 2010 J. D. User <jduser@noreply.com> 1.9.1\n- update to 1.9.1\n\n* Thu Mar 11 2010 J. D. User <jduser@noreply.com> 1.9.0-*git*\n- add BR libxml2-devel\n\n* Wed Mar 10 2010 J. D. User <jduser@noreply.com> 1.9.0\n- update to 1.9.0\n\n* Mon Mar 08 2010 J. D. User <jduser@noreply.com> 1.8.1-*git*\n- increased libpurple build requisite to >= 2.4.0\n\n* Sun Mar 07 2010 J. D. User <jduser@noreply.com> 1.8.1-*git*\n- sync with RPM SPEC from contrib/OBS\n\n* Sat Mar 06 2010 J. D. User <jduser@noreply.com> 1.8.1-*git*\n- update package summary & description\n\n* Tue Feb 16 2010 J. D. User <jduser@noreply.com> 1.8.1\n- update to 1.8.1\n\n* Sun Feb 07 2010 J. D. User <jduser@noreply.com> 1.8.0\n- update to 1.8.0\n\n* Thu Jan 14 2010 J. D. User <jduser@noreply.com> 1.7.1-*git*\n- autogen.sh no longer runs configure\n\n* Tue Dec 29 2009 J. D. User <jduser@noreply.com> 1.7.1-*git*\n- add configure parameters for purple and telepathy\n\n* Sat Dec 12 2009 J. D. User <jduser@noreply.com> 1.7.1-*git*\n- add Epoch: for git packages to avoid update clash with official packages\n\n* Thu Nov 19 2009 J. D. User <jduser@noreply.com> 1.7.1\n- update to 1.7.1\n\n* Wed Oct 28 2009 J. D. User <jduser@noreply.com> 1.7.0-*git*\n- add missing Group: to purple-sipe\n\n* Mon Oct 19 2009 J. D. User <jduser@noreply.com> 1.7.0\n- update to 1.7.0\n\n* Sun Oct 11 2009 J. D. User <jduser@noreply.com> 1.6.3-*git*\n- move non-Pidgin files to new sub-package purple-sipe\n\n* Sun Oct 11 2009 J. D. User <jduser@noreply.com> 1.6.3-*git*\n- remove directory for emoticon theme icons\n\n* Sun Oct 11 2009 J. D. User <jduser@noreply.com> 1.6.3-*git*\n- libpurple protocol plugins are located under %%{_libdir}/purple-2\n\n* Mon Sep 28 2009 J. D. User <jduser@noreply.com> 1.6.3-*git*\n- added directory for emoticon theme icons\n\n* Wed Sep 09 2009 J. D. User <jduser@noreply.com> 1.6.3\n- update to 1.6.3\n\n* Fri Aug 28 2009 J. D. User <jduser@noreply.com> 1.6.2-*git*\n- reduce libpurple-devel requirement to >= 2.3.1\n\n* Mon Aug 24 2009 J. D. User <jduser@noreply.com> 1.6.2\n- update to 1.6.2\n\n* Fri Aug 21 2009 J. D. User <jduser@noreply.com> 1.6.1-*git*\n- reduce libpurple-devel requirement to >= 2.4.1\n\n* Mon Aug 17 2009 J. D. User <jduser@noreply.com> 1.6.1-*git*\n- com_err.h only required for kerberos\n\n* Tue Aug 11 2009 J. D. User <jduser@noreply.com> 1.6.0-*git*\n- require libpurple-devel >= 2.5.0\n\n* Sun Aug 09 2009 J. D. User <jduser@noreply.com> 1.6.0-*git*\n- refactor configure parameters\n- make kerberos configurable\n- don't hard code prefix for git builds\n\n* Sun Aug 09 2009 J. D. User <jduser@noreply.com> 1.6.0-*git*\n- removed unnecessary zlib-devel\n\n* Sat Aug 08 2009 J. D. User <jduser@noreply.com> 1.6.0-*git*\n- fix prefix for git builds\n\n* Sat Aug 01 2009 J. D. User <jduser@noreply.com> 1.6.0-*git*\n- append -Wno-unused-parameter for GCC <4.4 compilation errors\n\n* Thu Jul 30 2009 J. D. User <jduser@noreply.com> 1.6.0-*git*\n- remove duplicate GPL2\n\n* Thu Jul 30 2009 J. D. User <jduser@noreply.com> 1.6.0-*git*\n- use \"--with git\" to build from git\n- corrected download URL for release archive\n- add missing BR gettext-devel\n\n* Wed Jul 29 2009 J. D. User <jduser@noreply.com> 1.6.0-*git*\n- use default rpmbuild CFLAGS also for git builds\n- merge with SPEC files created by mricon & jberanek\n\n* Tue Jul 28 2009 J. D. User <jduser@noreply.com> 1.6.0-*git*\n- initial RPM SPEC example generated\n"
  },
  {
    "path": "git-build.sh",
    "content": "#!/bin/sh\n#\n# Convenience to (re-)build pidgin-sipe from git repository.\n#\n# Example: add configure parameters\n#\n#  $ ./git-build.sh --with-krb5\n#\n# Example: setup debug build, e.g. for valgrind ((ba)sh style)\n#\n#  $ CFLAGS=\"-g -O0\" ./git-build.sh\n#\n# Sanity check\nif [ ! -x autogen.sh ]; then\n    echo 1>&2 \"Your pidgin-sipe repository seems to be broken...\"\n    exit 1\nfi\n\n# Check for previous build artifacts\nrm -f build.log\nif [ -r Makefile ]; then\n    echo \"Cleaning up previous build artifacts...\"\n    echo >build.log \"------ Cleanup ------\"\n    make >>build.log 2>&1 -k maintainer-clean\nfi\n\n# Rebuild\n(\n    set -e\n    echo \"Generating configure script...\"\n    echo >>build.log \"------ Generate Configure Script ------\"\n    ./autogen.sh >>build.log 2>&1\n    echo -n \"Configuring build with\"\n    if [ $# -eq 0  ]; then\n\techo \"out any options...\"\n    else\n\techo \" '$@'...\"\n    fi\n    echo >>build.log \"------ Configure ------\"\n    ./configure >>build.log 2>&1 \"$@\"\n    echo \"Running build...\"\n    echo >>build.log \"------ Build ------\"\n    make >>build.log 2>&1\n)\nif [ $? -eq 0 ]; then\n    echo >>build.log \"------ SUCCESS ------\"\n    echo \"Congratulations: the build was successful!\"\nelse\n    echo >>build.log \"------ FAILED ------\"\n    echo 1>&2 \"Build FAILED!\"\nfi\necho \"Details can be found in 'build.log'.\"\n"
  },
  {
    "path": "git-snapshot.sh",
    "content": "#!/bin/sh\n#\n# Take a snapshot of the current pidgin-sipe git HEAD from the mob branch.\n#\n# You can specify the path to a local repository to speed up the cloning\n# process. The output will be a bzip2 compressed tarball whose name includes\n# the current date and the abbreviated commit object name of HEAD.\n#\n# Adapted from several examples found on the Internet.\n#\n# Configuration\nPROJECT=pidgin-sipe\nREPOSITORY=\"git+ssh://mob@repo.or.cz/srv/git/siplcs.git\"\nBRANCH=mob\n\n# Create clone\nset -e\nTODAY=$(date +%Y%m%d)\nCLONEDIR=${PROJECT}-${TODAY}\necho \"Clone directory '$CLONEDIR'.\"\nREFERENCE=${1:+--reference $1}\nif [ -n \"$1\" ]; then\n    echo \"Using local repository under '$1'.\"\nfi\nif [ -n \"$2\" ]; then\n    REPOSITORY=$2\nfi\necho \"Cloning from repository URL '$REPOSITORY'.\"\nrm -rf $CLONEDIR\ngit clone -n $REFERENCE $REPOSITORY $CLONEDIR\ncd $CLONEDIR\ngit checkout -q -b $CLONEDIR origin/$BRANCH\n\n# Create archive\nCOMMIT=$(git log -n 1 --abbrev-commit --pretty=oneline | cut -d' ' -f1| sed -e 's/\\.//g')\nPREFIX=${PROJECT}-${TODAY}git${COMMIT}\nARCHIVE=${PREFIX}.tar.bz2\necho \"Creating archive '$ARCHIVE'...\"\ngit archive --format=tar --prefix=$PREFIX/ HEAD | bzip2 >../${PREFIX}.tar.bz2\n\n# Cleanup\necho \"Cleanup...\"\ncd ..\nrm -rf $CLONEDIR\necho \"DONE.\"\n"
  },
  {
    "path": "pidgin-sipe.nsi",
    "content": ";NSIS Modern User Interface\n;Basic Example Script\n;Written by Joost Verburg\n\n;--------------------------------\n;Include Modern UI\n\n!include \"MUI.nsh\"\n\n;--------------------------------\n;General\n\n;Name and file\nName \"Pidgin SIPE Plugin\"\nOutFile \"pidgin-sipe-${VERSION}.exe\"\n\n;Default installation folder\nInstallDir \"$PROGRAMFILES\\Pidgin\"\n\n;Get installation folder from registry if available\nInstallDirRegKey HKLM \"Software\\pidgin\" \"\"\n\n;\nSetCompressor /FINAL /SOLID lzma\nSetCompressorDictSize 64\n\n;--------------------------------\n;Interface Settings\n\n!define MUI_ABORTWARNING\n\n;--------------------------------\n;Pages\n\n;!insertmacro MUI_PAGE_LICENSE \"Basic.nsi\"\n;!insertmacro MUI_PAGE_COMPONENTS\n!insertmacro MUI_PAGE_DIRECTORY\n!insertmacro MUI_PAGE_INSTFILES\n\n!insertmacro MUI_UNPAGE_CONFIRM\n!insertmacro MUI_UNPAGE_INSTFILES\n\n;--------------------------------\n;Languages\n\n!insertmacro MUI_LANGUAGE \"English\"\n\n;--------------------------------\n;Installer Sections\n\nSection \"PidginSIPE\" SecPidginSIPE\nSetOutPath \"$INSTDIR\"\nFile \"${TREETOP}\\..\\win32-dev\\mingw\\bin\\libiconv-2.dll\"\nSetOutPath \"$INSTDIR\\plugins\"\nFile \"${TREETOP}\\win32-install-dir\\plugins\\libsipe.dll\"\nSetOutPath \"$INSTDIR\\locale\\ar\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\ar\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\cs\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\cs\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\da\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\da\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\de\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\de\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\es\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\es\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\fi\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\fi\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\fr\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\fr\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\hi\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\hi\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\hu\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\hu\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\it\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\it\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\ja\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\ja\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\ko\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\ko\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\nb\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\nb\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\nl\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\nl\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\pl\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\pl\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\pt_BR\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\pt_BR\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\ru\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\ru\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\sv\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\sv\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\ta\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\ta\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\zh_CN\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\zh_CN\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\locale\\zh_TW\\LC_MESSAGES\"\nFile \"${TREETOP}\\win32-install-dir\\locale\\zh_TW\\LC_MESSAGES\\pidgin-sipe.mo\"\nSetOutPath \"$INSTDIR\\pixmaps\\pidgin\\protocols\\16\"\nFile \"${TREETOP}\\win32-install-dir\\pixmaps\\pidgin\\protocols\\16\\sipe.png\"\nSetOutPath \"$INSTDIR\\pixmaps\\pidgin\\protocols\\22\"\nFile \"${TREETOP}\\win32-install-dir\\pixmaps\\pidgin\\protocols\\22\\sipe.png\"\nSetOutPath \"$INSTDIR\\pixmaps\\pidgin\\protocols\\48\"\nFile \"${TREETOP}\\win32-install-dir\\pixmaps\\pidgin\\protocols\\48\\sipe.png\"\n\n;Create uninstaller\nWriteUninstaller \"$INSTDIR\\Uninstall-pidgin-sipe.exe\"\n\nSectionEnd\n\n;--------------------------------\n;Descriptions\n\n;Language strings\nLangString DESC_SecPidginSIPE ${LANG_ENGLISH} \"The Pidgin SIPE Plugin.\"\n\n;Assign language strings to sections\n;!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN\n;\t!insertmacro MUI_DESCRIPTION_TEXT ${SecPidginPP} $(DESC_SecPidginPP)\n;!insertmacro MUI_FUNCTION_DESCRIPTION_END\n\n;--------------------------------\n;Uninstaller Section\n\nSection \"Uninstall\"\n\n;ADD YOUR OWN FILES HERE...\n\nDelete \"$INSTDIR\\Uninstall-pidgin-sipe.exe\"\nDelete \"$INSTDIR\\libiconv-2.dll\"\nDelete \"$INSTDIR\\plugins\\libsipe.dll\"\nDelete \"$INSTDIR\\locale\\ar\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\cs\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\da\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\de\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\es\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\fi\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\fr\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\hi\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\hu\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\it\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\ja\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\ko\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\nb\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\nl\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\output\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\pl\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\pt_BR\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\ru\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\sv\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\ta\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\zh_CN\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\locale\\zh_TW\\LC_MESSAGES\\pidgin-sipe.mo\"\nDelete \"$INSTDIR\\pixmaps\\pidgin\\protocols\\16\\sipe.png\"\nDelete \"$INSTDIR\\pixmaps\\pidgin\\protocols\\22\\sipe.png\"\nDelete \"$INSTDIR\\pixmaps\\pidgin\\protocols\\48\\sipe.png\"\n\nSectionEnd\n\n"
  },
  {
    "path": "pidgin-sipe.wxs",
    "content": "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n<Wix xmlns=\"http://schemas.microsoft.com/wix/2006/wi\">\n  <!-- online GUID generator http://www.somacon.com/p113.php -->\n  <Product Name=\"Pidgin SIPE plug-in $(env.PACKAGE_VERSION)\" Id=\"*\" UpgradeCode=\"5B2EC7C8-2A9A-11DE-9AEE-4E8256D89593\" Language=\"1033\" Codepage=\"1252\" Version=\"$(env.PACKAGE_VERSION)\" Manufacturer=\"http://sipe.sourceforge.net/\">\n    <Package Id=\"*\" Keywords=\"Installer\" Description=\"Pidgin SIPE plug-in $(env.PACKAGE_VERSION) Installer\" Comments=\"An Open Implementation of SIP/Simple protocol for Live Communications Server 2003/2005/2007/2007R2\" Manufacturer=\"http://sipe.sourceforge.net/\" InstallerVersion=\"100\" Languages=\"1033\" Compressed=\"yes\" SummaryCodepage=\"1252\"/>\n    <Property Id=\"OLDERVERSIONBEINGUPGRADED\" Secure=\"yes\" />\n    <Media Id=\"1\" Cabinet=\"Sample.cab\" EmbedCab=\"yes\" DiskPrompt=\"CD-ROM #1\"/>\n    <Property Id=\"DiskPrompt\" Value=\"Pidgin SIPE plug-in $(env.PACKAGE_VERSION) Installation [1]\"/>\n\n    <Upgrade Id=\"5B2EC7C8-2A9A-11DE-9AEE-4E8256D89593\">\n      <UpgradeVersion Minimum=\"0.00.0000\" IncludeMinimum=\"yes\" Maximum=\"$(env.PACKAGE_VERSION)\" IncludeMaximum=\"no\" OnlyDetect=\"no\" MigrateFeatures=\"yes\" IgnoreRemoveFailure=\"yes\" Property=\"OLDERVERSIONBEINGUPGRADED\" />\n    </Upgrade>\n\n    <Directory Id=\"TARGETDIR\" Name=\"SourceDir\">\n      <Directory Id=\"ProgramFilesFolder\" Name=\"PFiles\">\n        <Directory Id=\"INSTALLDIR\" Name=\"Pidgin\">\n          <Component Id=\"IconvDLL\" Guid=\"A609DDD2-EB69-11DF-AC01-B734DFD72085\">\n            <File Id=\"LibiconvDLL\" Name=\"libiconv-2.dll\" DiskId=\"1\" Source=\"libiconv-2.dll\" Vital=\"yes\"/>\n          </Component>\n          <!-- SIPE dll -->\n          <Directory Id=\"plugins\" Name=\"plugins\">\n            <Component Id=\"MainExecutable\" Guid=\"C0F1C152-2A98-11DE-9F53-817056D89593\">\n              <File Id=\"LibsipeDLL\" Name=\"libsipe.dll\" DiskId=\"1\" Source=\"src\\core\\libsipe.dll\" Vital=\"yes\"/>\n            </Component>\n          </Directory>\n          <!-- Protocal Icons -->\n          <Directory Id=\"pixmaps\" Name=\"pixmaps\">\n            <Directory Id=\"pidgin\" Name=\"pidgin\">\n              <Directory Id=\"protocols\" Name=\"protocols\">\n                <Directory Id=\"sixteen\" Name=\"16\">\n                  <Component Id=\"PixmapsProtocols16icon\" Guid=\"DF22ADA4-2A9C-11DE-A54B-FD9B56D89593\">\n                    <File Id=\"SipePNG16\" Name=\"sipe.png\" DiskId=\"1\" Source=\"pixmaps/16/sipe.png\" Vital=\"yes\"/>\n                  </Component>\n                </Directory>\n                <Directory Id=\"twenty.two\" Name=\"22\">\n                  <Component Id=\"PixmapsProtocols22icon\" Guid=\"58A125D8-2A9E-11DE-912A-71AD56D89593\">\n                    <File Id=\"SipePNG22\" Name=\"sipe.png\" DiskId=\"1\" Source=\"pixmaps/22/sipe.png\" Vital=\"yes\"/>\n                  </Component>\n                </Directory>\n                <Directory Id=\"forty.eight\" Name=\"48\">\n                  <Component Id=\"PixmapsProtocols48icon\" Guid=\"62BD24FE-2A9E-11DE-802B-E7AE56D89593\">\n                    <File Id=\"SipePNG48\" Name=\"sipe.png\" DiskId=\"1\" Source=\"pixmaps/48/sipe.png\" Vital=\"yes\"/>\n                  </Component>\n                </Directory>\n              </Directory>\n            </Directory>\n          </Directory>\n          <!-- Translations -->\n          <Directory Id=\"locale\" Name=\"locale\">\n            <Directory Id=\"cs\" Name=\"cs\">\n              <Directory Id=\"cs_LC_MESSAGES\" Name=\"LC_MESSAGES\">\n                <Component Id=\"LocaleCsLcMessages\" Guid=\"026FD274-5F21-11DE-BE4B-D76A56D89593\">\n                  <File Id=\"cs.gmo\" Name=\"pidgin-sipe.mo\" DiskId=\"1\" Source=\"po/cs.gmo\" Vital=\"yes\"/>\n                </Component>\n              </Directory>\n            </Directory>\n            <Directory Id=\"da\" Name=\"da\">\n              <Directory Id=\"da_LC_MESSAGES\" Name=\"LC_MESSAGES\">\n                <Component Id=\"LocaleDaLcMessages\" Guid=\"2AE5620C-2A9F-11DE-930D-E5B556D89593\">\n                  <File Id=\"da.gmo\" Name=\"pidgin-sipe.mo\" DiskId=\"1\" Source=\"po/da.gmo\" Vital=\"yes\"/>\n                </Component>\n              </Directory>\n            </Directory>\n            <Directory Id=\"de\" Name=\"de\">\n              <Directory Id=\"de_LC_MESSAGES\" Name=\"LC_MESSAGES\">\n                <Component Id=\"LocaleDeLcMessages\" Guid=\"57D06CC0-2AA0-11DE-BACD-A7C056D89593\">\n                  <File Id=\"de.gmo\" Name=\"pidgin-sipe.mo\" DiskId=\"1\" Source=\"po/de.gmo\" Vital=\"yes\"/>\n                </Component>\n              </Directory>\n            </Directory>\n            <Directory Id=\"es\" Name=\"es\">\n              <Directory Id=\"es_LC_MESSAGES\" Name=\"LC_MESSAGES\">\n                <Component Id=\"LocaleEsLcMessages\" Guid=\"619F22C8-2AA0-11DE-B345-EFC056D89593\">\n                  <File Id=\"es.gmo\" Name=\"pidgin-sipe.mo\" DiskId=\"1\" Source=\"po/es.gmo\" Vital=\"yes\"/>\n                </Component>\n              </Directory>\n            </Directory>\n            <Directory Id=\"fi\" Name=\"fi\">\n              <Directory Id=\"fi_LC_MESSAGES\" Name=\"LC_MESSAGES\">\n                <Component Id=\"LocaleFiLcMessages\" Guid=\"1BC74F20-0EAA-11DF-9BE6-406D55D89593\">\n                  <File Id=\"fi.gmo\" Name=\"pidgin-sipe.mo\" DiskId=\"1\" Source=\"po/fi.gmo\" Vital=\"yes\"/>\n                </Component>\n              </Directory>\n            </Directory>\n            <Directory Id=\"fr\" Name=\"fr\">\n              <Directory Id=\"fr_LC_MESSAGES\" Name=\"LC_MESSAGES\">\n                <Component Id=\"LocaleFrLcMessages\" Guid=\"675623F6-2AA0-11DE-892D-0FC156D89593\">\n                  <File Id=\"fr.gmo\" Name=\"pidgin-sipe.mo\" DiskId=\"1\" Source=\"po/fr.gmo\" Vital=\"yes\"/>\n                </Component>\n              </Directory>\n            </Directory>\n            <Directory Id=\"hi\" Name=\"hi\">\n              <Directory Id=\"hi_LC_MESSAGES\" Name=\"LC_MESSAGES\">\n                <Component Id=\"LocaleHiLcMessages\" Guid=\"6E3FDAD6-2AA0-11DE-AB1D-53C156D89593\">\n                  <File Id=\"hi.gmo\" Name=\"pidgin-sipe.mo\" DiskId=\"1\" Source=\"po/hi.gmo\" Vital=\"yes\"/>\n                </Component>\n              </Directory>\n            </Directory>\n            <Directory Id=\"it\" Name=\"it\">\n              <Directory Id=\"it_LC_MESSAGES\" Name=\"LC_MESSAGES\">\n                <Component Id=\"LocaleItLcMessages\" Guid=\"D02EDFEC-5CED-11DE-9027-84C456D89593\">\n                  <File Id=\"it.gmo\" Name=\"pidgin-sipe.mo\" DiskId=\"1\" Source=\"po/it.gmo\" Vital=\"yes\"/>\n                </Component>\n              </Directory>\n            </Directory>\n            <Directory Id=\"nb\" Name=\"nb\">\n              <Directory Id=\"nb_LC_MESSAGES\" Name=\"LC_MESSAGES\">\n                <Component Id=\"LocaleNbLcMessages\" Guid=\"2B63CAE6-5F21-11DE-B69E-D46B56D89593\">\n                  <File Id=\"nb.gmo\" Name=\"pidgin-sipe.mo\" DiskId=\"1\" Source=\"po/nb.gmo\" Vital=\"yes\"/>\n                </Component>\n              </Directory>\n            </Directory>\n            <Directory Id=\"nl\" Name=\"nl\">\n              <Directory Id=\"nl_LC_MESSAGES\" Name=\"LC_MESSAGES\">\n                <Component Id=\"LocaleNlLcMessages\" Guid=\"C058D684-432B-11DF-A979-159555D89593\">\n                  <File Id=\"nl.gmo\" Name=\"pidgin-sipe.mo\" DiskId=\"1\" Source=\"po/nl.gmo\" Vital=\"yes\"/>\n                </Component>\n              </Directory>\n            </Directory>\n            <Directory Id=\"pl\" Name=\"pl\">\n              <Directory Id=\"pl_LC_MESSAGES\" Name=\"LC_MESSAGES\">\n                <Component Id=\"LocalePlLcMessages\" Guid=\"55BFEA02-0DE2-11DF-8408-137956D89593\">\n                  <File Id=\"pl.gmo\" Name=\"pidgin-sipe.mo\" DiskId=\"1\" Source=\"po/pl.gmo\" Vital=\"yes\"/>\n                </Component>\n              </Directory>\n            </Directory>\n            <Directory Id=\"pt_BR\" Name=\"pt_BR\">\n              <Directory Id=\"pt_BR_LC_MESSAGES\" Name=\"LC_MESSAGES\">\n                <Component Id=\"LocalePtBrLcMessages\" Guid=\"68E345DE-1D3C-11DF-95EC-76AC55D89593\">\n                  <File Id=\"pt_BR.gmo\" Name=\"pidgin-sipe.mo\" DiskId=\"1\" Source=\"po/pt_BR.gmo\" Vital=\"yes\"/>\n                </Component>\n              </Directory>\n            </Directory>\n            <Directory Id=\"ru\" Name=\"ru\">\n              <Directory Id=\"ru_LC_MESSAGES\" Name=\"LC_MESSAGES\">\n                <Component Id=\"LocaleRuLcMessages\" Guid=\"DFF98418-5CED-11DE-93FA-18C556D89593\">\n                  <File Id=\"ru.gmo\" Name=\"pidgin-sipe.mo\" DiskId=\"1\" Source=\"po/ru.gmo\" Vital=\"yes\"/>\n                </Component>\n              </Directory>\n            </Directory>\n            <Directory Id=\"ta\" Name=\"ta\">\n              <Directory Id=\"ta_LC_MESSAGES\" Name=\"LC_MESSAGES\">\n                <Component Id=\"LocaleTaLcMessages\" Guid=\"752DBD5E-2AA0-11DE-B49D-17C256D89593\">\n                  <File Id=\"ta.gmo\" Name=\"pidgin-sipe.mo\" DiskId=\"1\" Source=\"po/ta.gmo\" Vital=\"yes\"/>\n                </Component>\n              </Directory>\n            </Directory>\n            <Directory Id=\"zh_CN\" Name=\"zh_CN\">\n              <Directory Id=\"zh_CN_LC_MESSAGES\" Name=\"LC_MESSAGES\">\n                <Component Id=\"LocaleZhCnLcMessages\" Guid=\"2762E448-361A-11DE-83ED-79A556D89593\">\n                  <File Id=\"zh_CN.gmo\" Name=\"pidgin-sipe.mo\" DiskId=\"1\" Source=\"po/zh_CN.gmo\" Vital=\"yes\"/>\n                </Component>\n              </Directory>\n            </Directory>\n          </Directory>\n        </Directory>\n      </Directory>\n    </Directory>\n    <Feature Id=\"Complete\" Level=\"1\">\n      <ComponentRef Id=\"MainExecutable\"/>\n      <ComponentRef Id=\"IconvDLL\"/>\n      <ComponentRef Id=\"PixmapsProtocols16icon\"/>\n      <ComponentRef Id=\"PixmapsProtocols22icon\"/>\n      <ComponentRef Id=\"PixmapsProtocols48icon\"/>\n      <ComponentRef Id=\"LocaleCsLcMessages\"/>\n      <ComponentRef Id=\"LocaleDaLcMessages\"/>\n      <ComponentRef Id=\"LocaleDeLcMessages\"/>\n      <ComponentRef Id=\"LocaleEsLcMessages\"/>\n      <ComponentRef Id=\"LocaleFiLcMessages\"/>\n      <ComponentRef Id=\"LocaleFrLcMessages\"/>\n      <ComponentRef Id=\"LocaleHiLcMessages\"/>\n      <ComponentRef Id=\"LocaleItLcMessages\"/>\n      <ComponentRef Id=\"LocaleNbLcMessages\"/>\n      <ComponentRef Id=\"LocaleNlLcMessages\"/>\n      <ComponentRef Id=\"LocalePlLcMessages\"/>\n      <ComponentRef Id=\"LocalePtBrLcMessages\"/>\n      <ComponentRef Id=\"LocaleRuLcMessages\"/>\n      <ComponentRef Id=\"LocaleTaLcMessages\"/>\n      <ComponentRef Id=\"LocaleZhCnLcMessages\"/>\n    </Feature>\n    <!--Icon Id=\"sipe.png\" SourceFile=\"pixmaps/16/sipe.png\" /-->\n\n    <InstallExecuteSequence>\n      <RemoveExistingProducts Before=\"InstallInitialize\" />\n    </InstallExecuteSequence>\n  </Product>\n</Wix>\n\n"
  },
  {
    "path": "pixmaps/16/Makefile.am",
    "content": "pixmapsize = 16\npixmapinst = 16x16\npixmapext  = png\ninclude $(srcdir)/../Makefile.common.am\n"
  },
  {
    "path": "pixmaps/22/Makefile.am",
    "content": "pixmapsize = 22\npixmapinst = 22x22\npixmapext  = png\ninclude $(srcdir)/../Makefile.common.am\n"
  },
  {
    "path": "pixmaps/24/Makefile.am",
    "content": "pixmapsize = 24\npixmapinst = 24x24\npixmapext  = png\ninclude $(srcdir)/../Makefile.common.am\n"
  },
  {
    "path": "pixmaps/32/Makefile.am",
    "content": "pixmapsize = 32\npixmapinst = 32x32\npixmapext  = png\ninclude $(srcdir)/../Makefile.common.am\n"
  },
  {
    "path": "pixmaps/48/Makefile.am",
    "content": "pixmapsize = 48\npixmapinst = 48x48\npixmapext  = png\ninclude $(srcdir)/../Makefile.common.am\n"
  },
  {
    "path": "pixmaps/Makefile.am",
    "content": "SUBDIRS = 16 22 24 32 48 scalable\n\nEXTRA_DIST = \\\n\tMakefile.mingw\n\nMAINTAINERCLEANFILES = \\\n\tMakefile.in\n"
  },
  {
    "path": "pixmaps/Makefile.common.am",
    "content": "MAINTAINERCLEANFILES = Makefile.in\nEXTRA_DIST           = sipe.$(pixmapext)\n\nif SIPE_INCLUDE_PURPLE\npidginprotocolpixdir   = $(datadir)/pixmaps/pidgin/protocols/$(pixmapsize)\npidginprotocolpix_DATA = sipe.$(pixmapext)\nendif\n\nif SIPE_INCLUDE_TELEPATHY\nempathyappsiconsdir    = $(datadir)/empathy/icons/hicolor/$(pixmapinst)/apps\nempathyappsicons_DATA  = im-sipe.$(pixmapext)\nDISTCLEANFILES         = im-sipe.$(pixmapext)\n\nim-sipe.$(pixmapext): $(srcdir)/sipe.$(pixmapext)\n\tcp $< $@\nendif\n"
  },
  {
    "path": "pixmaps/Makefile.mingw",
    "content": "#\n# Makefile.mingw\n#\n# Description: Makefile for win32 (mingw) version of Pidgin pixmaps\n#\n\nOLD_PIDGIN_TREE_TOP := $(PIDGIN_TREE_TOP)\nPIDGIN_TREE_TOP := ../$(OLD_PIDGIN_TREE_TOP)\n\ninclude $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak\n\ndatadir := $(PIDGIN_INSTALL_DIR)\npidginprotocolpixdir = $(datadir)/pixmaps/pidgin/protocols\n\nPROTOCOLS_16 = \\\n\t\t16/sipe.png\n\nPROTOCOLS_22 = \\\n\t\t22/sipe.png\n\nPROTOCOLS_48 = \\\n\t\t48/sipe.png\n\nPROTOCOLS_scalable = \\\n\t\tscalable/sipe.svg\n\nnobase_dist_pidginpixmap_DATA = \\\n\t\t$(PROTOCOLS_16) \\\n\t\t$(PROTOCOLS_22) \\\n\t\t$(PROTOCOLS_48) \\\n\t\t$(PROTOCOLS_scalable) \\\n\n.PHONY: install\n\ninstall:\n\tif test '$(nobase_dist_pidginpixmap_DATA)'; then \\\n\t  list='$(nobase_dist_pidginpixmap_DATA)'; for file in $$list; do \\\n\t    dir=`dirname $$file`; \\\n\t    mkdir -p $(pidginprotocolpixdir)/$$dir; \\\n\t    cp $$file $(pidginprotocolpixdir)/$$dir/; \\\n\t  done; \\\n\tfi;\n"
  },
  {
    "path": "pixmaps/scalable/Makefile.am",
    "content": "pixmapsize = scalable\npixmapinst = scalable\npixmapext  = svg\ninclude $(srcdir)/../Makefile.common.am\n\n# original artwork is only distributed, not installed\nEXTRA_DIST += sipe-original.svg\n"
  },
  {
    "path": "po/LINGUAS",
    "content": "ar\ncs\nda\nde\nel\nes\nfi\nfr\nfr_CA\nhi\nhu\nit\nja\nko\nlt\nnb\nnl\npl\npt\npt_BR\nro\nru\nsv\nta\nte\ntr\nzh_CN\nzh_TW\n"
  },
  {
    "path": "po/Makefile.mingw",
    "content": "# Makefile.mingw\n#\n# Description: Makefile to generate mo files\n#\n\nOLD_PIDGIN_TREE_TOP := $(PIDGIN_TREE_TOP)\nPIDGIN_TREE_TOP := ../$(OLD_PIDGIN_TREE_TOP)\n\ninclude $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak\n\nPACKAGE = pidgin-sipe\n\n.SUFFIXES:\n.SUFFIXES: .po .gmo\n\n##\n## SOURCES, OBJECTS\n##\n\nCATALOGS = $(patsubst %.po,%.gmo,$(wildcard *.po))\n\n##\n## RULES\n##\n\n.po.gmo:\n\trm -f $@ && $(GMSGFMT) --statistics -o $@ $<\n\n##\n## TARGETS\n##\n\n.PHONY: all install clean\n\nall: $(CATALOGS)\n\ninstall: all\n\tmkdir -p $(PURPLE_INSTALL_PO_DIR)\n\t@catalogs='$(CATALOGS)'; \\\n\tfor cat in $$catalogs; do \\\n\t  cat=`basename $$cat`; \\\n\t  lang=`echo $$cat | sed 's/\\.gmo$$//'`; \\\n\t  dir=$(PURPLE_INSTALL_PO_DIR)/$$lang/LC_MESSAGES; \\\n\t  mkdir -p $$dir; \\\n\t  if test -r $$cat; then \\\n\t    cp $$cat $$dir/$(PACKAGE).mo; \\\n\t    echo \"installing $$cat as $$dir/$(PACKAGE).mo\"; \\\n\t  else \\\n\t    cp $(PURPLE_PO_TOP)/$$cat $$dir/$(PACKAGE).mo; \\\n\t    echo \"installing $(PURPLE_PO_TOP)/$$cat as\" \\\n\t\t \"$$dir/$(PACKAGE).mo\"; \\\n\t  fi; \\\n\tdone\n\nclean:\n\trm -f *.gmo\n"
  },
  {
    "path": "po/POTFILES.in",
    "content": "# List of source files containing translatable strings.\n[encoding: UTF-8]\n\nsrc/adium/ESPurpleSIPEAccount.h\nsrc/core/sip-transport.c\nsrc/core/sipe-appshare.c\nsrc/core/sipe-buddy.c\nsrc/core/sipe-cal.c\nsrc/core/sipe-certificate.c\nsrc/core/sipe-chat.c\nsrc/core/sipe-conf.c\nsrc/core/sipe-core.c\nsrc/core/sipe-domino.c\nsrc/core/sipe-ft.c\nsrc/core/sipe-ft-lync.c\nsrc/core/sipe-ft-tftp.c\nsrc/core/sipe-group.c\nsrc/core/sipe-groupchat.c\nsrc/core/sipe-im.c\nsrc/core/sipe-incoming.c\nsrc/core/sipe-media.c\nsrc/core/sipe-notify.c\nsrc/core/sipe-ocs2007.c\nsrc/core/sipe-status.c\nsrc/core/sipe-subscriptions.c\nsrc/core/sipe-ucs.c\nsrc/core/sipe-user.c\nsrc/purple/purple-buddy.c\nsrc/purple/purple-chat.c\nsrc/purple/purple-groupchat.c\nsrc/purple/purple-im.c\nsrc/purple/purple-plugin-common.c\nsrc/purple/purple-search.c\nsrc/purple/purple-transport.c\nsrc/purple/purple-user.c\nsrc/telepathy/telepathy-protocol.c\nsrc/telepathy/telepathy-transport.c\n"
  },
  {
    "path": "po/ar.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Stefan Becker <chemobejk@gmail.com>, 2011\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 16:09+0000\\n\"\n\"Last-Translator: Stefan Becker <chemobejk@gmail.com>\\n\"\n\"Language-Team: Arabic (http://www.transifex.com/stefanb/pidgin-sipe/language/ar/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: ar\\n\"\n\"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"لقد تم رفضك من قِبل الخادم: %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"السبب غير محدد\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"الخدمة غير متاحة: %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"تم استلام توقيع رسالة غير صالح\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\nmsgstr[2] \"\"\nmsgstr[3] \"\"\nmsgstr[4] \"\"\nmsgstr[5] \"\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" (أكثر تطابقًا للاستعلام الخاص بك)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"مشغول\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"\"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \"\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"تعذر إنشاء مقبس استماع\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"الشركة\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"البلد\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"رسالة\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"اتصال\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"إل_غاء\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"تلقائي\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"وكيل المستخدم\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"الاسم\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"البريد الإلكتروني\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"بحث\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_بحث\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"تم قطع الاتصال بالخادم\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"تعذر الاتصال\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"تعذر إنشاء سياق SSL\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"\"\n"
  },
  {
    "path": "po/cs.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Jakub Adam <jakub.adam@ktknet.cz>, 2011-2013,2015-2018\n# Stefan Becker <chemobejk@gmail.com>, 2011\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-20 16:38+0000\\n\"\n\"Last-Translator: Jakub Adam <jakub.adam@ktknet.cz>\\n\"\n\"Language-Team: Czech (http://www.transifex.com/stefanb/pidgin-sipe/language/cs/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: cs\\n\"\n\"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"Nepodařilo se ověřit přihlašovací údaje na serveru\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"Selhal požadavek na certifikát od %s\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"Nebylo zadáno URI služby poskytující certifikáty\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"Nepodařilo se ověřit přihlašovací údaje na serveru\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"Zvoleno nekompatibilní autentizační schéma\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"Následující server odmítl připojení: %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"bez udání důvodu\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"Uživatel %s nenalezen. Prosím kontaktujte svého administrátora\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"SIP není povolen pro cílové URI nebo neexistuje\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"Služba není dostupná: %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"Přijatá zpráva je poškozená\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"Přijatý podpis zprávy je neplatný\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"%s chce spustit prezentaci\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"Přijmout\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"Odmítnout\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"Problém při sdílení plochy\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"Nastavený klient vzdálené plochy není podporován.\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"Nepodařilo se připojit ke vzdálené ploše\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"Nelze vytvořit RDP server.\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"Nelze nastavit parametry RDP serveru.\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"Nelze spustit RDP server.\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"Sdílím plochu s: %s\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"Ukončit prezentaci\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"Nelze zahájit sdílení plochy\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"Celá plocha\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"Monitor k nasdílení\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"Mobilní telefon\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"Stav\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Kalendář\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"Schůzka v\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"Schůzka o\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"Poznámka \\\"mimo kancelář\\\"\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"Poznámka\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"Úroveň přístupu\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"Nalezen %d kontakt%s:\"\nmsgstr[1] \"Nalezeny %d kontakty%s:\"\nmsgstr[2] \"Nalezeno %d kontaktů%s:\"\nmsgstr[3] \"Nalezeno %d kontaktů%s:\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" (další shody s dotazem)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"Žádné kontakty nebyly nalezeny\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"Nemohu zobrazit výsledky hledání.\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"Vyhledání kontaktu selhalo\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"Chybný vyhledávací dotaz\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"Učinit vedoucím '%s'\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"Odstranit z '%s'\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"Pozvat do '%s'\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"Nový chat\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"Telefon do práce\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Domů\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"Jiný telefon\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"Vlastní1\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"Odeslat e-mail...\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"Odebrat kontrolu nad plochou\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"Předat kontrolu nad plochou\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"Sdílet plochu\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Volný\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"Nezávazně zaneprázdněn\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Zaneprázdněn\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"Mimo kancelář\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"není znám stav kontaktu\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"Právě %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"Příštích 8 hodin není v práci\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s dalších 8 hodin\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"Není v práci\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s do %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s. Pracovní doba mu končí %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s. %s v %.2d:%.2d\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"Požadavek na certifikát od %s selhal\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"Požadavek na Web ticket od %s selhal\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"Chat #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"Nepodařilo se připojit ke konferenci\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"Nezdařilo se nalézt URI konference na této stránce:\\n\\n%s\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\\\"%s\\\" není platná adresa konference\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"Zadány neúplné údaje o konferenci\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\\n\\nProtože tento klient nebyl přeložen se zapnutou podporou audiohovoru, pokud se připojíte, budete moci ostatní účastníky kontaktovat pouze pomocí textových zpráv.\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"vás chce přizvat ke konferenčnímu hovoru%s\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"Tato konference již není uzamčená. Mohou se připojovat další účastníci.\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"Tato konference je uzamčená. Dokud tomu tak je, nikdo další se do ní nemůže připojit.\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"Byl jste od této konference odpojen.\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"Údaje pro připojení telefonem\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"Telefonní číslo\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"ID konference\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"URL konference\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"Organizátor\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"Alternativní telefonní čísla\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"Plugin třetí strany poskytující rozšířenou verzi SIP/SIMPLE, používanou v různých produktech.\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"Domovská stránka\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"Uživatelská podpora\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"Diskuzní forum s pomocí\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"Nahlásit problémy\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"Sledování nahlášených chyb\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"Překlady\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"Licence\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"Prosím pomozte přeložit SIPE do vašeho mateřského jazyka\"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \"použitím pohodlného webového rozhraní\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"Autoři\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"Překlad do češtiny (cs): psilo a Jakub Adam\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"Uživatelské jméno pro SIP Exchange obsahuje neplatné znaky\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"Uživatelské jméno musí být platné SIP URI\\nNapříklad: uzivatel@spolecnost.cz\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"Pokud není povoleno jednotné přihlašování (Single Sign-On), je nutné zadat heslo\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"E-mailová adresa musí mít správný formát nebo zůstat nevyplněná\\nNapříklad: uzivatel@spolecnost.cz\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"Uživatelské jméno služby SIP Exchange obsahuje mezery\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"URL e-mailové služby musí být ve správném tvaru nebo zůstat nevyplněné\\nNapříklad: https://exchange.corp.com/EWS/Exchange.asmx\\nNapříklad: https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"Místo\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"Selhalo čtení ze socketu\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"Obdržený šifrovací klíč nemá správnou délku \"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"Obdržený hashovací klíč nemá správnou délku \"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"Soket pro naslouchání nelze vytvořit\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"Došlo k chybě\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"Problém při vytváření spojení\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"Selhal zápis do socketu\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"Skutečná velikost souboru se liší od udávané.\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"Obdržený MAC je poškozený\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"Obdržený soubor je poškozený\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"Nepodařilo se zahájit přenos souboru\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"Selhala autentizace při přenosu souboru\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"Nedostatek paměti\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Ostatní kontakty\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"Proxy server pro skupinový chat je chybný:\\n\\n\\t%s\\n\\nOpravte prosím nastavení vašeho účtu.\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"Nelze nalézt server pro skupinový chat!\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"Tato zpráva nebyla doručena do místnosti „%s“\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"Chyba při načítání seznamu místností\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"Chyba při připojování k místnosti\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"Pozvat uživatele %s se nezdařilo\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"Obdržena zpráva s nerozpoznaným obsahem od uživatele %s\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"Nelze vytvořit datový proud\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"Spojení se nezdařilo navázat v daném čase\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"Požadavek nebyl zpracován v daném čase\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"Volaný uživatel neodpovídá\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"Hovor nelze spojit\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"Nastavení šifrování na straně kontaktu není kompatibilní s naším\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"Uživatel %s hovor odmítl \"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"Hovor odmítnut\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"Chyba při vytváření audio proudu\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"Chyba při vytváření video proudu\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"Připojit ke konferenčnímu hovoru\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"Tento server nepodporuje konferenční hovory.\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"Chybné telefonní číslo\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"Služba zkušební hovor není k dispozici.\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"Uživatel nedostupný\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s si nepřeje být vyrušován\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"Uživatel %s je nedostupný\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"Nepodporovaný formát média\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"Problém se spojením\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"Problém při čtení dat\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"už jsi přihlášen(a) z jiného místa\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"uživatel je zakázán\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"uživatel přesunut\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"Zablokováno\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"Osobní\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"Team\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Společnost\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"Veřejný\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"Neznámý\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"Odebrat nastavení\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"Lidé v mé společnosti\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"Lidé v doménách propojených s mou společností\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"Lidé ve veřejných doménách\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"Lidé v %s\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"Přidat další doménu...\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"Online nápověda...\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"Přístupové skupiny\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Neaktivní\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"Zaneprázdněn\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Za chvíli budu zpět\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"Na obědě\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"Telefonuji\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"Na konferenci\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"Na schůzce\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"Pouze urgentní záležitosti\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"Prezentuji\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"Nelze odebírat informace o přítomnosti uživatelů!\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"Některé kontakty se proto budou trvale jevit jako nedostupné.\\n\\nProsím zkontroluje jestli váš seznam kontaktů neobsahuje neplatná SIP URI.\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"Nelze inicializovat jednotné úložiště kontaktů (UCS)!\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"Nepodařilo se nalézt server Exchange pomocí výchozího nastavení emailu, seznam kontaktů nebude proto fungovat.\\n\\nBude potřeba vyplnit parametry emailu v nastavení účtu.\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"Nepodařilo se nalézt server Exchange pomocí parametrů emailu v nastavení účtu, seznam kontaktů nebude proto fungovat.\\n\\nProsím opravte své nastavení emailu.\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"Vaše zpráva nebo pozvánka nebyla doručena, pravděpodobně obsahuje hypertextový odkaz nebo jiný obsah, který administrátor zablokoval.\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"Tato zpráva nebyla uživateli %s doručena, služba není dostupná\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"Tato zpráva nebyla uživateli %s doručena, jeden nebo více uživatelů nechce být vyrušováno\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"Tato zpráva nebyla uživateli %s doručena, jeden nebo více uživatelů nepodporuje tento typ zprávy\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"Tato zpráva nebyla uživateli %s doručena, jeden nebo více uživatelů není dostupno\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Zobrazit jméno\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"Funkce\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"Město\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"Stát\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"Kancelář\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"Země\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"Telefon do práce\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"E-mailová adresa\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"WWW stránka\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"Přezdívka\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"Jméno zařízení\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"ty\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"Doména\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"Přidat doménu\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"Přidat\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"Zrušit\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"Zkopírovat do\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Zamknout\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Odemknout\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"Zobrazit prezentaci\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"Přístupové údaje\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"_URI:\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"Uživatelé\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"Pozvat do „%s“\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"Soukromá\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"Logovaná\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"Popisek\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"Téma konverzace: %s\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Zpráva\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"Připojování\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"Je vyžadováno heslo\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"uzivatel@spolecnost.cz\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"Telefonní číslo\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"Volat na telefonní číslo\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"_Volat\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"_Storno\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"Adresa konference\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"Nebo\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"Email organizátora\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"ID konference\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"Připojit ke konferenci\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"Připojit k naplánované konferenci\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"Zadejte adresu konference, kterou jste obdrželi v pozvánce.\\n\\nPlatné adresy bývají ve tvaru:\\nmeet:sip:uzivatel@spolecnost.cz;gruu;opaque=app:conf:focus:id:abcdef1234\\nconf:sip:uzivatel@spolecnost.cz;gruu;opaque=app:conf:focus:id:abcdef1234\\nnebo\\nhttps://meet.spolecnost.cz/uzivatel/abcdef1234\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"_Připojit\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"Zveřejňování informací z kalendáře bylo zakázáno\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"O SIPE pluginu...\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"Hledání kontaktů...\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"Volat na telefonní číslo...\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"Zkušební hovor\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"Připojit k naplánované konferenci...\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"Znovu zveřejnit kalendář\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"Obnovit stav\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Server[:Port]\\n(pro automatické zjištění nevyplňujte)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"Typ spojení\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Automaticky\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"Protokol SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"Protokol TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"Uživatelský agent\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"Ověřovací schéma\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"Kerberos\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Použít Single Sign-On\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"Nezveřejňovat informace z mého kalendáře\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"Stahovat fotografie uživatelů z webu\\n(potenciálně nebezpečné)\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"URL e-mailové služby\\n(pro automatické zjištění nevyplňujte)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"E-mailová adresa\\n(liší-li se od SIP adresy)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"Uživatelské jméno pro e-mail\\n(liší-li se od uživatelského jména)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"Heslo pro e-mail\\n(liší-li se od hesla pro komunikátor)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"Proxy server pro skupinový chat\\n spolecnost.com nebo uzivatel@spolecnost.com\\n(nechte prázdné pro odvození z uživatelského jména)\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"Klient vzdálené plochy\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"Šifrování hovorů\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"Podle politiky serveru\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"Vždy\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"Volitelně\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"Nikdy\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"Přihlašovací jméno\\n   uzivatel  nebo  DOMENA\\\\uzivatel  nebo\\n   uzivatel@spolecnost.cz\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"Jméno uživatele\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"Název\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"E-mailová adresa\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"Jméno\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Příjmení\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"SIP ID\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Hledat\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"Hledat kontakt\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"Zadejte informaci o osobě, kterou si přejete najít. Prázdná pole budou ignorována.\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_Hledat\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"Chyba čtení\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"Došlo k odpojení serveru.\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"Spojení nelze navázat\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"Kontext protokolu SSL se nepodařilo vytvořit.\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"Nemohu vytvořit socket\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"Chyba zápisu\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"OK\"\n"
  },
  {
    "path": "po/da.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Joe Hansen <joedalton2@yahoo.dk>, 2013,2015-2018\n# Stefan Becker <chemobejk@gmail.com>, 2011\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-11-08 07:32+0000\\n\"\n\"Last-Translator: Joe Hansen <joedalton2@yahoo.dk>\\n\"\n\"Language-Team: Danish (http://www.transifex.com/stefanb/pidgin-sipe/language/da/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: da\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"Kunne ikke godkende til serveren\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"Kan ikke anmode om certifikat fra %s\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"Ingen URI for certifikatprovisioningtjeneste tilbudt\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"Godkendelse mislykkedes\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"Inkompatibelt godkendelsesskema valgt\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"Du er blevet afvist af serveren: %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"ingen årsag angivet\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"Ikke fundt: %s. Kontakt venligst din administrator\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"SIP er enten ikke aktiveret for destinations-URI'en eller den findes ikke\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"Tjenesten er ikke tilgængelig: %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"Ødelagt besked modtaget\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"Ugyldig meddelelsessignatur modtaget\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"%s ønsker at starte præsentation\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"Accepter\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"Afvis\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"Programdelingsfejl\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"Ukendt ekstern skrivebordsklient konfigureret.\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"Kunne ikke forbinde programdeling\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"Kunne ikke oprette RDP-server.\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"Kunne ikke initialisere RDP-server.\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"Kunne ikke starte RDP-server.\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"Deler skrivebord med %s\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"Stop præsentation\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"Kunne ikke initialisere programdeling\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"Hele skrivebordet\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"Skærm at dele\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"Mobil\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"Status\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Kalender\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"Møde i\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"Møde om\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"Væk fra kontoret-note\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"Note\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"Adgangsniveau\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"Fandt %d kontakt%s:\"\nmsgstr[1] \"Fandt %d kontakter%s:\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" (mere stemte med din forespørgsel)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"Ingen kontakter fundet\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"Kunne ikke vise søgeresultaterne\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"Kontaktsøgning mislykkedes\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"Ugyldig kontaktsøgningsforespørgsel\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"Gør »%s« til leder\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"Fjern fra »%s«\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"Inviter til »%s\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"Ny snak (chat)\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"Arbejde\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Hjem\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"Andet\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"Tilpasset1\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"Send e-post ...\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"Overtag skrivebordskontrol\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"Giv skrivebordskontrol\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"Del mit skrivebord\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Fri\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"Foreløbig\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Optaget\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"Væk fra kontoret\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"Ingen data\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"I øjeblikket %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"Uden for arbejdstid de næste 8 timer\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s for de næste 8 timer\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"Arbejder ikke\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s indtil %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s. Uden for arbejdstid kl. %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s. %s kl. %.2d:%.2d\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"Certifikatforespørgsel til %s mislykkedes\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"Netbilletforespørgsel til %s mislykkedes\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"Snak #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"Kunne ikke slutte til konferencen\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"Kan ikke finde en konference-URI på denne side:\\n\\n%s\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"»%s« er ikke en gyldig konference-URI\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"Ufuldstændig konferenceinformation\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\\n\\nDa denne klient ikke blev kompileret med understøttelse af stemmekald (voice call), vil du kun kunne kontakte de andre deltagere via IM-session, såfremt du accepterer dette.\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"ønsker at invitere dig til et konferencekald%s\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"Denne konference er ikke længere låst. Yderligere deltagere kan nu slutte sig til.\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"Denne konference er låst. Ingen andre kan slutte sig til konferencen mens den er låst.\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"Du er blevet frakoblet fra denne konference.\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"Opkaldsinfo\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"Nummer\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"Konference-id\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"Mødehenvisning\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"Organisator\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"Alternative opkaldsnumre\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"Et tredjepartudvidelsesmodul der implementerer en udvidet version af SIP/SIMPLe brug af diverse produkter\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"Hjemmeside\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"Hjælp\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"Hjælpeforum\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"Rapporter problemer\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"Fejlrapporter\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"Oversættelser\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"Licens\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"Hjælp os venligst med at oversætte SIPE til dit sprog via\"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \"bruger praktisk netgrænseflade\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"Forfattere\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"Oprindelige tekster på engelsk (en): SIPE-udviklere\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"SIP Exchange-brugernavn indeholder ugyldige tegn\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"Brugernavn skal være en gyldig SIP URI\\nEksempel: bruger@firma.com\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"Adgangskode er krævet når Single Sign-On ikke er aktiveret\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"E-postadresse skal være gyldig hvis angivet\\nEksempel: bruger@firma.com\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"SIP Exchange-brugernavn indeholder mellemrum\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"E-posttjenestens adresse skal være gyldig hvis angivet\\nEksempel: https://exchange.corp.com/EWS/Exchange.asmx\\nEksempel: https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"Sted:\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"Sokkellæsning mislykkedes\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"Modtaget krypteringsnøgler har forkert størrelse.\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"Modtaget hash-nøgle har forkert størrelse.\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"Kunne ikke oprette lyttende sokkel\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"Der opstod en fejl\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"Der opstod en fejl under oprettelse af datastrøm\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"Sokkelskrivning mislykkedes\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"Fuld størrelse er anderledes end den annoncerede værdi.\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"Modtaget MAC er ødelagt\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"Modtaget fil er ødelagt\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"Initialisering af filoverførsel mislykkedes.\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"Godkendelse for filoverførsel mislykkedes.\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"Ikke nok hukommelse\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Andre kontakter\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"Group Chat Proxy-indstilling er forkert:\\n\\n\\t%s\\n\\nOpdater venligst din konto.\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"Kunne ikke finde Group Chat-server!\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"Denne besked blev ikke leveret til snakkerum (chat) »%s«\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"Fejl ved indhentelse af rumliste\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"Kunne ikke slutte til snakkerum (chat)\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"Kunne ikke invitere %s\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"Modtog en besked med ukendt indhold fra %s\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"Kunne ikke oprette strøm\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"Forbindelse fik tidsudløb\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"Forespørgsel fik tidsudløb\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"Opkald kunne ikke besvares\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"Kunne ikke etablere et opkald\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"Krypteringsindstillinger for modpart er ikke kompatible med vores.\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"Bruger %s afviste kald\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"Kald afvist\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"Fejl under oprettelse af lydstrøm\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"Fejl ved oprettelse af videostrøm\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"Gå til konferencekald\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"Konferencekald er ikke understøttet på denne server.\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"Ugyldigt telefonnummer\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"Audio Test Service er ikke tilgængelig.\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"Bruger utilgængelig\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s ønsker ikke at blive forstyrret\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"Bruger %s er ikke tilgængelig\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"Medietype er ikke understøttet\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"Mediefejl\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"Der opstod en fejl under læsning fra strøm\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"du er allerede indregistreret på et andet sted\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"bruger deaktiveret\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"bruger flyttet\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"Blokeret\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"Personlig\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"Hold\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Firma\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"Offentlig\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"Ukendt\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"Fjern specifikation\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"Folk i mit firma\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"Folk i domæner forbundet med mit firma\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"Folk i offentlige domæner\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"Folk i %s\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"Tilføj et nyt domæne ...\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"Hjælp på nettet ...\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"Tilgå grupper\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Inaktiv\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"Optaget-ledig\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Er snart tilbage\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"Væk til frokost\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"Optaget på telefonen\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"Til konference\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"I møde\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"Kun vigtige afbrydelser\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"Præsenterer\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"Presence-abonnement mislykkedes!\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"En eller flere venner vil derfor permanent blive vist frakoblet.\\n\\nKontroller at der ikke er ødelagte SIP URI'er i din kontaktliste.\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"Initialisering af UCS mislykkedes!\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"Kunne ikke finde en Exchangeserver med standardindstillinger for e-post. Derfor vil kontaktlisten ikke fungere.\\n\\nDu skal angive indstillinger for e-post i kontoopsætningen.\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"Kunne ikke finde en Exchangeserver med indstillinger for e-post i kontoopsætningen. Derfor vil kontaktlisten ikke fungere.\\n\\nRet venligst dine indstillinger for e-post.\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"Din besked eller invitation blev ikke leveret, muligvis fordi den indeholder et hyperlink eller andet indhold som systemadministratoren har blokeret.\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"Denne besked blev ikke leveret til %s, da tjenesten ikke er tilgængelig\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"Denne besked blev ikke leveret til %s da en eller flere modtager ikke ønskede at blive afbrudt\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"Denne besked blev ikke leveret til %s da en eller flere af modtagerne ikke understøtter denne beskedtype\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"Denne besked blev ikke leveret til %s da en eller flere modtagere er frakoblede\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Vist navn\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"Stilling\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"By\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"Stat\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"Kontor\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"Land\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"Forretningstelefon\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"E-postadresse\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"Side\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"Alias\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"Enhed\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"dig\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"Domæne\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"Tilføj nyt domæne\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"Tilføj\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"Afbryd\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"Kopier til\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Lås\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Åbn\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"Vis præsentation\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"Info om mødepunkt\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"_URI:\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"Brugere\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"Inviter\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"Privat\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"Log\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"Beskrivelse\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"Konversationsemne: %s\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Besked\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"Forbinder\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"Adgangskode krævet\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"bruger@firma.com\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"Telefonnummer\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"Foretag opkald til telefonnummer\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"_Opkald\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"_Afbryd\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"Mødested\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"Alternativt\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"Organisators e-post\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"Møde-id\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"Slut til konference\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"Slut til planlagt konference\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"Indtast mødestedsstreng du modtog i invitationen.\\n\\nGyldigt sted vil ligne\\nmeet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nconf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\neller\\nhttps://meet.company.com/someone/abcdef1234\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"_Tilslut\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"Udgivelse af kalenderinformation er blevet deaktiveret\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"Om SIPE-udvidelsesmodul ...\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"Kontaktsøgning ...\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"Foretag opkald til et telefonnummer ...\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"Testkald\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"Slut til planlagt konference ...\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"Genudsend kalender\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"Nulstil status\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Server[:Port]\\n(tom for automatisk registrering)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"Forbindelsestype\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Auto\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"Brugeragent\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"Godkendelsesskema\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"Kerberos\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Brug Single Sign-On\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"Udgiv ikke min kalenderinformation\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"Vis profilbilleder fra nettet\\n(kan være farligt)\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"E-posttjenestens adresse\\n(tom for automatisk registrering)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"E-postadresse\\n(hvis forskellig fra brugernavn)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"E-postlogind\\n(hvis forskellig fra logind)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"Adgangskode for e-post\\n(hvis forskellig fra adgangskode)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"Group Chat Proxy\\nfirma.com eller bruger@firma.com\\n(tom hvis brugernavn skal bruges)\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"Ekstern skrivebordsklient\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"Mediekryptering\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"Overhold serverpolitik\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"Altid\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"Valgfrit\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"Deaktiveret\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"Logind\\n   bruger eller DOMÆNE\\\\bruger eller\\n   bruger@firma.com\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"Brugernavn\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"Navn\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"E-post\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"Fornavn\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Efternavn\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"SIP-ID\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Søg\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"Søg efter kontakt\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"Indtast informationen for personen du ønsker at finde. Tomme felter vil blive ignoreret.\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_Søg\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"Læsefejl\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"Server har afbrudt forbindelsen\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"Kunne ikke forbinde\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"Kunne ikke oprette SSL-kontekst\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"Kunne ikke oprette sokkel\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"Skrivefejl\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"O.k.\"\n"
  },
  {
    "path": "po/de.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Stefan Becker <chemobejk@gmail.com>, 2011-2013,2015-2018\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 16:23+0000\\n\"\n\"Last-Translator: Stefan Becker <chemobejk@gmail.com>\\n\"\n\"Language-Team: German (http://www.transifex.com/stefanb/pidgin-sipe/language/de/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: de\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"Authentifizierung mit dem Server fehlgeschlagen.\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"Kann kein Zertifikat bei %s anfordern\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"Keine URI für den Zertifikationsbereitstellungsdienst angegeben\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"Authentifizierung fehlgeschlagen\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"Sie haben ein nicht unterstütztes Authentizierungsverfahren konfiguriert\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"Sie wurden vom Server '%s' abgewiesen\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"Kein Grund angegeben\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"Konnte %s nicht finden. Bitte wenden Sie sich an Ihren Systemadministrator\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"entweder wurde der SIP-Service nicht für die Ziel-URI aktiviert oder die URI existiert nicht\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"Der Dienst %s ist nicht verfügbar\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"Beschädigte Nachricht empfangen\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"Ungültige Nachrichtensignatur erhalten\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"%s will mit der Präsentation beginnen\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"Akzeptieren\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"Ablehnen\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"Anwendungsfreigabefehler\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"Unbekannter Remote-Desktop-Client konfiguriert\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"Verbindung zur Anwendungsfreigabe fehlgeschlagen\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"Konnte den RDP-Server nicht erstellen\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"Konnte den RDP-Server nicht initialisieren\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"Konnte den RDP-Server nicht starten\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"Teile den Desktop mit %s\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"Beende Präsentation\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"Konnte Desktop-Teilen nicht initialisieren\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"Den ganzen Desktop\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"Welchen Bildschirm teilen\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"Telefon (Handy)\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"Status\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Kalender\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"Besprechungsraum\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"Besprechungsthema\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"Abwesenheitsnotiz\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"Notiz\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"Sichtbarkeitsniveau\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"%d Kontakt%s gefunden:\"\nmsgstr[1] \"%d Kontakte%s gefunden:\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" (es gab noch mehr Ergebnisse für Ihrer Suche)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"Es wurden keine Einträge gefunden\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"Kann die Suchergebnisse nicht anzeigen\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"Suche im Adressbuch fehlgeschlagen\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"Ungültige Suchanfrage\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"Ernenne zum Leiter der Konferenz '%s'\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"Aus der Konferenz '%s' entfernen\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"Zu der Konferenz '%s' einladen\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"Neue Konferenz\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"Telefon (Arbeit)\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Telefon (Privat)\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"Telefon\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"Telefon (benutzerdefiniert)\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"Sende E-Mail...\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"Übernehme Kontrolle über den Deskop\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"Erlaube Kontrolle des Desktops\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"Teile meinen Desktop\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Verfügbar\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"Vorläufig\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Beschäftigt\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"Nicht im Büro\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"Keine Angaben\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"Zurzeit %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"Nicht im Büro in den nächsten 8 Stunden\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s für die nächsten 8 Stunden\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"Freizeit\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s bis %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s. Verlässt das Büro um %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s. %s ab %.2d:%.2d\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"Zertifikatsanforderung bei %s fehlgeschlagen\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"Web-Ticket-Anforderung bei %s fehlgeschlagen\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"Konferenz #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"Konnte der Konferenz nicht beitreten\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"Kann keine Konferenz-Kennung auf der folgenden Seite finden:\\n\\n%s\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\\\"%s\\\" ist keine gültige Konferenz-Kennung\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"Die Konferenz-Daten sind unvollständig \"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\\n\\nWenn sie die Einladung akzeptieren, dann können Sie sich mit den anderen Teilnehmer nur via Textmitteilungen unterhalten, da Ihr Client keinen Voice Call unterstützt.\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"möchte Sie zu der Telefonkonferenz %s einladen\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"Diese Konferenz ist nicht mehr gesperrt. Andere Teilnehmer können jetzt ungehindert daran teilnehmen.\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"Diese Konferenz ist gesperrt. Niemand kann ihr beitreten solange sie gesperrt ist.\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"Sie haben die Verbindung mit dieser Konferenz verloren.\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"Einwahlinformation\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"Telefonnummer\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"Konferenz-Kennung\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"Veranstaltungs-URL\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"Organisator\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"Alternative Einwahlnummern\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"Ein Third-Party Plugin, das die von den folgenden Produkten eingesetzte erweiterte Version des SIP/SIMPLE-Protokolls implementiert\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"Homepage\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"Forum\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"Hilfe-Forum (in Englisch)\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"Probleme melden im\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"Bugtracker\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"Übersetzungen\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"Lizenz\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"Wir bitten um Ihre Hilfe bei der Anpassung von SIPE an weitere Sprachen. Auf \"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \" gibt es dazu eine einfach zu erlernende Web-Benutzerschnittstelle\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"Autoren\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"Deutsche Übersetzung (de): Stefan Becker\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"Der SIP-Exchange-Benutzername enthält unerlaubte Zeichen\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"Benutzername sollte eine gültige SIP URI sein\\nBeispiel: benutzer@domäne.com\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"Sie müssen ein Passwort setzen, wenn Sie Single Sign-On nicht aktiviert haben\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"Falls angegeben, dann sollte der Benutzername eine gültige SIP URI sein\\nBeispiel: benutzer@domäne.com\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"Der SIP-Exchange-Benutzername enthält Leerzeichen\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"Die Email-Service-URL muss gültig sein, wenn angegeben\\nBeispiel 1: https://exchange.corp.com/EWS/Exchange.asmx\\nBeispiel 2: https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"Veranstaltungsort:\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"Netzwerklesefehler\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"Der empfangene Chiffrierschlüssel hat die falsche Länge.\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"Der empfangene Hash-Schlüssel hat die falsche Länge.\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"Konnte den Listen-Socket nicht erstellen\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"Ein Fehler ist aufgetreten\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"Es konnte keine Daten-Verbindung hergestellt werden\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"Netzwerksendefehler\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"Die Dateigröße entspricht nicht dem vorgegebenen Wert.\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"Die empfangene MAC-Adresse ist fehlerhaft\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"Die empfangene Datei ist fehlerhaft\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"Der Start der Dateiübertragung ist fehlgeschlagen.\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"Die Authentifizierung für die Dateiübertragung ist fehlgeschlagen.\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"Es ist nicht genügend freier Speicher verfügbar.\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Andere Kontakte\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"Die Einstellung für den Group Chat Proxy ist falsch:\\n\\n\\t%s\\n\\nBitte korrigieren Sie Ihr Konto.\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"Der Group Chat Server konnte nicht gefunden werden!\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"Diese Nachricht konnte nicht an den Chatraum '%s' zugestellt werden\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"Fehler beim Empfangen der Raumliste\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"Fehler beim Betreten des Chatraums\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"Kann den Benutzer %s nicht einladen\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"Es wurde eine Nachricht von %s mit unbekanntem Inhalt empfangen\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"Konnte die Daten-Verbindung nicht erstellen\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"Zeitüberschreitung beim Aufbau der Verbindung\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"Zeitüberschreitung bei der Anfrage\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"Der Anruf konnte nicht beantwortet werden\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"Der Anruf ist fehlgeschlagen\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"Es konnten keine gemeinsamen Verschlüsselungseinstellungen mit der Gegenseite ausgehandelt werden.\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"Der Benutzer %s hat den Anruf abgewiesen\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"Der Anruf wurde abgewiesen\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"Es konnte keine Audio-Verbindung hergestellt werden\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"Es konnte keine Video-Verbindung hergestellt werden\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"Telefonkonferenz beitreten\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"Telefonkonferenzen werden von diesem Server nicht unterstützt.\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"Ungültige Telefonnummer\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"Der Audio Test-Service ist nicht verfügbar\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"Der Benutzer ist nicht verfügbar\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s möchte nicht gestört werden\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"Der Benutzer %s ist nicht verfügbar\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"Medientyp wird nicht unterstützt\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"Fehler in der Daten-Verbindung\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"Fehler beim Lesen von der Daten-Verbindung\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"Sie haben sich bereits von einem anderen Ort aus angemeldet\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"Benutzer ist gesperrt\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"Benutzer ist auf einen neuen Server umgezogen\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"Unsichtbar\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"Persönlich\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"Arbeitsgruppe\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Firma\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"Öffentlich\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"Unbekannt\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"Zurücksetzen\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"Personen in meiner Firma\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"Personen in Domänen, die mit meiner Firma verbunden sind\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"Personen in öffentlichen Domänen\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"Personen in %s\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"Neue Domäne hinzufügen...\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"Online-Hilfe...\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"Zugriffsgruppen\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Inaktiv\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"Nicht verfügbar\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Bin gleich zurück\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"Zur Mittagspause\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"In einem Telefonat\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"In einer Konferenz\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"In einer Besprechung\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"Bitte nur in dringenden Fällen stören\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"Präsentiert\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"Registrierung für Präsenz-Informationen fehlgeschlagen!\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"Ein oder mehrere Kontakte werden daher als offline angezeigt.\\n\\nBitte überprüfen Sie, dass sich keine fehlerhafte SIP URI in Ihrer Kontakte-Liste befindet.\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"UCS-Initialisierung fehlgeschlagen! \"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"Mit den Standard E-Mail Einstellungen konnte kein Exchange-Server gefunden werden. Daher wird die Kontakte-Liste nicht funktionieren.\\n\\nSie müssen Ihrem Konto E-Mail Einstellungen hinzufügen.\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"Mit den E-Mail Einstellungen Ihres Kontos konnte kein Exchange-Server gefunden werden. Daher wird die Kontakte-Liste nicht funktionieren.\\n\\nBitte überprüfen Sie die E-Mail Einstellungen in Ihrem Konto.\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"Ihre Mitteilung oder Einladung konnte nicht zugestellt werden. Vermutlich enthält sie einen Hyperlink oder irgendeinen anderen Inhalt, der von dem Systemadministrator gesperrt wurde.\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"Diese Nachricht konnte nicht an %s zugestellt werden, da der Dienst nicht verfügbar ist\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"Diese Nachricht konnte nicht an %s zugestellt werden, da ein oder mehrere Empfänger nicht gestört werden wollen\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"Diese Nachricht konnte nicht an %s zugestellt werden, da ein oder mehrere Empfänger diesen Nachrichtentyp nicht unterstützen\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"Diese Nachricht konnte nicht an %s zugestellt werden, da ein oder mehrere Empfänger offline sind\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Display-Name\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"Beruf\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"Stadt\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"Provinz/Bundesland\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"Büro\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"Land\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"Geschäftstelefon\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"E-Mail Adresse\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"Standort\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"Alias\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"Gerät\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"Sie\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"Domäne\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"Neue Domäne hinzufügen\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"Hinzufügen\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"Abbrechen\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"Kopiere nach\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Sperren\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Freigeben\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"Präsentation anzeigen\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"Veranstaltungsinformation\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"_URI:\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"Teilnehmer\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"Einladung\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"Privat\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"Mitschnitt\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"Beschreibung\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"Gesprächsthema: %s\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Nachricht\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"Verbindungsaufbau\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"Sie müssen ein Password setzen\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"benutzer@domäne.com\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"Telefonnummer\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"Telefonnummer anrufen\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"_Anrufen\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"_Abbrechen\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"Konferenz-Bezeichner\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"Alternative Veranstaltungsort\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"E-Mail des Organisators\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"Veranstaltungs-Kennung\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"Konferenz beitreten\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"Geplanter Konferenz beitreten\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"Geben Sie bitte die Konferenz-Kennung ein, die sie in der Einladung erhalten haben.\\n\\nGültige Kennungen sehen wie folgt aus\\nmeet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nconf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\noder\\nhttps://meet.company.com/someone/abcdef1234\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"_Beitreten\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"Sie haben die Veröffentlichung ihrer Kalenderdaten unterdrückt\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"Informationen zum SIPE Plugin...\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"Suche im Adressbuch...\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"Telefonnummer anrufen...\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"Test-Anruf\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"Geplanter Konferenz beitreten...\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"Ihre Kalenderdaten erneut veröffentlichen\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"Den Status zurücksetzen\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Server[:Port]\\n(Bitte leer lassen für voreingestellten Server)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"Verbindungstyp\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Auto\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"Benutzeragent\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"Authentizierungsschema\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"Kerberos\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Benutze Single Sign-On\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"Meine Kalenderdaten sollen nicht veröffentlicht werden\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"Profilbilder aus dem Internet anzeigen\\n(potenziell gefährlich)\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"E-Mail-Service URL\\n(Bitte leer lassen für voreingestellten Dienst)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"E-Mail Adresse\\n(falls sie sich vom Benutzernamen unterscheiden sollte)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"E-Mail Anmeldenamen\\n(falls er sich vom Anmeldenamen unterscheiden sollte)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"E-Mail Passwort\\n(falls die Passwörter unterschiedlich sein sollten)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"Group Chat Proxy\\n   domäne.com  oder  benutzer@domäne.com\\n(Bitte leer lassen um vom Benutzernamen abzuleiten)\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"Remote-Desktop-Client\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"Audio/Video-Verschlüsselung\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"Server-Vorgabe\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"Immer\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"Optional\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"Abgeschaltet\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"Anmeldenamen\\nBenutzer oder Domäne\\\\Benutzer oder\\n   benutzer@domäne.com\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"Benutzername\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"Name\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"E-Mail\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"Vorname\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Nachname\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"SIP-Identität\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Suchen\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"Suche im Adressbuch\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"Geben Sie bitte die Informationen für die Person ein, die Sie im Adressbuch suchen möchten. Leere Felder werden ignoriert.\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_Suchen\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"Lesefehler\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"Der Server hat die Verbindung abgebrochen\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"Es konnte keine Verbindung hergestellt werden\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"Es konnte kein SSL-Kontext erstellt werden\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"Es konnte kein Socket erzeugt werden\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"Schreib-Fehler\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"OK\"\n"
  },
  {
    "path": "po/el.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 16:09+0000\\n\"\n\"Last-Translator: Stefan Becker <chemobejk@gmail.com>\\n\"\n\"Language-Team: Greek (http://www.transifex.com/stefanb/pidgin-sipe/language/el/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: el\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"\"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \"\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"\"\n"
  },
  {
    "path": "po/es.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Anibal Avelar <debianmx@gmail.com>, 2011, 2012\n# Maximiliano Rico <maximilian.rico@gmail.com>, 2016-2017\n# Sebastian Muniz <basurerosebita@gmail.com>, 2013\n# Stefan Becker <chemobejk@gmail.com>, 2011\n# Ubay Manuel González Díaz <ubay.glezdiaz@gmail.com>, 2018\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-29 08:50+0000\\n\"\n\"Last-Translator: Ubay Manuel González Díaz <ubay.glezdiaz@gmail.com>\\n\"\n\"Language-Team: Spanish (http://www.transifex.com/stefanb/pidgin-sipe/language/es/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: es\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"Fallo de autenticación con el servidor\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"No se puede solicitar certificado de %s\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"No URI para el certificado de servicio de aprovisionamiento\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"Fallo de autenticación\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"Seleccionado un esquema de autenticación incompatible\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"El servidor %s ha rechazado al usuario\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"no se indicó una razón\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"No encontró: %s. Por favor, contacte a su administrador\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"SIP está deshabilitado para la URI de destino o la URI no existe\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"Servicio no disponible: %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"El mensaje recibido está corrupto\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"Recibida firma de mensaje no valida\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"%squiere empezar a presentar\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"Aceptar\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"Declinado\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"Error al compartir\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"configuración de cliente de escritorio remota desconocida\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"No se pudo compartir\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"No se ha podido crear el servidor RDP.\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"No se ha podido inicializar el servidor RDP.\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"No se ha podido iniciar el servidor RDP.\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"Compartiendo escritorio con %s\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"Detener presentación\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"No se pudo inicializar el uso compartido\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"Todo el escritorio\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"Monitor para compartir\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"Móvil\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"Status\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Calendario\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"Reunión en\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"Reunión sobre\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"Mensaje de ausencia\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"Nota\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"Nivel de Acceso\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"Se ha encontrado %d contacto%s:\"\nmsgstr[1] \"Se han encontrado %d contactos%s:\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" (hay más que coinciden con la consulta)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"No se encontrarón contactos\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"Imposible mostrar los resultados de la búsqueda.\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"Búsqueda de contacto fallo\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"Búsqueda de contact inválida\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"Hazte líder de '%s'\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"Eliminar de '%s'\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"Invitar a '%s'\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"Chat nuevo\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"Trabajo\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Inicio\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"Otro\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"Custom1\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"Enviar E-Mail...\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"Tomar control del escritorio\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"Dar control del escritorio\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"Compartir mi escritorio\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Libre\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"Tentativo\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Ocupado\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"Fuera de la oficina\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"Sin datos\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"Actualmente %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"Fuera de horas de trabajo durante las siguientes 8 horas\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s durante las siguientes 8 horas\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"Sin trabajar\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s hasta que %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s. Fuera del trabajo a las %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s. %s en %.2d:%.2d\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"Petición de certificado a %s fallo\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"Petición de Web ticket a %s fallo\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"Conversación #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"Fallo para unirse a la conferencia\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"No se puede encontrar una URI de conferencia en esta página:\\n\\n%s\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"La URI \\\"%s\\\" no es una conferencia válida\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"La Información de conferencia es inconmpleta\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\\n\\nComo el cliente no fue compilado con soporte de llamadas de voz, sí tú la aceptas, tú debes ser capaz de contactar a los demás participantes sólo vía sesión de IM.\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"te invita a una conferencia %s\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"Esta conferencia ya no esta bloqueada. Mas participantes pueden unirse.\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"Esta conferencia esta bloqueada. Nadie mas puede unirse a la conferencia mientras esté bloqueada.\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"Usted ha sido desconectado de esta conferencia.\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"Información de discado\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"Número\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"ID de conferencia\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"enlace a la reunión\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"Organizador\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"Números de discado alternativos\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"Un plugin desarrollado por terceros que implementa una versión del protocolo SIP/SIMPLE usado por varios productos.\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"Página principal\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"Soporte\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"Foro de Ayuda\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"Reportar Problemas\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"Seguimiento de Errores\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"Traducciones\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"Licencia\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"Por favor, ayudanos a traducir SIPE para su lenguaje nativo en\"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \"usando una interfaz web\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"Autores\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"Textos originales en Ingles (en): Desarrolladores de SIPE\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"El nombre de usuario de SIP Exchange contiene caracteres inválidos\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"El nombre de usuario debe ser una URI SIP válida\\nEjemplo: usuario@dominio.com\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"La contraseña es requerida cuando  la Autenticación única  no se encuentra habilitada.\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"Si se proporciona una direccion de correo, debe ser válida\\nEjemplo: usuario@dominio.com\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"El nombre de cuenta SIP Exchange contiene espacios\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"Si se proporciona una URL para el servicio de correo debe ser válida\\nEjemplo: https://exchange.corp.com/EWS/Exchange.asmx\\nEjemplo: https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"Localización:\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"Fallo en lectura de socket\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"La clave cifrada recibida tiene un tamaño erroneo.\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"La clave hash recibida tiene un tamaño incorrecto.\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"Imposible crear el socket de escucha\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"Ocurrió un error\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"Error creando el flujo de datos\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"Fallo en escritura de socket\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"El tamaño del archivo es diferente del valor anunciado.\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"La dirección MAC está corrupta\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"El archivo recibido está corrupto\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"Fallo en la inicializacion de la transferencia de archivos\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"Fallo en la autenticación de la transferencia de archivos\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"Memoria insuficiente\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Otros contactos\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"Proxy de chat de grupo is incorrecto:\\n\\n»%s\\n\\nPor favor, actualiza tu cuenta.\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"No encontró servidor de Chat de Grupo\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"Este mensaje no fue enviado a la sala chat '%s'\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"Error en recuperación de lista de salas\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"Error al unirse a la sala de chat\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"Fallo invitando a %s\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"Se recibió un mensaje con contenido no reconocido de %s\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"No se pudo crear la secuencia\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"Tiempo de conexión agotado\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"Tiempo de espera agotado\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"La llamada no ha podido ser contestada\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"Imposible establecer la llamada\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"La configuración de encriptación del destino es incompatible con la nuestra.\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"El usuario %s rechazo la llamada\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"Llamada rechazada\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"Error creando el flujo de audio\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"Error creando el flujo de video\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"Unirse a llamada de conferencia\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"Las llamadas en conferencia no son soportadas en este servidor.\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"Número de teléfono inválido\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"El servicio para Test de Audio no se encuentra disponible\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"Usuario no disponible\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s no quiere ser molestado\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"El usuario %s no esta disponible\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"medio no soportado.\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"Error media\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"Error leyendo desde flujo\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"ya está conectado desde otro lugar\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"usuario deshabilitado\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"usuario movido\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"Bloqueado\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"Personal\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"Equipo\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Compañía\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"Publico\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"Desconocido\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"No especificado\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"Personas de mi compañia\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"Personas de dominios conectados con mi compañia\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"Personas de dominios públicos\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"Persona en %s\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"Agregar nuevo dominio...\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"Ayuda en linea ...\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"Agregar grupos\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Inactivo\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"Ocupado-Inactivo\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Regreso en un momento\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"He salido a comer\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"En una llamada\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"En una conferencia\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"En una reunión\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"Sólo interrupciones urgentes\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"Presentando\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"falló la suscripción\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"Uno o más contactos se van a mostrar offline de manera permanente. Por favor chequea que no haya URIs SIP corrompidas en tu lista de contactos\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"Fallo en inicialización UCS!\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"No se pudo encontrar un servidor Exchange con la configuración de Email por defecto, por lo tanto la lista de contactos no va a funcionar.\\n\\nNecesitará configurar un correo electrónico en la configuración de la cuenta.\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"No se pudo encontrar un servidor Exchange con la configuración de Email provista en la instalación de la cuenta, por lo tanto la lista de contactos no va a funcionar.\\n\\nPor favor corrija su configuración de Email\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"Su mensaje o invitación no fue enviado, posiblemente porque contiene un hipervínculo u otro contenido que el administrador del sistema ha bloqueado.\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"Este mensaje no fue enviado a %s porque el servicio no esta disponible\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"Este mensaje no fue enviado a %s porque uno o mas recipientes no desean ser molestados\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"Este mensaje no fue enviado a %s porque uno o mas recipientes no soportan este tipo de mensajes\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"Este mensaje no fue enviado a %s porque uno o mas recipientes desconectados\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Nombre completo\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"Puesto\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"Ciudad\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"Estado\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"Oficina\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"País\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"Telefono de oficina\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"Dirección de E-Mail\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"Sitio\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"Alias\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"Dispositivo\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"tu\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"Dominio\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"Agregar nuevo dominio\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"Agregar\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"Cancelar\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"Copiar a\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Bloquear\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Desbloquear\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"Mostrar presentación\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"Información de la reunión\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"_URI:\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"Usuarios\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"Invitar\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"Privado\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"Log\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"Descripción\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"Tema de conversación: %s\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Mensaje\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"Conectando\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"Contraseña requerida\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"usuario@dominio.com\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"Número de teléfono\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"Llamar a un número de teléfono\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"_Llamada\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"_Cancelar\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"Lugar de la reunión\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"Altenativamente\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"Email del organizador\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"ID de reunión\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"Unirse a la conferencia\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"Unirse a la conferencia programada\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"Introduzca el URI de reunión que recibió en la inviación.⏎\\nUn URI válido es de la forma:⏎\\nmeet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234⏎\\nconf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234⏎\\no sinó⏎\\nhttps://meet.company.com/someone/abcdef1234\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"_Unirse\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"La publicacion de la información de calendario ha sido deshabilitada\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"Acerca del plugin SIPE\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"Búsqueda de Contactos...\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"Llamar a un número de teléfono...\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"Llamada de prueba\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"Unirse a la conferencia programada ...\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"Republicar calendario\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"Reinicializar status\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Server[:Port]\\n(dejar vacio para autoconfiguración)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"Tipo de conexión\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Automático\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"User Agent\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"Esquema de autenticación\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"Kerberos\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Usar Single Sign-On\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"No publique mi información de calendario\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"Mostrar imágen de perfil desde la web\\n(potencialmente peligroso)\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"URL de servicios de E-mail\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"Dirección de E-mail\\n(si es diferente al Usuario)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"Login de E-mail\\n(si es diferente al Login)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"Clave de E-mail\\n(si es diferente  a la clave)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"Proxy para Chat de Grupo\\n   company.com o user@company.com\\n  (dejar vácio para dejar el Username)\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"Cliente de escritorio remoto\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"Encriptación media\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"Seguir política del servidor\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"Siempre\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"Opcional\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"Deshabilitado\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"Login\\n   usuario o DOMINIO\\\\usuario o\\n   usuario@dominio.com\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"Usuario\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"Nombre\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"Correo electrónico\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"Nombre\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Apellidos\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"SIP ID\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Búsqueda\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"Buscar un contacto\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"Introduce la información de la persona que usted desea encontrar. Los campos en blanco serán ignorados.\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_Buscar\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"Error de lectura\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"El servidor ha desconectado\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"No es posible conectar\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"No es posible crear el contexto SSL\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"No se pudo crear el socket\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"Error de escritura\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"Ok\"\n"
  },
  {
    "path": "po/fi.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Stefan Becker <chemobejk@gmail.com>, 2011\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 16:09+0000\\n\"\n\"Last-Translator: Stefan Becker <chemobejk@gmail.com>\\n\"\n\"Language-Team: Finnish (http://www.transifex.com/stefanb/pidgin-sipe/language/fi/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: fi\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"Varmentaminen epäonnistui palvelimelle\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"Palvelu ei käytettävissä: %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"Virheellinen viesti allekirjoitus vastaanotettu\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"Tila\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Kalenteri\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"Uusi ryhmäkeskustelu\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Kotisivu\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"Lähetä sähköpostia...\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Vapaa\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"Alustavia\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Varattu\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"Ei tietoja\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"Nykyään %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s seuraavan 8 tuntia\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"Ei töissä\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"Ryhmäkeskustelu #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"\"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \"\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"SIP Exchange:n käyttäjätunnus sisältää virheellisiä merkkejä\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"Käyttäjätunnus on voimassa SIP-URI\\nEsimerkki: user@company.com\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Muut yhteystiedot\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"Epäonnistui kutsua %s\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"Vastaanotettu viesti tuntemattomat sisältö %s:lta\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"Olet jo kirjautunut toisesta paikasta\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"käyttäjä siirretty\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Yritys\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Inaktiivinen\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Kohta takaisin\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"Tämä viesti ei ole toimitettu %s:lle, koska palvelu ei ole käytettävissä\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"Tämä viesti ei ole toimitettu %s:lle, koska yhdelle tai useammalle vastaanottajalle ei halua tulla häirityksi\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"Tämä viesti ei ole toimitettu %s:lle, koska yhdelle tai useammalle vastaanottajalle on offline-tilassa\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Näyttönimen\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"Työnimike\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"Kaupunki\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"Osavaltio\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"Maa\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"Sähköpostiosoite\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"Lempinimi\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"sinä\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Lukitse\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Aukaista\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Viesti\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"_Peru\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Automaattinen\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Käytä Single Sign-On\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"Käyttäjätunnus\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"Nimi\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"Sähköposti\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"Etunimi\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Sukunimi\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Etsi\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_Etsi\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"Ei voitu yhdistää\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"Ei voitu luoda socket\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"\"\n"
  },
  {
    "path": "po/fr.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Clément SABATTIÉ, 2019\n# djano <djanoiup@yahoo.fr>, 2011\n# Jeremy Brown, 2017\n# Julien Rabier <>, 2012\n# Kevin C <kdc_net@laposte.net>, 2013,2015-2016\n# Stefan Becker <chemobejk@gmail.com>, 2011,2013\n# lkppo, 2012-2013\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2019-03-07 14:05+0000\\n\"\n\"Last-Translator: Clément SABATTIÉ\\n\"\n\"Language-Team: French (http://www.transifex.com/stefanb/pidgin-sipe/language/fr/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: fr\\n\"\n\"Plural-Forms: nplurals=2; plural=(n > 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"Échec de l'authentification sur le serveur\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"Impossible de demander le certificat auprès de %s\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"Aucun URI fourni pour le service de certification\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"Échec de l'authentification\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"Le protocole d'authentification choisi est incompatible\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"Vous avez été rejeté par le serveur : %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"pas de raison donnée\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"%s introuvable. Merci de contacter l'Administrateur\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"SIP n'est pas activé pour l'URI de destination ou bien l'URI n'existe pas.\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"Service indisponible : %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"Message corrompu reçu\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"La signature de message reçue est invalide\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"%s veut débuter une présentation\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"Accepter\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"Refuser\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"Erreur de partage d'application\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"Client de bureau à distance inconnu configuré\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"Échec de connexion au partage d'application\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"Impossible de créer le serveur RDP\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"Impossible d'initialiser le serveur RDP\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"Impossible de démarrer le serveur RDP\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"Présenter son bureau avec %s\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"Arrêter de présenter\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"Ne peut pas démarrer le partage\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"Bureau entier\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"Écran à partager\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"Portable\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"État\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Calendrier\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"Réunion en cours\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"Réunion au sujet de\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"Message d'absent du bureau\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"Note\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"Niveau d'accès\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"%d contact%s trouvé :\"\nmsgstr[1] \"%d contacts%s trouvés :\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" (il y avait plus de résultats pour votre requête)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"Aucun contact trouvé\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"Impossible d'afficher les résultats de la recherche\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"Échec de la recherche de contact\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"Requête de recherche de contact invalide\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"Promouvoir à la tête de '%s'\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"Supprimer de '%s'\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"Inviter à '%s'\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"Nouvelle discussion\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"Travail\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Accueil\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"Autres\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"Personnalisé1\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"Envoyer un courriel…\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"Prendre le contrôle du bureau\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"Donner le contrôle du bureau\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"Présenter mon bureau\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Disponible\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"En réunion acceptée provisoirement\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Occupé\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"Absent du bureau\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"Aucune donnée\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"Actuellement %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"En repos pour les 8 prochaines heures\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s pour les 8 prochaines heures\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"En repos\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s jusqu'à %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s. En repos à partir de %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s. %s à %.2d:%.2d\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"La demande de certificat auprès de %s a échoué\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"La demande de ticket web auprès de %s a échoué\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"Chat #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"Impossible de rejoindre la conférence\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"Impossible de trouver un URI de conférence sur cette page:\\n\\n%s\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\\\"%s\\\" n'est pas un URI de conférence valide\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"Les informations fournies pour la conférence sont incomplètes\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\\n\\nPuisque ce client n'a pas été compilé avec la prise en charge des appels vocaux, si vous acceptez, vous pourrez seulement contacter les autres participants par chat.\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"veut vous inviter à un appel conférence%s\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"Cette conférence n'est plus verrouillée. D'autres participants peuvent maintenant se joindre à celle-ci.\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"Cette conférence est verrouillée. Personne d'autres ne peut participer à celle-ci tant qu'elle le sera.\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"Vous avez été déconnecté de cette conférence.\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"Information de connexion\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"Numéro\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"ID de la conférence\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"Lien de la réunion\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"Organisateur\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"Numéros alternatifs\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"Une extension tierce qui implémente une version étendue de SIP / SIMPLE utilisée par divers produits.\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"Page d'accueil\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"Support\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"Forum d'aide\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"Signaler un problème\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"Système de suivi des bogues\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"Traductions\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"Licence\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"Merci de nous aider à traduire SIPE dans votre langue maternelle ici \"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \" utilisation d'une interface web conviviale\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"Auteurs\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"Textes originaux en Anglais (en) : développeurs SIPE\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"Le nom d'utilisateur SIP Exchange contient des caractères invalides\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"Le nom d'utilisateur doit être une URI SIP valide\\nExemple : utilisateur@company.com\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"Un mot de passe est requis lorsque l'authentification unique (SSO) n'est pas activée\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"Si l'adresse email est fournie, elle doit être valide\\nExemple : utilisateur@company.com\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"Les noms SIP Exchange ne peuvent contenir d'espace\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"L'URL des services email doit être valide si elle est indiquée\\nExemple : https://exchange.corp.com/EWS/Exchange.asmx\\nExemple : https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"Lieu :\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"La lecture du socket a échoué\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"La clef de chiffrement reçue a une longueur incorrecte.\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"La clef de hachage reçue a une longueur incorrecte.\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"Impossible de créer le socket d'écoute\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"Une erreur est survenue\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"Erreur lors de la création du flux de données\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"L'écriture du socket a échoué\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"La taille du fichier est différente de la valeur annoncée.\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"L’adresse MAC reçue est corrompue\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"Le fichier reçu est corrompu\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"L'initialisation du transfert de fichier a échoué.\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"L'authentification du transfert de fichier a échoué.\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"Plus de mémoire.\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Autres contacts\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"Le paramètre du proxy de chat de groupe est incorrect :\\n\\n\\t%s\\n\\nMettez votre compte à jour s'il vous plaît.\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"Impossible de trouver le serveur de chat de groupe !\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"Ce message n'a pu être remis au canal de chat '%s'\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"Impossible de récupérer la liste des canaux de chat.\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"Impossible de rejoindre le canal de chat.\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"L'invitation de %s a échoué\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"Message reçu de %s avec un contenu non reconnaissable\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"Impossible de créer le flux\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"Connexion tombée en time out\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"Requête tombée en time out\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"L'appel n'a pas abouti\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"Impossible d'établir un appel\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"Les paramètres d'encodage du correspondant sont incompatibles avec les votres.\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"L'utilisateur %s a rejeté l'appel\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"Appel rejeté\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"Impossible de créer le flux audio\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"Impossible de créer le flux vidéo\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"Rejoindre l'appel en conférence\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"Les audio-conférences ne sont pas supportées sur ce serveur.\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"Numéro de téléphone invalide\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"Le service de test audio est indisponible.\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"Utilisateur indisponible\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s ne veut pas être dérangé\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"L'utilisateur %s est indisponible\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"Format non supporté\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"Erreur du média\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"Erreur lors de la lecture des informations du flux\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"Vous êtes déjà connecté depuis un autre lieu\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"Utilisateur désactivé\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"Utilisateur déplacé\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"Bloqué\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"Personnel\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"Équipe\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Société\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"Public\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"Inconnu\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"Non spécifié\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"Personnes de ma société\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"Personnes provenant de domaines connectés à mon entreprise\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"Personnes de la fonction publique\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"Personnes à %s\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"Ajouter un nouveau domaine...\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"Aide en ligne…\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"Groupes d'accès\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Inactif\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"Occupé-inactif\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Bientôt de retour\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"Sorti manger\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"Au téléphone\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"En conférence\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"En réunion\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"Urgences uniquement\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"En présentation\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"Échec de l'alerte de présence \"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"Un ou plusieurs de vos amis seront marqué comme hors ligne de manière permanente.\\n\\nMerci de vérifier qu'il n'y a pas de URIs SIP corrompues dans votre liste de contact.\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"L'initialisation UCS a échoué !\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"Ne parvient pas à se connecter à un serveur Exchange avec les paramètres mail par défaut. La liste de contacts ne sera pas disponible.\\n\\nVous devez saisir des paramètres de mail dans la configuration du compte.\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"Ne parvient pas à se connecter à un serveur Exchange avec les paramètres mail saisis dans la configuration du compte. La liste de contacts ne sera pas disponible.\\n\\nMerci de corriger ces paramètres.\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"Votre message ou invitation n'a pas pu être remis, peut-être parce qu'il contient un lien hypertexte ou un autre contenu que l'administrateur a bloqué.\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"Ce message n'a pas pu être remis à %s parce que le service n'est pas disponible.\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"Ce message n'a pas pu être remis à %s parce qu'un ou plusieurs destinataires ne veulent pas être dérangés\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"Ce message n'a pas pu être remis à %s parce qu'un ou plusieurs destinataires n'acceptent pas ce type de message\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"Ce message n'a pas pu être remis à %s parce qu'un ou plusieurs destinataires ne sont pas connectés\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Afficher le nom\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"Intitulé du poste\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"Ville\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"Pays\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"Bureau\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"Pays\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"Téléphone professionnel\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"Adresse email\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"Site\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"Pseudonyme\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"Appareil\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"vous\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"Domaine\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"Ajouter un nouveau domaine\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"Ajouter\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"Annuler\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"Copier vers\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Bloquer\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Débloquer\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"Afficher la présentation\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"Information d'entrée en réunion\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"_URI :\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"Utilisateurs\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"Inviter\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"Privé\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"Journal\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"Description\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"Sujet de conversation : %s\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Message\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"Connexion\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"Mot de passe nécessaire\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"utilisateur@company.com\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"Numéro de téléphone\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"Composer un numéro de téléphone\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"_Appeler\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"_Annuler\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"Lieu de réunion\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"Alternativement\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"E-mail de l'organisateur\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"ID de la réunion\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"Rejoindre la conférence\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"Rejoindre une conférence planifiée\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"Saisissez l'adresse de conversation que vous avez reçu dans l'invitation.\\n\\nUne adresse valide devrait ressembler à ceci :\\nmeet:sip:quelquun@societeexemple.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nconf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nou cela :\\nhttps://rencontrer.societeexemple.com/quelquun/abcdef1234\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"_Rejoindre\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"La publication du calendrier a été désactivée\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"À propos de l'extension SIPE...\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"Recherche du contact...\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"Composer un numéro de téléphone…\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"Test d'appel\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"Rejoindre la conférence planifiée...\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"Calendrier républicain\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"Réinitialiser l'état\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Serveur[:Port]\\n(laisser vide pour utiliser la découverte automatique)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"Type de connection\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Auto\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL / TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"Agent utilisateur\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"Schéma d'authentification\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"Kerberos\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Utiliser l'authentification unique\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"Ne pas rendre public mon calendrier\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"Voir la photo de profil depuis Internet\\n(potentiellement dangereux)\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"URL des services email\\n(laisser vide pour utiliser la découverte automatique)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"Adresse email\\n(si différente du nom d'utilisateur)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"Email de login\\n(si différent du login)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"Mot de passe de l'email\\n(si différent du mot de passe)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"Proxy pour le chat en groupe\\n   entreprise.com  or  utilisateur@entreprise.com\\n(laisser vide pour le déterminer à partir du nom d'utilisateur)\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"Client de bureau à distance \"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"Chiffrement du média\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"Respecte la politique du serveur\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"Toujours\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"Optionnel\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"Désactivé\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"Login\\n   utilisateur  ou  DOMAINE\\\\utilisateur  ou\\n   utilisateur@entreprise.com\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"Nom d'utilisateur\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"Nom\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"Adresse électronique\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"Prénom\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Nom\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"SIP ID\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Rechercher\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"Rechercher un contact\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"Entrez les critères de recherche de la personne. Les champs vides seront ignorés.\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_Rechercher\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"Erreur de lecture\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"Le serveur s'est déconnecté\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"Impossible de se connecter\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"Impossible de créer un contexte SSL\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"Impossible de créer le socket\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"Erreur d'écriture\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"Ok\"\n"
  },
  {
    "path": "po/fr_CA.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 16:09+0000\\n\"\n\"Last-Translator: Stefan Becker <chemobejk@gmail.com>\\n\"\n\"Language-Team: French (Canada) (http://www.transifex.com/stefanb/pidgin-sipe/language/fr_CA/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: fr_CA\\n\"\n\"Plural-Forms: nplurals=2; plural=(n > 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"\"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \"\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"\"\n"
  },
  {
    "path": "po/hi.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# krupa.sagar <gksreddy@eml.cc>, 2014\n# Stefan Becker <chemobejk@gmail.com>, 2011\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 16:09+0000\\n\"\n\"Last-Translator: Stefan Becker <chemobejk@gmail.com>\\n\"\n\"Language-Team: Hindi (http://www.transifex.com/stefanb/pidgin-sipe/language/hi/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: hi\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"सर्वर से प्रमाणीकरण करने मे विफल \"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"प्रमाणीकरण विफल \"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"असंगत प्रमाणीकरण व्यवस्था चुना गया \"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"%s: आप सर्वर द्वारा अस्वीकार किये गए\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"कोई कारण नहीं दिया गया \"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"%s मौजूद नहीं। अपने व्यवस्थापक से संपर्क करें \"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"अवैध संदेश हस्ताक्षर प्राप्त\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"स्थिति \"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"कैलेंडर \"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"खोज परिणामों को प्रदर्शित करने में तकलीफ़ \"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"अवैध कांटेक्ट खोज क्वेरी \"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"नया चैट \"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"होम \"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"अन्य \"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"ईमेल भेजिए ...  \"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"व्यस्त \"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"छुट्टी पे \"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"होम पेज \"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"सपोर्ट \"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"सहायता फोरम \"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"समस्याए बतायें \"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"बग ट्रैकर \"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"अनुवाद \"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"लाइसेंस \"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"SIPE को अपनी भाषा में अनुवाद करने में हमारी मदद करें - यहाँ पे \"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \"सुविधाजनक वेब इंटरफ़ेस का उपयोग करके \"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"ऑथर्स \"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"स्थान \"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"सॉकेट से पढ़ना नाकाम हुआ \"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"सॉकेट को लिखने में तकलीफ \"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"अन्य कांटेक्ट \"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"%s को आमंत्रित करने मे विफल \"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"ऑडियो टेस्ट सेवा उपलब्ध नही है \"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \" \"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"यूज़र डिसेबल किये गए \"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"यूज़र मूव किये गए \"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"ब्लॉक किये गए \"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"व्यक्तिगत \"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"टीम \"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"संस्था\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"सार्वजानिक \"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"अनजाना \"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"मेरे संस्था के लोग \"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"निष्क्रिय\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"व्यस्त-निष्क्रिय\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"थोड़ी ही देर में वापस \"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"भोजन विराम में \"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"कॉल में \"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"कॉन्फरेंस में \"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"मीटिंग में \"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"सिर्फ़ ज़रूरी रुकावटें ही \"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"दिखने वाला नाम \"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"शहर \"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"राज्य \"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"दफ्तर \"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"देश\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"ईमेल एड्रेस \"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"आप \"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"संदेश\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"पासवर्ड ज़रूरी\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"फ़ोन नंबर \"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"किसी फ़ोन नंबर पर कॉल करें \"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"_कॉल \"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"किसी फ़ोन नंबर पर कॉल करें ...\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"टेस्ट कॉल \"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"यूज़र नाम \"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"नाम\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"ईमेल \"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"सर्वर ने कनेक्शन तोड़ा\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"कनेक्ट नहीं कर पाया\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"\"\n"
  },
  {
    "path": "po/hu.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Laszlo Pal <vlad@vlad.hu>, 2012-2013,2016\n# Stefan Becker <chemobejk@gmail.com>, 2011,2013\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 16:09+0000\\n\"\n\"Last-Translator: Stefan Becker <chemobejk@gmail.com>\\n\"\n\"Language-Team: Hungarian (http://www.transifex.com/stefanb/pidgin-sipe/language/hu/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: hu\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"Sikertelen bejelentkezés a szerverre\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"Nem sikerült tanúsítványt kérni %s tól/től\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"Nincs megadva URI a tanúsítvány elosztó szolgáltatáshoz\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"Sikertelen azonosítás\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"Nem kompatibilis azonosítási módszer\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"A(z) %s kiszolgáló elutasította\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"nincs ok megadva\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"%s nem található. Kérem lépjen kapcsolatba a rendszergazdával\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"A SIP protokol nincs engedélyezve a megadott URI-n, vagy az URI nem létezik <http://hu.wikipedia.org/wiki/URI>\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"A(z) %s szolgáltatás nem érhető el\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"Sérült üzenet\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"Érvénytelen üzenetaláírás érkezett\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"Elfogad\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"Elutasít\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"Mobil\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"Állapot\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Naptár\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"Megbeszélés -kor\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"Megbeszélés témája\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"\\\"Irodán kívül\\\" üzenet\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"Megjegyzés\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"Hozzáférési szint\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"Found %d contacts%s:\"\nmsgstr[1] \"Found %d contacts%s:\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" (a keresésnek több találata van)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"Nem található kapcsolat\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"A keresési eredményeket nem lehet megjeleníteni\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"Kapcsolat keresés meghiúsult\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"Érvénytelen kapcsolat keresési lekérdezés\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"Vezetőnek jelölés %s -hez/höz\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"Eltávolítás %s -ból/ből\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"Meghívás %s -ba/be\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"Új társalgás\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"Munka\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Kiindulás\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"Más\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"Speciális1\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"E-mail küldése...\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Szabad\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"Kétséges\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Elfoglalt\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"Irodán kívül\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"Nincs információ\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"Jelenleg %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"A következő 8 órában nem dolgozik\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"A következő nyolc órában %s\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"Nem dolgozik\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s %.2d:%.2d -ig\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s. \\\"Nem dolgozik\\\" %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s. %s %.2d:%.2d -kor\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"Nem sikerült a tanúsítvány igénylés %s-hez \"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"Nem sikerült Web-es jegyet nyitni %s-hez\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"Beszélgetés #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"Nem sikerült csatlakozni a konferenciához\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"A megadott oldalon konferencia URI nem található:\\n\\n\\n%s\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"A következő URI nem valós konferencia cím: \\\"%s\\\"\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"Hiányos konferencia információ\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\\n\\nMivel ez a kliens hang-hívás támogatás nélkül került lefordításra, ezért amennyiben elfogadja a másik féllel csak azonnali üzeneteket fog tudni váltani.\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"A megbeszélés feloldva, további résztvevők csatlakozhatnak\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"Megbeszélés lezárva, további résztvevők nem csatlakozhatnak\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"Ön eltávolításra került a megbeszélésről\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"Behívási adatok\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"Szám\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"Konferencia azonosító\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"A megbeszéléshez tartozó link\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"Szervező\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"Alternatív behívószám\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"Egy harmadik féltől származó kiegészítés amely a SIP/SIMPLE egy kiterjesztett verzióját valósítja meg.\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"Web-lap\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"Támogatás\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"Közösségi segítség\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"Problémák jelzése\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"Hiba követés\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"Fordítás\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"Licensz\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"Kérem segítse munkánkat a a SIPE fordításával más nyelvekre a következő címen: \"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \"egy könnyen használható web-es interfész használatával\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"Fejlesztők\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"Az eredeti szöveg Angolul (en): SIPE Developers\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"Az Exchange SIP felhasználó név tiltott karaktereket tartalmaz\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"A felhasználó névnek egy valós SIP URI-nak kell lennie⏎\\nmint például \\\"felhasznalo@ceg.hu\\\"\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"A jelszó megadása kötelező amennyiben az Egyszeri bejelentkezés (Single Sign-On) nincs engedélyezve\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"Ha megadott e-mail címet, akkor ennek valósnak kell lennie⏎\\nmint például \\\"felhasznalo@ceg.hu\\\"\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"Az Exchange SIP felhasználó név üres karaktert tartalmaz\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"Az e-mail szolgáltatásokhoz megadott URL-nek valósnak kell lennie⏎\\nPélda 1.: https://exchange.corp.com/EWS/Exchange.asmx⏎ \\nPélda 2.: https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"Helyszín\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"\\\"Socket\\\" olvasási hiba\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"A kapott titkosítási kulcs rossz méretű\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"A kapott \\\"hash\\\" kulcs rossz méretű\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"Nem sikerült létrehozni a figyelő foglalatot\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"Hiba történt\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"Adatfolyam létrehozása sikertelen\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"\\\"Socket\\\" írási hiba\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"A fájl méret különbözik a megadott mérettől\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"A kapott \\\"MAC\\\" érvénytelen\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"A kapott fájl sérült\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"Fájl átvitel indítása meghiúsult\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"Fájl átviteli azonosítás sikertelen\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"Elfogyott a memória\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Egyéb kapcsolatok\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"A csoport-társalgás proxy beállítása érvénytelen:\\n\\n<span class=\\\"whitespace other\\\" title=\\\"Tab\\\">»</span>%s\\n\\nKérem frissítse a fiókbeállításokat\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"A csoport-társalgás szerver nem található\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"Az üzenet továbbítása a %s szobába sikertelen\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"A szoba lista letöltése sikertelen\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"Csatlakozás a szobához sikertelen\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"%s meghívása sikertelen\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"%s értelmezhetetlen tartalmú üzenetet küldött\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"Sikertelen hívás\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"A partner titkosítási beállításai nem egyeznek a mienkkel\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"%s visszautasította a hívást\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"Hívás visszautasítva\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"A hang adatfolyam létrehozása nem sikerült\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"A videó adatfolyam létrehozása nem sikerült\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"Csatlakozás telefon konferenciához\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"A konferenciahívások nem támogatottak ezen a kiszolgálón\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"Érvénytelen telefonszám\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"Hang tesztelési szolgáltatás nem elérhető\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"Felhasználó nem elérhető\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s állapota: \\\"Ne zavarj!\\\"\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"%s állapota: \\\"Nem elérhető\\\"\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"Nem támogatott médiatípus \"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"Média hiba\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"Hiba az adatfolyam olvasásakor\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"Egy másik helyről már be va jelentkezve\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"Felhasználó letiltva\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"Felhasználó áthelyezve\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"Blokkolva\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"Személyes\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"Csapat\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Cég\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"Nyilvános\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"Ismeretlen\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"Mellőz\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"Emberek a cégemnél\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"Emberek a cégemmel kapcsolódott domainekben\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"Emberek a nyílvános domainekben\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"Emberek %s -nál/nél\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"Domain hozzáadása...\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"Online segítség...\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"Hozzáférési csoportok...\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Tétlen\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"Elfoglalt->Tétlen\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Rögtön jön\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"Ebédel\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"Hívásban\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"Telefonkonferenciában\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"Megbeszélésen\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"Csak sürgős esetben elérhető\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"UCS inicializálás sikertelen!\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"Az üzenet vagy meghívó továbbítása sikertelen mivel linket vagy egyéb, az adminisztrátor által letiltott elemet tartalmaz\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"Az üzenet továbbítása %s számára nem lehetséges mivel a szolgáltatás nem elérhető\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"Az üzenet továbbítása %s számára nem lehetséges mivel egy vagy több címzett állapota \\\"Ne zavarj!\\\"\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"Az üzenet továbbítása %s számára nem lehetséges mivel egy vagy több címezett nem támogatja az üzenetek ezen formáját.\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"Az üzenet továbbítása %s számára nem lehetséges mivel egy vagy több címzett ki van jelentkezve.\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Megjelenített név\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"Munkakör\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"Város\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"Állam\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"Iroda\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"Ország\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"Hivatali telefon\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"E-mail cím\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"Telephely\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"Álnév\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"Eszköz\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"Te\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"Domain\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"Új domain hozzáadása\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"Hozzáad\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"Mégsem\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"Másolás...\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Kizár\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Kizárást felold\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"A megbeszélés belépési adatai\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"_URI:\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"Felhasználók\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"Meghívás\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"Magánszféra\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"Napló\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"Leírás\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"A beszélgetés témája: %s\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Üzenet\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"Kapcsolódás\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"Jelszó megadása kötelező\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"user@company.com\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"Telefonszám\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"Telefonszám felhívása\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"_Hívás\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"_Mégse\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"Megbeszélés helyszíne\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"A szervező e-mail címe\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"Megbeszélés azonosítója\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"Kapcsolódás a konferenciához\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"Kapcsolódás tervezett konferenciához\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"Add meg a megbeszélés helyére vonatkozó hivatkozást a meghívóból.\\n\\nEgy valós hivatkozás formátuma valami ehhez hasonló\\nmeet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nor\\nhttps://meet.company.com/someone/abcdef1234\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"_Csatlakozás\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"A naptár információk közzététele letiltva\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"A SIPE kiegészítőről...\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"Kapcsolatok Keresése...\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"Telefonszám felhívása...\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"Teszt hívás\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"Kapcsolódás tervezett konferenciához...\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"A naptár közzététele\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"Állapot alaphelyzetbe\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Server[:Port]⏎\\n(az automatikus kitöltéshez hagyja üresen!)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"Kapcsolat típusa\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Automatikus\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"Felhasználó ügynökprogram\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"Autentikációs séma\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"Kerberos\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Egyszeri-bejelentkezés (SSO) használata\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"Ne publikáld a naptár információkat!\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"E-mail szolgáltatások URI-ja⏎\\n(az automatikus kitöltéshez hagyja üresen!)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"E-mail cím\\n(ha különbözik a felhasználó névtől)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"E-mail bejelentkezési név\\n(ha különbözik a bejelentkezési névtől)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"E-mail jelszó\\n(ha különbözik a jelszótól)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"Csoportos beszélgetés proxy\\nceg.hu  vagy  felhasznalo@ceg.hu\\n(hagyja üresen a felhasználó névből való meghatározáshoz!)\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"Média titkosítás\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"Mindig\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"Opcionális\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"Letiltva\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"Bejelentkezés⏎\\n   \\\"Felhasználó név\\\"  vagy  \\\"DOMAIN\\\\felhasználó név\\\"  vagy\\n   felhasznalo@ceg.hu\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"Felhasználónév\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"Név\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"E-mail\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"Keresztnév\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Vezetéknév\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"SIP azonosító\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Keresés\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"Kapcsolat keresése\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"Adja meg a keresett személy adatait. Az üres mezők figyelmen kívül lesznek hagyva\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_Keresés\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"Olvasási hiba\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"A kiszolgáló bontotta a kapcsolatot\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"Nem sikerült kapcsolódni\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"Az SSL-környezet nem hozható létre\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"Nem tudom létrehozni a \\\"Socket\\\"-et\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"Írási hiba\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"\"\n"
  },
  {
    "path": "po/it.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Saverio <saverio.brancaccio@gmail.com>, 2014\n# Stefan Becker <chemobejk@gmail.com>, 2011\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 16:09+0000\\n\"\n\"Last-Translator: Stefan Becker <chemobejk@gmail.com>\\n\"\n\"Language-Team: Italian (http://www.transifex.com/stefanb/pidgin-sipe/language/it/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: it\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"Errore di autenticazione con il server\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"Impossibile richiedere il certificato da %s\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"Nessun URI fornito per il servizio di rilascio certificati\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"Errore di autenticazione\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"Lo schema di autenticazione scelto è incompatibile.\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"Connessione rifiutata dal server: %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"nessun motivo fornito\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"Non trovato: %s. Contattare l'amministratore\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"SIP non abilitato per la URI di destinazione oppure non esistente\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"Servizio non disponibile:%s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"La firma del messaggio ricevuta non è valida\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"Accetta\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"Rifiuta\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"Mobile\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"Stato\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Calendario\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"Riunione in\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"Riunione su\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"Nota per il Fuori Ufficio\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"Nota\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"Livello di accesso\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"%d contatto%s trovato:\"\nmsgstr[1] \"%d contatti%s trovati:\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" (altri risultati per l'interrogazione)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"Nessun contatto trovato\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"Non è stato possibile mostrare i risultati della ricerca.\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"Impossibile cercare il contatto\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"Criteri non validi per la ricerca del contatto\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"Rendi leader di '%s'\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"Rimuovi da '%s'\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"Invita a '%s'\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"Nuova chat\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"Lavoro\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Home\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"Altro\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"Personalizzato1\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"Spedisci email...\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Libero\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"Incerto\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Occupato\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"Fuori ufficio\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"Nessun dato\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"Attualmente %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"Fuori sede per le prossime 8 ore\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s per le prossime 8 ore\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"Non al lavoro\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s fino a %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s. Fuori dagli orari di lavoro al %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s. %s al %.2d:%.2d\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"La richiesta del certificato a %s non è andata a buon fine\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"La richiesta del web ticket a %s non è andata a buon fine\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"Chat #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"Impossibile collegarsi alla conferenza\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\\\"%s\\\" non è un URI di conferenza valido\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\\n\\nPoichè il client non è stato compilato con il supporto alla chiamata vocale, se si accetta, si potranno contattare gli altri partecipanti solo tramite sessione IM.\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"Questa conference non è più bloccata. Ora possono connnettersi altri partecipanti.\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"Questa conference è bloccata. Nessun altro può partecipare fino a che sarà bloccata.\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"Sei stato disconnesso da questa conferenza\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"Un plugin che implementa una versione estesa di SIP/SIMPLE usato in molti prodotti\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"Pagina principale\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"Supporto\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"Forum di Aiuto\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"Riporta Problemi\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"Bug Tracker\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"Traduzioni\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"Licenza\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"Per favore aiutaci a tradurre SIPI nella tua lingua madra qui in\"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \"usando una comoda interfaccia web\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"Autori\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"Traduzione in Italiano (it): Emanuele Zattin\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"Il nome utente di SIP Exchange contiene caratteri non validi\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"Il nome utente deve essere un SIP URI valido\\nEsempio: utente@azienda.com\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"L'indirizzo email deve essere valido se fornito\\nEsempio: utente@azienda.com\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"Il nome utente di SIP Exchange contiene spazi bianchi\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"Gli URL dei servizi email devono essere validi se inseriti\\nEsempio: https://exchange.corp.com/EWS/Exchange.asmx\\nEsempio: https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"Locazione:\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"Errore di lettura del socket.\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"La chiave di cifratura ricevuta ha una dimensione errata.\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"L' hash ricevuto ha una dimensione errata.\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"Impossibile creare il socket in ascolto\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"Errore di scrittura nel socket\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"Le dimensioni del file sono diverse da quelle attese.\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"Il MAC ricevuto è corrotto.\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"Il file ricevuto è corrotto\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"Errore di inizializzazione nel trasgerimento del file\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"Errore di autenticazione nel trasferimento del file\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"Memoria esaurita\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Altri Contatti\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"L'impostazione del proxy per la chat di gruppo è errata: \\n\\n    %s\\n\\nAggiornare il proprio account.\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"Impossibile trovare un server per la chat di gruppo!\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"Questo messaggio non è stato consegnato alla chat room '%s'\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"Impossibile ricevere la lista delle chat room\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"Impossibile entrare nella chat room\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"Errore nell'invitare %s\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"È stato ricevuto un messaggio con contenuti non riconosciuti da %s\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"Impossibile stabilire una chiamata\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"I settaggi del criptaggio del peer sono incompatibili con i nostri.\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"L'utente %s ha rifiutato la chiamata\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"Chiamata rifiutata\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"Errore durante la creazione dello stream audio\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"Errore durante la creazione dello stream video\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"Partecipa alla chiamata in conferenza\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"Numero di telefono errato\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"Servizio per il test audio non disponibile\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"Utente non disponibile:%s\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s non vuole essere disturbato/a\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"L'utente %s non é disponibile\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"Tipo di supporto non gestito\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"sei giá collegato da un'altra locazione\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"utente disabilitato\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"utente spostato\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"Bloccato\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"Personali\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"Team\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Società\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"Pubblici\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"Sconosciuti\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"Rimuovi\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"Persone nella mia azienda\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"Persone in domini connessi alla mia azienda\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"Persone in domini pubblici\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"Persone in %s\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"Aggiungi nuovo dominio...\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"Aiuto online...\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"Gruppi di accesso\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Inattivo\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"Occupato-Inattivo\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Torno subito\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"A pranzo\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"Al telefono\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"In una conferenza\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"In riunione\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"Solo interruzioni urgenti\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"Il tuo messaggio o invito non è stato recapitato, forse perchè contenente un link o altro che l'amministratore di sistema ha bloccato.\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"Questo messaggio non é stato inoltrato a %s perché il servizio non é disponibile\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"Questo messaggio non é stato inoltrato a %s perché uno e piú destinatari non vogliono essere disturbati\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"Questo messaggio non é stato inoltrato a %s perché uno o piú destinatari non supportano questo tipo di messaggio\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"Questo messaggio non é stato inoltrato a %s perché uno e piú destinatari non sono collegati\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Nome visualizzato\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"Ruolo\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"Città\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"Stato\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"Ufficio\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"Paese\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"Telefono Ufficio\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"Indirizzo Email\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"Sede\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"Alias\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"Periferica\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"tu\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"Dominio\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"Aggiungi un nuovo dominio\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"Aggiungi\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"Annulla\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"Copia in\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Blocca\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Sblocca\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"_URI:\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"Utenti\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"Invita\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"Privato\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"Log\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"Descrizione\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"Oggetto della conversazione: %s\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Messaggio\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"Connessione in corso\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"Password richiesta\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"utente@azienda.com\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"Numero di telefono\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"Chiama un numero telefonico\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"_Chiamata\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"_Annulla\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"Luogo della riunione\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"Partecipa alla conferenza\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"Partecipa  alla conferenza pianificata\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"Inserisci la frase del luogo della riunione che hai ricevuto nell'invito.\\n\\nIl luogo valido sarà quacosa di simile a\\nmeet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nconf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\noppure\\nhttps://meet.company.com/someone/abcdef1234\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"_Partecipa\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"La pubblicazione delle informazioni di calendario è stata disabilitata.\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"Informazioni sul plugin SIPE...\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"Cerca contatto...\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"Chiama il numero telefonico...\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"Chiamata di test\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"Partecipa alla conferenza pianificata...\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"Ripubblica il Calendario\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"Resetta lo stato\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Server[:Porta]\\n(lascia vuoto per auto-discovery)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"Tipo di connessione\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Auto\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"Agente utente\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"Schema per l'autenticazione\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"Kerberos\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Utilizza Sign-On\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"Non pubblicare le mie informazioni di calendario\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"URL Servizio Email\\n(lascia vuoto per ricerca automatica)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"Indirizzo Email\\n(se diverso dallo Username)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"Email login\\n(se diverso da Login)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"Email password\\n(se diversa da Password)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"Proxy della chat di gruppo\\ncompany.com oppure user@company.com\\n(lasciare vuoto per rilevare il proxy dal nome utente) \"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"Login\\n   utente  or  DOMINIO\\\\utente  or\\n   utente@azienda.com\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"Nome utente\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"Nome\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"E-mail\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"Nome\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Cognome\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Ricerca\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"Cerca un contatto\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"Inserisci le informazioni della persona che vuoi trovare. I campi lasciati vuoti saranno ignorati.\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_Cerca\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"Errore di lettura\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"Il server si è disconnesso\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"Impossibile connettersi\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"Impossibile creare il contesto SSL\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"Errore nella creazione del socket\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"Errore di scrittura\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"\"\n"
  },
  {
    "path": "po/ja.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Matthew Duggan <matthew@guarana.org>, 2011,2015\n# Stefan Becker <chemobejk@gmail.com>, 2011\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 16:09+0000\\n\"\n\"Last-Translator: Stefan Becker <chemobejk@gmail.com>\\n\"\n\"Language-Team: Japanese (http://www.transifex.com/stefanb/pidgin-sipe/language/ja/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: ja\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"サーバーに認証できませんでした\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"認証は失敗しました\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"サーバに拒否されました: %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"理由はわかりません\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"サービスが利用できません: %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"受信したメッセージ署名が正しくありません\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"承諾\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"否定\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"携帯\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"状態\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"カレンダー\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"会議室\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"会議課題\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"外出参考\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"メモ\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"アクセスレベル\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"%d連絡先が見つかりました%s:\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" (クエリに一致したものが他にもあります)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"連絡先は見つかりませんでした\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"検索結果は表示できませんでした\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"連絡先検索失敗しました\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"「%s」のリーダーにします\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"「%s」から取り除く\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"「%s」に誘います\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"新しいチャット\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"勤務先\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"自宅\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"その他\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"カスタム１\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"メールを送ります。。。\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"開いている\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"保留\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"取り込み中\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"外出中\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"データなし\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"現在%s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"これから８時間%s\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s、%.2d:%.2dまで\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s。%s、%.2d:%.2dから\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"チャット%d番\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"会議のロックは解除されました。他の人は参加できるようになりました。\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"会議はロックされています。ロックは解除されたまで他の人は参加できません。\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"オンライン会議からログアウトされました\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"ホームページ\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"サポート\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"翻訳\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"ライセンス\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"\"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \"\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"作者\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"ソケット読み込みエラー\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"監視ソケットを生成できませんでした\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"ソケット書き込みエラー\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"メモリー不足\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"その他の連絡先\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"チャットに参加するのを失敗しました\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"%sを招待できませんでした\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"呼び出しは否定されました\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"オンライン会議に参加する\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"ブロックされました\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"パーソナル\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"チーム\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"勤務先\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"一般公開\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"不明\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"指定をなくする\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"%sにいる人々\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"ドメインを追加する。。。\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"オンラインヘルプ。。。\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"一時退席\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"昼休み\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"話し中\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"会談中\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"会議中\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"連絡先はログアウトされた為、%sに送れませんでした\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"市\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"州\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"オフィス\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"国\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"メール宛先\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"デバイス\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"あなた\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"ドメイン\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"ドメインを追加する\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"追加\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"キャンセル\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"コピー\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"ロック\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"ロック解除\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"_URI:\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"ユーザー\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"招待\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"非公開\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"ログ\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"説明\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"メッセージ\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"接続中です\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"パースワードが必要\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"user@company.com\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"電話番号\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"通話(_C)\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"キャンセル(_C)\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"会議場\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"参加(_J)\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"SIPEプラグインについて。。。\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"連絡先検索。。。\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"試験通話\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"ステータスをリセット\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"接続方式\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"自動\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"ユーザエージェント\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"認証方式\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"ケルベロス\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"シングルサインオンを利用する\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"カレンダーを公表しない\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"メール宛先\\n（ログインと異なる場合）\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"メールのログイン\\n（ログインと異なる場合）\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"メールのパスワード\\n（パスワードと異なる場合）\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"ユーザー名\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"名前\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"E-メール\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"名\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"氏\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"SIP ID\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"検索\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"連絡先を検索する\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"検索(_S)\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"読み込みエラー\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"サーバが切断しました\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"接続できませんでした\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"SSLコンテキストを作成できませんでした\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"ソケットを作成できませんでした\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"書き込みエラー\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"\"\n"
  },
  {
    "path": "po/ko.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Stefan Becker <chemobejk@gmail.com>, 2011\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 16:09+0000\\n\"\n\"Last-Translator: Stefan Becker <chemobejk@gmail.com>\\n\"\n\"Language-Team: Korean (http://www.transifex.com/stefanb/pidgin-sipe/language/ko/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: ko\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"서버에서 거부되었습니다. %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"이유가 없습니다.\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"서비스를 이용할 수 없습니다. %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"잘못된 메시지 서명이 수신되었습니다.\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"%d contact%s 찾음:\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" (더 많은 항목이 쿼리와 일치)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"다른 용무 중\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"\"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \"\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"수신 소켓을 생성할 수 없습니다.\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"회사\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"국가\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"메시지\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"연결 중\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"취소(_C)\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"자동\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"사용자 에이전트\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"이름\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"전자 메일\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"검색\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"검색(_S)\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"서버의 연결이 끊겼습니다.\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"연결할 수 없습니다.\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"SSL 컨텍스트를 생성할 수 없습니다.\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"\"\n"
  },
  {
    "path": "po/lt.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Moo, 2016-2018\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 18:45+0000\\n\"\n\"Last-Translator: Moo\\n\"\n\"Language-Team: Lithuanian (http://www.transifex.com/stefanb/pidgin-sipe/language/lt/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: lt\\n\"\n\"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"Nepavyko nustatyti tapatybės serveriui\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"Nepavyksta užklausti liudijimo iš %s\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"Nebuvo pateiktas liudijimų aprūpinimo paslaugos URI\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"Tapatybės nustatymas nepavyko\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"Pasirinkta nesuderinama tapatybės nustatymo schema\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"Serveris jus atmetė: %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"priežastis nenurodyta\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"Nerasta: %s. Prašome susisiekti su savo administratoriumi\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"Arba SIP, skirtas paskirties URI neįjungtas, arbo jo nėra\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"Paslauga neprieinama: %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"Gauta sugadinta žinutė\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"Gautas neteisingas žinutės parašas\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"%s nori pradėti pristatymą\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"Priimti\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"Atmesti\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"Programos bendrinimo klaida\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"Sukonfigūruotas nežinomas nuotolinis darbalaukio klientas.\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"Nepavyko prijungti programos bendrinimą\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"Nepavyko sukurti RDP serverio.\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"Nepavyko inicijuoti RDP serverio.\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"Nepavyko paleisti RDP serverio.\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"Bendrinamas darbalaukis su %s\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"Stabdyti pristatymą\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"Nepavyko inicijuoti programos bendrinimo\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"Visas darbalaukis\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"Monitorius, kurį bendrinti\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"Mobilusis telefonas\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"Būsena\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Kalendorius\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"Susitikimo vieta\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"Susitikimas apie\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"\\\"Nėra biure\\\" raštelis\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"Raštelis\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"Prieigos lygis\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"Rastas %d kontaktas%s:\"\nmsgstr[1] \"Rasti %d kontaktai%s:\"\nmsgstr[2] \"Rasta %d kontaktų%s:\"\nmsgstr[3] \"Rasta %d kontaktų%s:\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" (daugiau atitiko jūsų užklausą)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"Kontaktų nerasta\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"Nepavyksta parodyti paieškos rezultatų\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"Kontaktų paieška nepavyko\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"Neteisinga kontaktų paieškos užklausa\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"Padaryti \\\"%s\\\" lyderiu\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"Šalinti iš \\\"%s\\\"\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"Pakviesti į \\\"%s\\\"\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"Naujas pokalbis\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"Darbas\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Namai\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"Kita\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"Tinkinta1\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"Siųsti el. paštą...\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"Perimti darbalaukio valdymą\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"Suteikti darbalaukio valdymą\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"Bendrinti savo darbalaukį\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Laisvas\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"Preliminariai užimtas\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Užimtas\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"Nėra biure\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"Nėra duomenų\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"Šiuo metu %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"Kitas 8 valandas ne darbe\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s kitas 8 valandas\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"Nedirba\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s iki %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s. Darbo laikas baigiasi %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s. %s %.2d:%.2d\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"%s liudijimo užklausa nepavyko\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"%s saityno bilieto užklausa nepavyko\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"Pokalbis #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"Nepavyko prisijungti prie konferencijos\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"Nepavyksta šiame puslapyje rasti konferencijos URI:\\n\\n%s\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\\\"%s\\\" nėra teisingas konferencijos URI\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"Pateikta ne visa konferencijos informacija\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\\n\\nKadangi šis klientas nebuvo kompiliuotas su balso skambučių palaikymu, jeigu priimsite, jūs galėsite susisiekti su kitais dalyviais tik per žinučių seansą.\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"nori jus pakviesti į konferencinį skambutį%s\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"Ši konferencija daugiau nebeužrakinta. Dabar, papildomi dalyviai gali prisijungti.\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"Ši konferencija yra užrakinta. Niekas negali prisijungti prie konferencijos, kol ji yra užrakinta.\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"Jūs buvote atjungti nuo šios konferencijos.\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"Numerio rinkimo informacija\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"Numeris\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"Konferencijos ID\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"Susitikimo nuoroda\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"Organizatorius\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"Alternatyvūs numerio rinkimo numeriai\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"Trečiosios šalies papildinys, įgyvendinantis įvairių produktų naudojamą išplėstinę SIP/SIMPLE versiją\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"Tinklalapis\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"Palaikymas\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"Pagalbos forumas\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"Pranešti apie klaidas\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"Klaidų seklys\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"Vertimai\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"Licencija\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"Padėkite mums išversti SIPE į jūsų gimtąją kalbą, apsilankydami \"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \" bei naudodamiesi patogia saityno sąsaja\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"Autoriai\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"Lokalizavimas į <Lietuvių> (<lt>): <Moo>\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"SIP Exchange naudotojo varde yra neteisingų simbolių\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"Naudotojo vardas turėtų būti tinkamas SIP URI\\nPavyzdys: naudotojas@kompanija.com\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"Slaptažodis reikalingas, kai nėra įjungtas vieningas prisijungimas (Single Sign-On)\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"Pateikiant el. pašto adresą, jis turi būti teisingas\\nPavyzdys: naudotojas@kompanija.com\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"SIP Exchange naudotojo varde yra tarpų\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"Pateikiant el. pašto paslaugų URL, jis turi būti teisingas\\nPavyzdys: https://exchange.corp.com/EWS/Exchange.asmx\\nPavyzdys: https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"Vieta:\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"Lizdo skaitymas nepavyko\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"Gautas šifravimo raktas yra neteisingo dydžio.\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"Gautas maišos raktas yra neteisingo dydžio.\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"Nepavyko sukurti klausymosi lizdo\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"Įvyko klaida\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"Klaida, kuriant duomenų srautą\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"Lizdo rašymas nepavyko\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"Failo dydis skiriasi nuo skelbiamos reikšmės.\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"Gautas MAC yra sugadintas\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"Gautas failas yra sugadintas\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"Failo persiuntimo inicijavimas nepavyko.\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"Failo persiuntimo tapatybės nustatymas nepavyko.\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"Trūksta atminties\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Kiti kontaktai\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"Grupės pokalbio įgaliotojo serverio nustatymas yra neteisingas:\\n\\n\\t%s\\n\\nPrašome atnaujinti savo paskyrą.\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"Nepavyko rasti grupės pokalbio serverio!\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"Ši žinutė nebuvo pristatyta į pokalbių kambarį \\\"%s\\\"\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"Klaida, gaunant kambarių sąrašą\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"Klaida, prisijungiant prie pokalbių kambario\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"Nepavyko pakviesti %s\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"Gauta žinutė su nepažįstamu turiniu nuo %s\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"Nepavyko sukurti srauto\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"Pasibaigė ryšiui skirtas laikas\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"Pasibaigė užklausai skirtas laikas\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"Skambutis negalėjo būti atsilieptas\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"Nepavyksta užmegzti skambutį\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"Pašnekovo šifravimo nustatymai yra nesuderinami su mūsų.\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"Naudotojas %s atmetė skambutį\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"Skambutis atmestas\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"Klaida, kuriant garso srautą\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"Klaida, kuriant vaizdo srautą\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"Prisijungti prie konferencinio skambučio\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"Konferenciniai skambučiai šiame serveryje nėra palaikomi.\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"Neteisingas telefono numeris\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"Garso bandymo paslauga neprieinama.\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"Naudotojas neprieinamas\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s nenori būti trukdomas(-a)\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"Naudotojas %s yra neprieinamas\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"Nepalaikomas medijos tipas\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"Medijos klaida\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"Klaida, skaitant iš srauto\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"jūs jau esate prisijungę kitoje vietoje\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"naudotojas išjungtas\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"naudotojas perkeltas\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"Užblokuotas\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"Asmeninis\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"Komanda\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Kompanija\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"Viešas\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"Nežinoma\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"Nebenurodinėti\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"Žmonės mano kompanijoje\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"Žmonės viešuosiuose tinkluose, prijungtuose prie mano kompanijos\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"Žmonės viešuosiuose tinkluose\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"Žmonės ties %s\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"Pridėti naują sritį...\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"Žinynas internete...\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"Prieigos grupės\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Neaktyvus\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"Užimtas-Neveiklus\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Netrukus grįšiu\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"Pietauju\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"Dalyvauju skambutyje\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"Konferencijoje\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"Susitikime\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"Tik skubūs pertraukimai\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"Pristatinėjama\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"Prisijungimo būsenos prenumerata nepavyko!\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"Dėl to, vienas ar daugiau bičiulių bus visą laiką rodomi kaip atsijungę.\\n\\nPrašome patikrinti ar jūsų kontaktų sąraše nėra sugadintų SIP URI.\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"UCS inicijavimas nepavyko!\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"Nepavyko rasti Exchange serverio su numatytaisiais el. pašto nustatymais. Dėl to, kontaktų sąrašas neveiks.\\n\\nJums reikės pateikti el. pašto nustatymus paskyros sąrankoje.\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"Nepavyko rasti Exchange serverio su paskyros sąrankoje pateiktais el. pašto nustatymais. Dėl to, kontaktų sąrašas neveiks.\\n\\nPrašome ištaisyti savo el. pašto nustatymus.\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"Jūsų žinutė ar pakvietimas nebuvo pristatytas, tikriausiai, dėl to, kad jame yra saitas arba kitas sistemos administratoriaus užblokuotas turinys.\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"Ši žinutė nebuvo pristatyta pašnekovui %s, kadangi paslauga yra neprieinama\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"Ši žinutė nebuvo pristatyta pašnekovui %s, kadangi vienas ar daugiau gavėjų nenori būti trukdomi\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"Ši žinutė nebuvo pristatyta pašnekovui %s, kadangi vienas ar daugiau gavėjų nepalaiko šio žinutės tipo\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"Ši žinutė nebuvo pristatyta pašnekovui %s, kadangi vienas ar daugiau gavėjų yra atsijungę\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Rodomas vardas\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"Pareigos\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"Miestas\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"Valstija\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"Biuras\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"Šalis\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"Darbo telefonas\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"El. pašto adresas\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"Svetainė\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"Slapyvardis\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"Įrenginys\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"jūs\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"Sritis\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"Pridėti naują sritį\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"Pridėti\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"Atsisakyti\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"Kopijuoti į\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Užrakinti\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Atrakinti\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"Rodyti pristatymą\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"Susitikimo įrašo informacija\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"_URI:\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"Naudotojai\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"Pakviesti\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"Privatus\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"Žurnalas\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"Aprašas\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"Pokalbio tema: %s\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Žinutė\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"Jungiamasi\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"Reikalingas slaptažodis\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"naudotojas@kompanija.com\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"Telefono numeris\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"Skambinti telefono numeriu\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"_Skambinti\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"_Atsisakyti\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"Susitikimo vieta\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"Kitu atveju\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"Organizatoriaus el. paštas\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"Susitikimo ID\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"Prisijungti prie konferencijos\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"Prisijungti prie suplanuotos konferencijos\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"Įveskite susitikimo vietos eilutę, kurią gavote pakvietime.\\n\\nTeisinga vieta būtų kažkas panašaus į\\nmeet:sip:kažkas@kompanija.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nconf:sip:kažkas@kompanija.com;gruu;opaque=app:conf:focus:id:abcdef1234\\narba\\nhttps://susitikimas.kompanija.com/kažkas/abcdef1234\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"_Prisijungti\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"Kalendoriaus informacijos skelbimas buvo išjungtas\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"Apie SIPE papildinį...\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"Kontaktų paieška...\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"Skambinti telefono numeriu...\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"Bandomasis skambutis\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"Prisijungti prie suplanuotos konferencijos...\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"Iš naujo skelbti kalendorių\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"Atstatyti būseną\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Serveris[:Prievadas]\\n(automatiniam aptikimui palikite tuščią)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"Ryšio tipas\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Automatiškai\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"Naudotojo agentas\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"Tapatybės nustatymo schema\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"Kerberos\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Naudoti vieningą prisijungimą (Single Sign-On)\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"Neskelbti mano kalendoriaus informacijos\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"Rodyti profilio paveikslus iš saityno\\n(potencialiai pavojinga)\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"El. pašto paslaugų URL\\n(automatiniam aptikimui palikite tuščią)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"El. pašto adresas\\n(jeigu kitoks nei Naudotojo vardas)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"El. pašto prisijungimas\\n(jeigu kitoks nei Prisijungimas)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"El. pašto slaptažodis\\n(jeigu kitoks nei Slaptažodis)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"Grupės pokalbio įgaliotasis serveris\\n   kompanija.com  arba  naudotojas@kompanija.com\\n(palikite tuščią, kad būtų nustatyta pagal naudotojo vardą)\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"Nuotolinio darbalaukio klientas\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"Medijos šifravimas\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"Paklusti serverio politikai\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"Visada\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"Pasirinktinai\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"Išjungta\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"Prisijungimas\\n   naudotojas  ar  SRITIS\\\\naudotojas  ar\\n   naudotojas@kompanija.com\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"Naudotojo vardas\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"Vardas\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"El. paštas\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"Vardas\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Pavardė\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"SIP ID\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Paieška\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"Kontakto paieška\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"Įrašykite norimo rasti asmens informaciją. Tuščių laukų bus nepaisoma.\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_Ieškoti\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"Skaitymo klaida\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"Serveris atsijungė\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"Nepavyko prisijungti\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"Nepavyko sukurti SSL konteksto\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"Nepavyko sukurti lizdo\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"Rašymo klaida\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"Gerai\"\n"
  },
  {
    "path": "po/nb.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Espen Stefansen <libbe@stefansen.net>, 2011\n# Stefan Becker <chemobejk@gmail.com>, 2011\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 16:09+0000\\n\"\n\"Last-Translator: Stefan Becker <chemobejk@gmail.com>\\n\"\n\"Language-Team: Norwegian Bokmål (http://www.transifex.com/stefanb/pidgin-sipe/language/nb/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: nb\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"Klarte ikke å autentisere til tjener\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"Autentisering feilet\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"Du har blitt avslått av tjeneren: %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"ingen grunn gitt\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"Ikke funnet: %s. Vennligst ta kontakt med administrator\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"Tjeneste utilgjengelig: %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"Ugyldig meldingssignatur mottatt\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"Aksepter\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"Avslå\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"Status\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Kalender\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"Møte i\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"Møte om\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"Ute av kontoret merknad\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"Merknad\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"Tilgangsnivå\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"Fant %d kontakt%s:\"\nmsgstr[1] \"Fant %d kontakter%s:\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"Klarte ikke vise søkeresultater\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"Fjern fra '%s'\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"Inviter til '%s'\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"Ny chat\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Hjemmeside\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"Send e-post...\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Ledig\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"Foreløpig\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Opptatt\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"Ikke på kontoret\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"Ingen informasjon\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"I øyeblikket %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"Utenfor arbeidstid de neste 8 timene\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s for de neste 8 timene\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"Fritid\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s til %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"Konferansen er ikke lengre låst. Nå kan andre deltakere koble til\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"Konferansen er låst. Ingen andre kan koble til så lenge konferansen er låst.\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"Du har blitt koblet fra denne konferansen.\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"Et tredjeparts programtillegg som implementerer en utvidet versjon av SIP/SIMPLE i bruk av diverse produkter\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"Hjelpeforum (på engelsk)\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"Rapporter problemer\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"Oversettelser\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"Lisens\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"Hjelp oss å oversette SIPE til flere språk på\"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \"ved å bruke et lettvindt vev-grensesnitt\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"Utviklere\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"Norsk oversettelse (nb): Andreas Angerman\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"SIP Exchange brukernavn inneholder ugyldige tegn\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"Brukernavn skal være en gyldig SIP URI\\nEksempel: bruker@firma.no\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"E-postadresse skal være gyldig hvis oppgitt\\nEksempel: bruker@firma.no\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"Brukernavnet til SIP Exchange inneholder mellomrom\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"Lokasjon:\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"Forbindelse feilet\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"Mottatt krypteringsnøkkel har feil størrelse\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"Mottatt hash-nøkkel har feil størrelse.\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"Kunne ikke lage lytte-sokkel\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"Størrelsen er ulik fra forespeilet verdi.\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"Mottatt MAC-adresse er skadet\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"Mottatt fil er skadet\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"Start av filoverføring feilet.\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"Autentisering av filoverføring feilet.\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"Tomt for minne\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Andre kontakter\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"Mislykkes med å invitere %s\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"Mottok en melding med ukjent innhold fra %s\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"Kunne ikke etablere en samtale\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"Bruker utilgjengelig\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s ønsker ikke å bli forstyrret\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"Bruker %s er ikke tilgjengelig\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"du er allerede logget på et annet sted\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"bruker er deaktivert\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"Blokkert\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Firma\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"Ukjent\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"Personer i mitt firma\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"Personer i domener koblet til mitt firma\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"Personer i offentlige domener\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"Personer hos %s\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"Legg til nytt domene...\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Ikke tilgjengelig\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Er snart tilbake\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"Ute til lunsj\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"I en samtale\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"I en konferanse\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"I et møte\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"Bare viktige forstyrrelser\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"Meldingen eller invitasjonen ble ikke levert, sansynligvis fordi den inneholder en hyperlenke eller annet innhold som systemadministratoren har blokkert.\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"Denne meldingen ble ikke levert til %s fordi tjenesten ikke er tilgjengelig\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"Denne meldingen ble ikke levert til %s fordi en eller flere av mottakerne ikke ville bli forstyrret\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"Denne meldingen ble ikke levert til %s fordi en eller flere av mottakerne støtter ikke denne type melding\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"Denne meldingen ble ikke levert til %s fordi en eller flere av mottakerne er frakoblet\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Skjermnavn\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"Stillingstittel\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"By\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"Fylke\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"Kontor\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"Land\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"Arbeidstelefon\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"E-postadresse\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"Alias\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"du\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"Domene\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"Legg til nytt domene\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"Legg til\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"Avbryt\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"Kopier til\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Lås\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Lås opp\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"Brukere\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"Inviter\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"Privat\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"Logg\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"Beskrivelse\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Melding\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"Kobler til\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"bruker@firma.no\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"_Avbryt\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"Om SIPE-programtillegget...\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"Kontaktsøk...\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"Republiser kalender\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"Tilbakestill status\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Tjener[:port]\\n(la stå tom for automatisk søk)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"Tilkoplingstype\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Automatisk\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"Brukeragent\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Bruk Single Sign-On\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"E-posttjeneste URL\\n(lå stå tom for automatisk søk)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"E-postadresse\\n(hvis ulik fra brukernavn)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"E-post brukernavn\\n(hvis ulik brukernavn)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"(E-post passord\\n(hvis ulik passord)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"Pålogging\\n brukernavn eller DOMENE\\\\brukernavn eller\\n brukernavn@firma.no\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"Brukernavn\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"Navn\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"E-post\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"Fornavn\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Etternavn\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Søk\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"Søk etter en kontakt\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"Legg inn informasjon om personen du ønsker å finne. Tomme felt vil bli ignorert.\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_Søk\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"Lesefeil\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"Tjener har koblet fra\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"Kunne ikke koble til\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"Skrivefeil\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"\"\n"
  },
  {
    "path": "po/nl.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# fieona <sofiemuys@hotmail.com>, 2012\n# Stefan Becker <chemobejk@gmail.com>, 2011\n# Tonnes <tonnes.mb@gmail.com>, 2016-2018\n# Yves Jacmans <yves@jacmans.net>, 2017\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-12-22 12:31+0000\\n\"\n\"Last-Translator: Tonnes <tonnes.mb@gmail.com>\\n\"\n\"Language-Team: Dutch (http://www.transifex.com/stefanb/pidgin-sipe/language/nl/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: nl\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"Authenticatie bij server mislukt\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"Kan geen certificaat aanvragen bij %s\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"Geen URI voor certificaat verstrekkende service opgegeven\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"Authenticatie mislukt\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"Niet-compatibel authenticatieschema gekozen\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"U bent geweigerd door de server %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"geen reden opgegeven\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"Niet gevonden: %s. Neem contact op met uw beheerder\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"SIP is niet ingeschakeld voor de bestemmings-URI, of deze bestaat niet\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"Service niet beschikbaar: %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"Beschadigd bericht ontvangen\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"Ongeldige berichthandtekening ontvangen\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"%s wil een presentatie starten\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"Accepteren\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"Weigeren\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"Fout bij delen van toepassingen\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"Onbekende extern-bureaubladclient geconfigureerd.\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"Kon het delen van toepassingen niet starten\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"Kon RDP-server niet maken.\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"Kon RDP-server niet initialiseren.\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"Kon RDP-server niet starten.\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"Bureaublad gedeeld met %s\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"Presenteren stoppen\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"Kon delen van toepassingen niet initialiseren\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"Hele bureaublad\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"Te delen monitor\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"Mobiel\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"Status\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Agenda\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"Vergadering in\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"Vergadering over\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"Afwezigheidsbericht\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"Bericht\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"Toegangsniveau\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"%d contact gevonden%s:\"\nmsgstr[1] \"%d contacten gevonden%s:\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" (meer resultaten voor uw query)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"Geen contacten gevonden\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"Kan de zoekresultaten niet weergeven\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"Zoeken naar contact mislukt\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"Ongeldige query voor zoeken naar contact\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"Leider maken van ‘%s’\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"Verwijderen van ‘%s’\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"Uitnodigen voor ‘%s’\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"Nieuwe chat\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"Werk\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Thuis\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"Anders\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"Aangepast1\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"E-mail sturen...\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"Bureaubladbesturing overnemen\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"Bureaubladbesturing overgeven\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"Mijn bureaublad delen\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Beschikbaar\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"Voorlopig\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Bezet\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"Niet aanwezig\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"Geen gegevens\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"Momenteel %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"Buiten werktijden voor de komende 8 uur\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s voor de komende 8 uur\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"Niet aan het werk\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s tot %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s. Buiten werktijden om %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s. %s om %.2d:%.2d\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"Certificaataanvraag bij %s mislukt\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"Webticketaanvraag bij %s mislukt\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"Chat #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"Deelnemen aan de vergadering mislukt\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"Kan geen vergadering-URI vinden op deze pagina:\\n\\n%s\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"‘%s’ is geen geldige vergadering-URI\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"Onvolledige vergaderingsgegevens opgegeven\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\\n\\nAangezien deze client niet met ondersteuning voor audiogesprekken is gecompileerd, zult u bij accepteren alleen met de andere deelnemers in contact kunnen komen via een IM-sessie.\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"wil u uitnodigen voor een telefonische vergadering%s\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"Deze vergadering is niet meer vergrendeld. Er kunnen nu anderen aan de vergadering deelnemen.\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"Deze vergadering is vergrendeld. Er kunnen geen anderen aan de vergadering deelnemen zolang deze is vergrendeld.\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"Uw verbinding met deze vergadering is verbroken.\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"Inbelgegevens\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"Nummer\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"Vergadering-id\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"Koppeling naar vergadering\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"Organisator\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"Alternatieve inbelnummers\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"Een plug-in van derden voor implementatie van een uitgebreide versie van SIP/SIMPLE, dat door diverse producten wordt gebruikt\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"Startpagina\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"Ondersteuning\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"Helpforum\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"Problemen melden\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"Bugtracker\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"Vertalingen\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"Licentie\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"Help SIPE naar uw eigen taal te vertalen op \"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \" via een handige webinterface\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"Auteurs\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"Nederlandse vertaling (nl): Fieona, Tonnes\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"SIP Exchange-gebruikersnaam bevat ongeldige tekens\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"Gebruikersnaam moet een geldige SIP-URI zijn\\nVoorbeeld: gebruiker@bedrijf.com\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"Wachtwoord is vereist als eenmalige aanmelding niet is ingeschakeld\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"E-mailadres moet geldig zijn wanneer opgegeven\\nVoorbeeld: gebruiker@bedrijf.com\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"SIP Exchange-gebruikersnaam bevat spatie\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"URL van e-mailservices moet geldig zijn wanneer opgegeven\\nVoorbeeld: https://exchange.corp.com/EWS/Exchange.asmx\\nVoorbeeld: https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"Locatie:\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"Lezen van socket mislukt\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"Ontvangen encryptiesleutel heeft onjuiste grootte.\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"Ontvangen hash-sleutel heeft onjuiste grootte.\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"Kon geen listen-socket maken\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"Er is een fout opgetreden\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"Fout bij het maken van gegevensstroom\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"Schrijven naar socket mislukt\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"Bestandsgrootte verschilt van de aangekondigde waarde.\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"Ontvangen MAC is beschadigd\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"Ontvangen bestand is beschadigd\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"Initialisatie van bestandsoverdracht mislukt.\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"Authenticatie voor bestandsoverdracht mislukt.\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"Onvoldoende geheugen\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Andere contacten\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"Proxyinstelling voor groepschat is onjuist:\\n\\n\\t%s\\n\\nWerk uw account bij.\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"Kon server voor groepschat niet vinden!\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"Dit bericht is niet afgeleverd bij chatruimte ‘%s’\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"Fout bij het ophalen van ruimtelijst\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"Fout bij het bijwonen van chatruimte\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"Uitnodigen van %s mislukt\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"Bericht met niet-herkende inhoud ontvangen van %s\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"Kon geen stream maken\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"Time-out bij verbinding\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"Time-out bij aanvraag\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"Oproep kon niet worden beantwoord\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"Kan geen gesprek tot stand brengen\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"Versleutelingsinstellingen van peer zijn niet compatibel met de onze.\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"Gebruiker %s heeft oproep geweigerd\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"Oproep geweigerd\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"Fout bij het maken van audiostream\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"Fout bij het maken van videostream\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"Deelnemen aan telefonische vergadering\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"Telefonische vergaderingen worden niet ondersteund op deze server.\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"Ongeldig telefoonnummer\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"Audiotestservice is niet beschikbaar.\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"Gebruiker niet beschikbaar\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s wil niet gestoord worden\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"Gebruiker %s is niet beschikbaar\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"Niet-ondersteund mediatype\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"Mediafout\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"Fout bij het lezen van stream\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"u bent al aangemeld op een andere locatie\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"gebruiker uitgeschakeld\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"gebruiker verplaatst\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"Geblokkeerd\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"Persoonlijk\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"Team\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Bedrijf\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"Openbaar\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"Onbekend\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"Wissen\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"Personen in mijn bedrijf\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"Personen in domeinen verbonden met mijn bedrijf\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"Personen in openbare domeinen\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"Personen bij %s\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"Nieuw domein toevoegen...\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"Onlinehulp...\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"Toegangsgroepen\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Inactief\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"Bezig-Inactief\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Ben zo terug\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"Lunchpauze\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"In gesprek\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"In conferentie\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"In vergadering\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"Alleen urgente onderbrekingen\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"Presenteren\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"Aanwezigheidsabonnement mislukt!\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"Een of meer buddy’s verschijnen daarom permanent als offline.\\n\\nControleer of er geen beschadigde SIP-URI’s in uw contactenlijst staan.\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"UCS-initialisatie mislukt!\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"Kon geen Exchange-server vinden met de standaard e-mailinstellingen. Daardoor zal de contactenlijst niet werken.\\n\\nU dient e-mailinstellingen op te geven in de accountinstellingen.\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"Kon geen Exchange-server vinden met de opgegeven e-mailinstellingen in de accountinstellingen. Daardoor zal de contactenlijst niet werken.\\n\\nCorrigeer uw e-mailinstellingen.\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"Uw bericht of uitnodiging is niet afgeleverd, omdat het mogelijk een hyperlink of andere inhoud bevat die de systeembeheerder heeft geblokkeerd.\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"Dit bericht is niet bij %s afgeleverd, omdat de service niet beschikbaar is\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"Dit bericht is niet bij %s afgeleverd, omdat een of meer ontvangers niet gestoord willen worden\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"Dit bericht is niet bij %s afgeleverd, omdat een of meer ontvangers dit type bericht niet ondersteunen\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"Dit bericht is niet bij %s afgeleverd, omdat een of meer ontvangers offline zijn\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Weergavenaam\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"Functie\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"Plaats\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"Provincie\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"Kantoor\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"Land\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"Telefoon op werk\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"E-mailadres\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"Website\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"Alias\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"Apparaat\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"u\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"Domein\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"Nieuw domein toevoegen\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"Toevoegen\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"Annuleren\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"Kopiëren naar\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Vergrendelen\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Ontgrendelen\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"Presentatie tonen\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"Toegangsgegevens voor de vergadering\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"_URI:\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"Gebruikers\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"Uitnodigen\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"Privé\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"Logboek\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"Beschrijving\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"Gespreksonderwerp: %s\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Bericht\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"Verbinding maken\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"Wachtwoord vereist\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"gebruiker@bedrijf.com\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"Telefoonnummer\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"Een telefoonnummer bellen\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"_Bellen\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"_Annuleren\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"Vergaderlocatie\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"Alternatief\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"E-mailadres van organisator\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"Vergadering-id\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"Deelnemen aan vergadering\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"Deelnemen aan geplande vergadering\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"Voer de locatie van de vergadering in die u in de uitnodiging hebt ontvangen.\\n\\nEen geldige locatie ziet eruit als\\nmeet:sip:iemand@bedrijf.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nconf:sip:iemand@bedrijf.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nof\\nhttps://meet.bedrijf.com/iemand/abcdef1234\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"_Deelnemen\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"Het publiceren van agendagegevens is uitgeschakeld\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"Over SIPE-plug-in...\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"Contacten zoeken...\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"Een telefoonnummer bellen...\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"Testgesprek\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"Deelnemen aan geplande vergadering...\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"Agenda opnieuw publiceren\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"Status opnieuw instellen\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Server[:Poort]\\n(laat leeg voor automatische herkenning)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"Verbindingstype\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Automatisch\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"Gebruikersagent\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"Authenticatieschema\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"Kerberos\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Eenmalige aanmelding gebruiken\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"Mijn agendagegevens niet publiceren\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"Profielafbeeldingen van web tonen\\n(mogelijk gevaarlijk)\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"URL van e-mailservices\\n(laat leeg voor automatische detectie)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"E-mailadres\\n(wanneer anders dan Gebruikersnaam)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"E-mailaanmelding\\n(wanneer anders dan Aanmelding)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"E-mailwachtwoord\\n(wanneer anders dan Wachtwoord)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"Proxy voor groepschat\\nbedrijf.com of gebruiker@bedrijf.com\\n(laat leeg voor bepaling uit Gebruikersnaam)\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"Extern-bureaubladclient\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"Mediaversleuteling\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"Serverbeleid volgen\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"Altijd\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"Optioneel\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"Uitgeschakeld\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"Aanmelding\\ngebruiker of DOMEIN\\\\gebruiker of\\ngebruiker@bedrijf.com\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"Gebruikersnaam\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"Naam\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"E-mail\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"Voornaam\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Achternaam\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"SIP-ID\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Zoeken\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"Contactpersoon zoeken\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"Vul de gegevens in voor de persoon die u probeert te vinden. Lege velden worden genegeerd.\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_Zoeken\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"Leesfout\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"Server heeft verbinding verbroken\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"Kon geen verbinding maken\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"Kon geen SSL-context maken\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"Kon geen socket maken\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"Schrijffout\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"OK\"\n"
  },
  {
    "path": "po/pidgin-sipe.pot",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Stefan Becker <chemobejk@gmail.com>, 2011\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 16:09+0000\\n\"\n\"Last-Translator: Stefan Becker <chemobejk@gmail.com>\\n\"\n\"Language-Team: English (http://www.transifex.com/stefanb/pidgin-sipe/language/en/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: en\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"Failed to authenticate to server\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"Can't request certificate from %s\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"No URI for certificate provisioning service provided\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"Authentication failed\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"Incompatible authentication scheme chosen\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"You have been rejected by the server: %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"no reason given\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"Not found: %s. Please contact your Administrator\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"SIP is either not enabled for the destination URI or it does not exist\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"Service unavailable: %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"Corrupted message received\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"Invalid message signature received\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"%s wants to start presenting\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"Accept\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"Decline\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"Application sharing error\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"Unknown remote desktop client configured.\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"Couldn't connect application sharing\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"Could not create RDP server.\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"Could not initialize RDP server.\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"Could not start RDP server.\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"Sharing desktop with %s\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"Stop presenting\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"Couldn't initialize application sharing\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"Whole desktop\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"Monitor to share\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"Mobile\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"Status\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Calendar\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"Meeting in\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"Meeting about\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"Out of office note\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"Note\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"Access level\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"Found %d contact%s:\"\nmsgstr[1] \"Found %d contacts%s:\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" (more matched your query)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"No contacts found\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"Unable to display the search results\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"Contact search failed\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"Invalid contact search query\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"Make leader of '%s'\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"Remove from '%s'\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"Invite to '%s'\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"New chat\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"Work\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Home\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"Other\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"Custom1\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"Send email...\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"Take desktop control\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"Give desktop control\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"Share my desktop\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Free\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"Tentative\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Busy\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"Out of office\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"No data\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"Currently %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"Outside of working hours for next 8 hours\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s for next 8 hours\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"Not working\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s until %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s. Outside of working hours at %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s. %s at %.2d:%.2d\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"Certificate request to %s failed\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"Web ticket request to %s failed\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"Chat #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"Failed to join the conference\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"Can't find a conference URI on this page:\\n\\n%s\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\\\"%s\\\" is not a valid conference URI\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"Incomplete conference information provided\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\\n\\nAs this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"wants to invite you to a conference call%s\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"This conference is no longer locked. Additional participants can now join.\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"This conference is locked. Nobody else can join the conference while it is locked.\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"You have been disconnected from this conference.\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"Dial-in info\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"Number\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"Conference ID\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"Meeting link\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"Organizer\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"Alternative dial-in numbers\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"A third-party plugin implementing extended version of SIP/SIMPLE used by various products\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"Home Page\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"Support\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"Help Forum\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"Report Problems\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"Bug Tracker\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"Translations\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"License\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"Please help us to translate SIPE to your native language here at \"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \" using convenient web interface\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"Authors\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"Original texts in English (en): SIPE developers\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"SIP Exchange user name contains invalid characters\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"User name should be a valid SIP URI\\nExample: user@company.com\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"Password is required when Single Sign-On is not enabled\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"Email address should be valid if provided\\nExample: user@company.com\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"SIP Exchange user name contains whitespace\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"Email services URL should be valid if provided\\nExample: https://exchange.corp.com/EWS/Exchange.asmx\\nExample: https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"Location:\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"Socket read failed\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"Received encryption key has wrong size.\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"Received hash key has wrong size.\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"Could not create listen socket\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"Error occurred\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"Error creating data stream\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"Socket write failed\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"File size is different from the advertised value.\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"Received MAC is corrupted\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"Received file is corrupted\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"File transfer initialization failed.\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"File transfer authentication failed.\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"Out of memory\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Other Contacts\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"Group Chat Proxy setting is incorrect:\\n\\n\\t%s\\n\\nPlease update your Account.\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"Couldn't find Group Chat server!\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"This message was not delivered to chat room '%s'\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"Error retrieving room list\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"Error joining chat room\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"Failed to invite %s\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"Received a message with unrecognized contents from %s\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"Couldn't create stream\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"Connection timed out\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"Request timed out\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"Call could not be answered\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"Unable to establish a call\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"Encryption settings of peer are incompatible with ours.\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"User %s rejected call\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"Call rejected\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"Error creating audio stream\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"Error creating video stream\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"Join conference call\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"Conference calls are not supported on this server.\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"Invalid phone number\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"Audio Test Service is not available.\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"User unavailable\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s does not want to be disturbed\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"User %s is not available\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"Unsupported media type\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"Media error\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"Error while reading from stream\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"you are already signed in at another location\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"user disabled\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"user moved\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"Blocked\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"Personal\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"Team\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Company\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"Public\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"Unknown\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"Unspecify\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"People in my company\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"People in domains connected with my company\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"People in public domains\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"People at %s\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"Add new domain...\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"Online help...\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"Access groups\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Inactive\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"Busy-Idle\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Be right back\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"Out to lunch\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"In a call\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"In a conference\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"In a meeting\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"Urgent interruptions only\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"Presenting\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"Presence subscription failed!\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"One or more buddies will therefore permanently show as offline.\\n\\nPlease check that there are no corrupted SIP URIs in your contacts list.\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"UCS initialization failed!\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\\nYou'll need to provide Email settings in the account setup.\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\\nPlease correct your Email settings.\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"Your message or invitation was not delivered, possibly because it contains a hyperlink or other content that the system administrator has blocked.\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"This message was not delivered to %s because the service is not available\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"This message was not delivered to %s because one or more recipients do not want to be disturbed\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"This message was not delivered to %s because one or more recipients don't support this type of message\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"This message was not delivered to %s because one or more recipients are offline\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Display name\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"Job title\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"City\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"State\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"Office\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"Country\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"Business phone\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"Email address\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"Site\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"Alias\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"Device\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"you\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"Domain\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"Add new domain\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"Add\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"Cancel\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"Copy to\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Lock\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Unlock\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"Show presentation\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"Meeting entry info\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"_URI:\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"Users\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"Invite\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"Private\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"Log\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"Description\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"Conversation subject: %s\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Message\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"Connecting\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"Password required\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"user@company.com\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"Phone number\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"Call a phone number\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"_Call\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"_Cancel\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"Meeting location\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"Alternatively\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"Organizer email\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"Meeting ID\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"Join conference\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"Join scheduled conference\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"Enter meeting location string you received in the invitation.\\n\\nValid location will be something like\\nmeet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nconf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nor\\nhttps://meet.company.com/someone/abcdef1234\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"_Join\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"Publishing of calendar information has been disabled\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"About SIPE plugin...\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"Contact search...\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"Call a phone number...\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"Test call\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"Join scheduled conference...\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"Republish Calendar\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"Reset status\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Server[:Port]\\n(leave empty for auto-discovery)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"Connection type\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Auto\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"User Agent\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"Authentication scheme\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"Kerberos\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Use Single Sign-On\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"Don't publish my calendar information\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"Show profile pictures from web\\n(potentially dangerous)\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Email services URL\\n(leave empty for auto-discovery)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"Email address\\n(if different from Username)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"Email login\\n(if different from Login)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"Email password\\n(if different from Password)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"Group Chat Proxy\\n   company.com  or  user@company.com\\n(leave empty to determine from Username)\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"Remote desktop client\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"Media encryption\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"Obey server policy\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"Always\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"Optional\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"Disabled\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"Login\\n   user  or  DOMAIN\\\\user  or\\n   user@company.com\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"User name\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"Name\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"Email\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"First name\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Last name\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"SIP ID\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Search\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"Search for a contact\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"Enter the information for the person you wish to find. Empty fields will be ignored.\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_Search\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"Read error\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"Server has disconnected\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"Could not connect\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"Could not create SSL context\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"Could not create socket\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"Write error\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"OK\"\n"
  },
  {
    "path": "po/pl.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Piotr Drąg <piotrdrag@gmail.com>, 2011-2013,2015-2018\n# Stefan Becker <chemobejk@gmail.com>, 2011\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 18:22+0000\\n\"\n\"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\\n\"\n\"Language-Team: Polish (http://www.transifex.com/stefanb/pidgin-sipe/language/pl/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: pl\\n\"\n\"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"Uwierzytelnienie do serwera się nie powiodło\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"Nie można zażądać certyfikatu od %s\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"Nie podano adresu URI dla usługi zabezpieczania certyfikatów\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"Uwierzytelnienie się nie powiodło\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"Wybrano niezgodny schemat uwierzytelnienia\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"Użytkownik został odrzucony przez serwer: %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"nie podano przyczyny\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"Nie odnaleziono: %s. Proszę skontaktować się z administratorem\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"SIP nie jest włączony dla docelowego adresu URI lub nie istnieje\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"Usługa jest niedostępna: %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"Odebrano uszkodzoną wiadomość\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"Odebrano nieprawidłowy podpis wiadomości\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"Użytkownik %s chce zacząć prezentację\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"Odbierz\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"Odmów\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"Błąd podczas udostępniania aplikacji\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"Skonfigurowano nieznanego zdalnego klienta.\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"Nie można połączyć udostępniania aplikacji\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"Nie można utworzyć serwera RDP.\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"Nie można zainicjować serwera RDP.\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"Nie można uruchomić serwera RDP.\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"Udostępnianie pulpitu użytkownikowi %s\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"Zatrzymaj prezentację\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"Nie można zainicjować udostępniania aplikacji\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"Cały pulpit\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"Udostępniany monitor\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"Komórka\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"Stan\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Kalendarz\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"Spotkanie za\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"Spotkanie w\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"Notatka poza biurem\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"Notatka\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"Poziom dostępu\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"Odnaleziono %d kontakt%s:\"\nmsgstr[1] \"Odnaleziono %d kontakty%s:\"\nmsgstr[2] \"Odnaleziono %d kontaktów%s:\"\nmsgstr[3] \"Odnaleziono %d kontaktów%s:\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" (więcej wyników zapytania)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"Nie odnaleziono kontaktów\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"Nie można wyświetlić wyników wyszukiwania\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"Wyszukanie kontaktu się nie powiodło\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"Nieprawidłowe zapytanie wyszukiwania kontaktu\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"Uczyń przywódcą „%s”\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"Usuń z „%s”\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"Zaproś do „%s”\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"Nowa rozmowa\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"Praca\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Strona domowa\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"Inne\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"Własne1\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"Wyślij wiadomość e-mail…\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"Przejmij sterowanie pulpitem\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"Oddaj sterowanie pulpitem\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"Udostępnij pulpit\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Wolne\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"Wstępnie\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Zajęty\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"Poza biurem\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"Brak danych\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"Obecnie %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"Poza godzinami pracy przez następne 8 godzin\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s przez następne 8 godzin\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"Nie pracuje\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s od %.2d∶%.2d\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s. Poza godzinami pracy o %.2d∶%.2d\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s. %s o %.2d∶%.2d\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"Żądanie certyfikatu do %s się nie powiodło\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"Żądanie zgłoszenia WWW do %s się nie powiodło\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"Rozmowa #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"Dołączenie do konferencji się nie powiodło\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"Nie można odnaleźć adresu URI konferencji na tej stronie:\\n\\n%s\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"„%s” nie jest prawidłowym adresem URI konferencji\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"Podano niepełne informacje o konferencji\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\\n\\nPonieważ klient nie został skompilowany z obsługą rozmów głosowych, po odebraniu będzie można kontaktować się z innymi uczestnikami tylko za pomocą komunikatora.\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"chce zaprosić użytkownika do pokoju konferencji%s\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"Ta konferencja nie jest już zablokowana. Dodatkowi uczestnicy mogą teraz dołączyć.\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"Ta konferencja jest zablokowana. Nikt więcej nie może teraz dołączyć.\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"Rozłączono z tej konferencji.\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"Informacje o wdzwanianiu\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"Numer\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"Identyfikator konferencji\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"Odnośnik do spotkania\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"Organizator\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"Alternatywne numery wdzwaniania\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"Wtyczka firmy trzeciej implementująca rozszerzoną wersję protokołu SIP/SIMPLE używaną przez różne produkty\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"Strona domowa\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"Wsparcie\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"Forum pomocy\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"Zgłaszanie problemów\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"System śledzenia błędów\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"Tłumaczenia\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"Licencja\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"Prosimy o pomoc w przetłumaczeniu wtyczki SIPE na inne języki pod adresem \"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \" za pomocą wygodnego interfejsu WWW\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"Autorzy\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"Tłumaczenie na język polski (pl): Piotr Drąg\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"Nazwa użytkownika SIP Exchange zawiera nieprawidłowe znaki\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"Nazwa użytkownika powinna być prawidłowym adresem URI protokołu SIP\\nPrzykład: użytkownik@example.com\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"Wymagane jest hasło, kiedy logowanie pojedyncze nie jest włączone\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"Jeśli podano adres e-mail, powinien on być prawidłowy\\nPrzykład: użytkownik@example.com\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"Nazwa użytkownika SIP Exchange zawiera spację\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"Adres e-mail serwisów powinien być prawidłowy, jeśli został podany\\nPrzykład: https://exchange.corp.com/EWS/Exchange.asmx\\nPrzykład: https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"Położenie:\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"Odczyt z gniazda się nie powiódł\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"Pobrany klucz szyfrowania ma błędny rozmiar.\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"Pobrany klucz mieszania ma błędny rozmiar.\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"Nie można utworzyć gniazda nasłuchiwania\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"Wystąpił błąd\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"Błąd podczas tworzenia strumienia danych\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"Zapis do gniazda się nie powiódł\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"Rozmiar pliku jest różny od ogłoszonej wartości.\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"Otrzymany adres MAC jest uszkodzony\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"Pobrany plik jest uszkodzony\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"Zainicjowanie przesyłania pliku się nie powiodło.\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"Uwierzytelnienie przesyłania pliku się nie powiodło.\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"Brak pamięci\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Inne kontakty\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"Ustawienie pośrednika rozmów grupowych jest niepoprawne:\\n\\n\\t%s\\n\\nProszę zaktualizować konto.\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"Nie można odnaleźć serwera rozmów grupowych.\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"Ta wiadomość nie została dostarczona do pokoju rozmów „%s”\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"Błąd podczas pobierania listy pokoi\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"Błąd podczas dołączania do pokoju rozmów\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"Zaproszenie %s się nie powiodło\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"Odebrano wiadomość z nierozpoznaną zawartością od %s\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"Nie można utworzyć strumienia\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"Połączenie przekroczyło czas oczekiwania\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"Żądanie przekroczyło czas oczekiwania\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"Nie można odebrać rozmowy\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"Nie można nawiązać rozmowy\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"Ustawienia szyfrowania partnera są niezgodne z lokalnymi.\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"Użytkownik %s odrzucił rozmowę\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"Odrzucono rozmowę\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"Błąd podczas tworzenia strumienia dźwięku\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"Błąd podczas tworzenia strumienia obrazu\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"Dołącz do konferencji\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"Ten serwer nie obsługuje konferencji\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"Nieprawidłowy numer telefonu\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"Usługa testowania dźwięku jest niedostępna.\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"Użytkownik jest niedostępny\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"Użytkownik %s nie chce, aby mu przeszkadzać\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"Użytkownik %s jest niedostępny\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"Nieobsługiwany typ multimediów\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"Błąd multimediów\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"Błąd podczas odczytywania ze strumienia\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"zalogowano się z innego położenia\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"użytkownik został wyłączony\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"użytkownik został przeniesiony\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"Zablokowane\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"Osobiste\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"Zespół\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Firma\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"Publiczne\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"Nieznane\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"Nieokreślony\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"Osoby z firmy\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"Osoby w domenach połączonych z firmą\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"Osoby w domenach publicznych\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"Osoby w %s\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"Dodaj nową domenę…\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"Pomoc online…\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"Grupy dostępu\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Nieaktywny\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"Bezczynny\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Zaraz wracam\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"Na obiedzie\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"Przy telefonie\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"Na konferencji\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"Na spotkaniu\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"Przeszkadzać tylko w pilnych przypadkach\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"Trwa prezentacja\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"Subskrypcja obecności się nie powiodła.\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"Jeden lub więcej znajomych będzie wyświetlanych jako w trybie offline.\\n\\nProszę sprawdzić, czy na liście kontaktów nie ma uszkodzonych adresów URI protokołu SIP.\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"Zainicjowanie UCS się nie powiodło.\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"Nie można odnaleźć serwera Exchange za pomocą domyślnych ustawień poczty. z tego powodu lista kontaktów nie będzie działała.\\n\\nNależy podać ustawienia poczty w ustawieniach konta.\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"Nie można odnaleźć serwera Exchange za pomocą ustawień poczty podanych w ustawieniach konta. Z tego powodu lista kontaktów nie będzie działała.\\n\\nNależy poprawić ustawienia poczty.\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"Wiadomość lub zaproszenie nie zostało dostarczone, prawdopodobnie dlatego, że zawiera odnośnik lub inną zawartość zablokowaną przez administratora systemu.\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"Nie dostarczono wiadomości do %s, ponieważ usługa jest niedostępna\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"Nie dostarczono wiadomości do %s, ponieważ jeden lub więcej odbiorców nie chce, aby im przeszkadzano\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"Nie dostarczono wiadomości do %s, ponieważ jeden lub więcej odbiorców nie obsługuje tego typu wiadomości\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"Nie dostarczono wiadomości do %s, ponieważ jeden lub więcej odbiorców jest trybie offline\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Wyświetlana nazwa\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"Stanowisko\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"Miasto\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"Stan/województwo\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"Biuro\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"Kraj\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"Telefon służbowy\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"Adres e-mail\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"Witryna\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"Alias\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"Urządzenie\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"ty\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"Domena\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"Dodaj nową domenę\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"Dodaj\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"Anuluj\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"Skopiuj do\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Zablokuj\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Odblokuj\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"Wyświetl prezentację\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"Informacje o spotkaniu\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"Adres _URI:\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"Użytkownicy\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"Zaproś\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"Prywatny\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"Dziennik\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"Opis\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"Temat rozmowy: %s\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Wiadomość\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"Łączenie\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"Wymagane jest hasło\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"użytkownik@example.com\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"Numer telefonu\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"Zadzwoń na numer telefonu\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"_Zadzwoń\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"_Anuluj\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"Położenie spotkania\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"Alternatywnie\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"Adres e-mail organizatora\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"Identyfikator spotkania\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"Dołączenie do konferencji\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"Dołączenie do zaplanowanej konferencji\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"Proszę podać ciąg położenia spotkania, który otrzymano w zaproszeniu.\\n\\nPrawidłowe położenie wygląda podobnie do\\nmeet:sip:ktoś@example.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nconf:sip:ktoś@example.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nlub\\nhttps://meet.example.com/ktoś/abcdef1234\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"_Dołącz\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"Publikowanie informacji kalendarza zostało wyłączone\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"O wtyczce SIPE…\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"Wyszukaj kontakt…\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"Zadzwoń na numer telefonu…\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"Rozmowa testowa\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"Dołącz do zaplanowanej konferencji…\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"Ponownie opublikuj kalendarz\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"Przywróć stan\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Serwer[:port]\\n(należy pozostawić puste, aby wykryć automatycznie)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"Typ połączenia\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Automatycznie\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"Agent użytkownika\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"Schemat uwierzytelniania\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"Kerberos\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Logowanie pojedyncze\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"Bez publikowania informacji kalendarza\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"Wyświetlanie obrazów profilu z Internetu\\n(potencjalnie niebezpieczne)\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Adres URL usług e-mail\\n(należy pozostawić puste, aby wykryć automatycznie)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"Adres e-mail\\n(jeśli różni się od nazwy użytkownika)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"Login adresu e-mail\\n(jeśli różni się od loginu)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"Hasło adresu e-mail\\n(jeśli różni się od hasła)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"Pośrednik rozmów grupowych\\n   example.com lub użytkownik@example.com\\n(należy pozostawić puste, aby ustalić z nazwy użytkownika)\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"Zdalny klient\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"Szyfrowanie multimediów\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"Przestrzeganie polityki serwera\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"Zawsze\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"Opcjonalnie\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"Wyłączone\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"Login\\n   użytkownik lub DOMENA\\\\użytkownik lub\\n   użytkownik@example.com\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"Nazwa użytkownika\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"Nazwa\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"Adres e-mail\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"Imię\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Nazwisko\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"Identyfikator SIP\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Wyszukiwanie\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"Wyszukiwanie kontaktu\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"Proszę podać informacje o wyszukiwanej osobie. Puste pola zostaną zignorowane.\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"Wy_szukaj\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"Błąd odczytu\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"Serwer został rozłączony\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"Nie można połączyć\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"Nie można utworzyć kontekstu SSL\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"Nie można utworzyć gniazda\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"Błąd zapisu\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"OK\"\n"
  },
  {
    "path": "po/pt.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Anibal Avelar <debianmx@gmail.com>, 2012\n# Bruno Martins <inactive+skorzen@transifex.com>, 2012\n# Bruno Queiros <bqueiros@gmail.com>, 2014-2015,2017\n# Filipe Boleto <fboleto@gmail.com>, 2011,2015-2016,2019\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2019-08-13 18:42+0000\\n\"\n\"Last-Translator: Filipe Boleto <fboleto@gmail.com>\\n\"\n\"Language-Team: Portuguese (http://www.transifex.com/stefanb/pidgin-sipe/language/pt/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: pt\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"Falha ao autenticar no servidor\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"Não é possível solicitar o certificado de %s\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"Nenhum URI fornecido para o serviço de provisionamento\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"Autenticação falhou\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"O método de autenticação escolhido é incompatível\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"Você foi rejeitado pelo servidor: %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"nenhuma razão apresentada\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"Não encontrado: %s. Por favor contacte o seu Administrador \"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"Ou o SIP não está habilitado no URI de destino, ou não existe\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"Serviço indisponível: %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"Mensagem corrompida recebida\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"Recebida uma assinatura de mensagem inválida\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"%s deseja iniciar a apresentação\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"Aceitar\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"Negar\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"Erro na partilha de aplicação\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"Cliente de desktop remoto desconhecido configurado.\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"Não foi possível ligar à partilha de aplicação\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"Não foi possível criar servidor de RDP \"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"Não foi possível iniciar o servidor de RDP\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"Não foi possível começar o servidor de RDP\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"A partilhar o ambiente de trabalho com %s\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"Parar a apresentação\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"Não foi possível iniciar a partilha de aplicação \"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"Todo o ambiente de trabalho\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"Monitor a partilhar\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"Móvel\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"Estado\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Calendário\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"Reunião em\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"Reunião sobre\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"Nota de fora do escritório\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"Notas\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"Nivel de acesso \"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"Encontrados %d contactos%s:\"\nmsgstr[1] \"Encontrados %d contactos%s:\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \"(mais correspondente à sua consulta)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"Nenhum contacto encontrado\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"Impossivel de apresentar resultados da pesquisa \"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"Pesquisa por contato falhou\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"Comando de procura de contacto inválido\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"Tornar líder de '%s'\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"Remover de '%s'\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"Convidar para '%s'\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"Novo chat\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"Trabalhar\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Home\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"Outro\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"Custom1\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"Enviar email...\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"Tomar controle do ambiente de trabalho\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"Dar controle do ambiente de trabalho\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"Partilhar o meu ambiente de trabalho\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Livre\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"Tentativa\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Ocupado\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"Fora do escritório\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"Sem data\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"Atualmente %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"Fora das horas de trabalho nas próximas 8 horas\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s para as próximas 8 horas\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"Não funciona\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s até %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s. Fora das horas de trabalho de  %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s. %s at %.2d:%.2d\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"Pedido de certificado para %s falhou\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"Solicitação da Web bilhete para %s falhou\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"Chat #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"Falhou a entrada na conferência\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"Não foi possível encontrar o URI da conferência nesta página\\n\\n%s\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\\\"%s\\\" não é um URI de conferência válido\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"Informação de conferência incompleta \"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\\n\\nComo este cliente não foi compilado com suporte a chamadas de voz, se você aceitar, você poderá entrar em contato com os outros participantes da sessão somente via IM.\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"deseja convidá-lo para uma chamada de conferência%s\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"Esta conferência não é mais protegida. Participantes adicionais podem agora juntar-se.\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"Esta conferência está bloqueada. Ninguém mais pode participar na conferência, enquanto esta estiver bloqueada.\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"Você foi desconectado desta conferência.\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"Informação de número Dial-in\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"Número\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"ID da conferência \"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"Link da reunião\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"Organizador\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"Números alternativos de dial-in\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"Um plugin de terceiros implementa versão estendida do SIP / SIMPLE usado por vários produtos\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"Homepage\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"Apoiar\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"Forum de Ajuda\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"Reportar problemas\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"Bug Tracker\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"Traduções\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"Licença\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"Por favor, ajude-nos a traduzir SIPE à sua língua nativa aqui no\"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \"utilizar web interface conviniente \"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"Autores\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"Textos originais em Inglês (en): desenvolvedores SIPE\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"Utilizador de SIP Exchange contém caracteres inválidos\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"Nome do utilizador deve ser um URI SIP\\nExemplo: user@company.com\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"Palavra passe é necessária quando o Single Sign-on não está activo\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"Endereço de e-mail deve ser válido se especificado\\nExemplo: user@company.com\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"SIP Exchange contém espaços em branco\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"URL serviços de e-mail deve ser válido se especificados\\nExample: https://exchange.corp.com/EWS/Exchange.asmx\\nExample: https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"Localização:\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"Leitura de Socket falhou\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"Chave de criptografia recebida tem tamanho errado.\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"Chave recebida de  hash tem tamanho errado.\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"Não foi possível criar socket de escuta\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"Ocorreu um erro\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"Erro ao criar o fluxo de dados\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"Escrita de Socket falhou\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"Tamanho do arquivo é diferente do valor anunciado.\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"Endereço de MAC recebido  está corrompido\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"Arquivo recebido está corrompido\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"Transferência de arquivos de inicialização falhou.\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"Autenticação de transferência de arquivo falhou.\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"Sem memória\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Outros Contactos\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"Definições de Chat Proxy de grupo estão incorrectas:\\n\\n<span class=\\\"whitespace other\\\" title=\\\"Tab\\\">»</span>%s\\n\\nPor favor actualize a sua conta.\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"Não foi possível localizar o servidor de bate-papo do grupo!\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"Esta mensagem não foi entregue ao chat room '%s'\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"Erro lista sala de recuperação\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"Erro juntando sala de chat\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"Falhou o convite %s\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"Recebeu uma mensagem com conteúdo não reconhecido de %s\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"Não foi possível criar stream\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"conexão esgotada\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"Solicitação expirada\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"Não foi possível atender a chamada\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"Não é possível estabelecer a chamada\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"Configurações de criptografia de pares são incompatíveis com o nossa.\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"Utilizador %s rejeitou a chamada\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"Chamada rejeitada\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"Erro ao criar fluxo de áudio\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"Erro ao criar fluxo de vídeo\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"Entrar em chamada de conferência\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"Chamadas de conferência não são suportadas neste servidor\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"Número de telefone inválido\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"Serviço de Testes de Áudio não está disponível.\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"Usuário não está disponível\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s não quer ser incomodado\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"%s usuário não está disponível\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"Tipo de média não suportado\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"Erro de Media\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"Erro durante a leitura do fluxo\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"Já está ligado noutro local\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"Utilizador desabilitado\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"Utilizador movido\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"Bloqueado\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"Pessoal\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"Equipa\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Empresa\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"Público\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"Desconhecido\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"Unspecify\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"Pessoas na minha empresa\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"Pessoas em domínios conectados com a minha empresa\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"Pessoas em dominios publicos \"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"Pessoas em %s\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"Adicionar novo domínio... \"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"Ajuda Online...\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"Grupos de acesso \"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Inativo\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"Ocupado-Ocioso\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Volto já\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"Ausente para almoço\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"Numa chamada\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"Numa conferência\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"Numa reunião\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"Apenas interrupções urgentes\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"Apresentando\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"Subscrição de presença falhou!\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"Um ou mais amigos irão por isso aparecer como offline permanentemente..\\n\\nPor favor verifique que não existem SIP URIs corrompidos na sua lista de contactos.\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"Inicialização UCS falhou!\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"Não foi possível encontrar um servidor Exchange com as configurações Email fornecidas na configuração de conta. Como tal a lista de contactos não funcionará.\\n\\nNecessita de fornecer as configurações Email na configuração de conta.\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"Não foi possível encontrar um servidor Exchange com as configurações Email fornecidas na configuração de conta. Como tal a lista de contactos não funcionará.\\n\\nPor favor corriga as configurações Email.\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"A sua mensagem ou convite não foram entregues, possivelmente porque o contém um link ou outro conteúdo bloqueado pelo administrador\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"Esta mensagem não foi entregue a %s porque o serviço não está disponível.\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"Esta mensagem não foi entregue a %s porque um ou mais recipientes não quer ser distribuído \"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"Esta mensagem não foi entregue a %s porque um ou mais recipientes não suporta este tipo de mensagem\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"Esta mensagem não foi entregue a %s um ou mais recipientes porque estão offline\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Nome de exibição\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"Titulo profissional\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"Cidade\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"Estado\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"Escritorio \"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"País\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"Telefone profissional\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"Endereço de email\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"Site\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"pseudônimo\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"Dispositivo\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"tu\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"Dominio \"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"Adicionar Dominio \"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"Adicionar\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"Cancelar\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"Copiar para\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Bloquear\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Desbloquear\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"Mostrar apresentação\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"Reunião Informação de entrada\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"_URI:\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"Utilizadores\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"Convidar\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"Privado\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"Log\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"Descrição\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"Assunto da conversa: %s\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Mensagem\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"A ligar\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"Palavra-chave necessária\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"user@company.com\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"Número de telefone\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"Chamar um número de telefone\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"_Chamar\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"_Cancelar\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"Local da reunião\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"Alternativamente\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"Email do organizador\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"ID da reunião\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"Entrar na conferência\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"Entrar na conferência agendada\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"Introduza a frase da localização da reunião que recebeu no convite.\\n\\nUma localização válida será algo como\\nmeet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nconf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nou\\nhttps://meet.company.com/someone/abcdef1234\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"_Entrar\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"A publicação da informação do calendário foi desativada\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"Sobre plugin SIPE...\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"Pesquisar contacto...\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"Chamar um número de telefone...\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"Chamada de teste\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"Junte-se conferência agendada ...\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"Re-publicar calendario \"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"Redefinir o estado\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Servidor [: porta]\\n (deixe em branco para auto-descoberta)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"Tipo de conexão\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Automático\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"User Agent\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"Esquema de autenticação\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"Kerberos\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Utilizar Single Sign-On\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"Não publicar a minha informação de calendário\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"Mostrar imagem de perfil da web\\n(potencialmente perigoso)\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"URL serviços de e-mail \\n(deixe em branco para auto-descoberta)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"Endereço de email\\n (se for diferente do nome do utilizador)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"Login E-mail\\n (se diferente do Login)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"Password de e-mail\\n(se diferente da Password)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"Proxy de chat de grupo \\n   company.com ou user@company.com \\n(deixe em branco para determinar a partir de nome de utilizador)\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"Cliente de desktop remoto\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"Encriptação do média\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"Obedecer à política do servidor\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"Sempre\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"Opcional\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"Desactivado\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"Login\\n   utilizador  ou  DOMINIO\\\\utilizador  ou\\n   user@company.com\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"Nome do utilizador\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"Nome\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"Email\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"Primeiro nome\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Sobrenome\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"ID de SIP\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Pesquisar\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"Procurar por um contacto\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"Digite informações sobre a pessoa que você deseja encontrar. Campos vazios serão ignorados.\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_Procurar\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"Erro de leitura\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"Servidor foi desligado\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"Não foi possível conectar\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"Não foi possível criar contexto SSL\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"Não foi possível criar socket\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"Erro de escrita\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"OK\"\n"
  },
  {
    "path": "po/pt_BR.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Anibal Avelar <debianmx@gmail.com>, 2011-2012\n# M3741 <luiz.linux@gmail.com>, 2018\n# M3741 <luiz.linux@gmail.com>, 2018\n# M3741 <luiz.linux@gmail.com>, 2018\n# Raul Liota da Rosa <raul.liota@gmail.com>, 2013,2017\n# Raul Liota da Rosa <raul.liota@gmail.com>, 2013\n# Stefan Becker <chemobejk@gmail.com>, 2011\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-11-28 18:41+0000\\n\"\n\"Last-Translator: M3741 <luiz.linux@gmail.com>\\n\"\n\"Language-Team: Portuguese (Brazil) (http://www.transifex.com/stefanb/pidgin-sipe/language/pt_BR/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: pt_BR\\n\"\n\"Plural-Forms: nplurals=2; plural=(n > 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"A autenticação com o servidor falhou\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"Não é possível solicitar o certificado de %s\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"Nenhuma URI para o serviço de provisionamento certificado provida\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"Falha de autenticação\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"Um esquema de autenticação incompatível foi escolhido\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"Você foi rejeitado pelo servidor: %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"nenhum motivo especificado\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"Não encontrado: %s. Por favor, entre em contato com seu Administrador de Rede.\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"SIP não está habilitado para a URI de destino ou a mesma não existe\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"Serviço indisponível: %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"Mensagem corrompida recebida\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"Assinatura da mensagem inválida recebida\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"%s quer iniciar uma apresentação\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"Aceitar\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"Recusar\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"Erro de compartilhamento na aplicação\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"Cliente de área de trabalho remota desconhecido.\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"Aplicação de compartilhamento não consegue conectar\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"Não foi possível criar servidor RDP.\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"Não foi possível inicializar servidor RDP.\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"Não foi possível iniciar servidor RDP.\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"Compartilhando a área de trabalho com %s\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"Finalizar a apresentação.\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"Não foi possível inicar o compartilhamento de aplicações\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"Toda a área de trabalho\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"Monitor a ser compartilhado\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"Celular\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"Status\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Calendário\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"Reunião em\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"Reunião sobre\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"Mensagem de ausência temporária\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"Nota\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"O nível de acesso\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"%d contato%s encontrado:\"\nmsgstr[1] \"%d contatos%s encontrados:\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" (mais correspondências à sua consulta)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"Nenhum contato encontrado\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"Não foi possível exibir os resultados da busca\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"Busca de contato falhou\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"Consulta inválida de pesquisa de contato\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"Tornar líder de '%s'\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"Remover de '%s'\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"Convidar a '%s'\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"Nova conversa\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"Trabalhar\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Início\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"Outro\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"Custom1\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"Enviar email...\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"Controlar a área de trabalho\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"Conceder controle da área de trabalho\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"Compartilhar minha área de trabalho\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Gratuito\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"Tentativa\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Ocupado\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"Fora do escritório\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"Sem dados\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"Atualmente %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"Fora do horário de trabalho pelas próximas 8 horas\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s pelas próximas 8 horas\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"Não trabalhando\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s até %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s. Fora do horário de trabalho às %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s. %s às %.2d:%.2d\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"Pedido de certificado para %s falhou\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"Solicitação da Web ticket para %s falhou\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"Conversa #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"Falha ao participar da conferência\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"Não foi possível encontrar uma URI de conferência nesta página:\\n\\n%s\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\\\"%s\\\" não é uma URI de conferência válida\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"Informação fornecida da conferência incompleta\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\\n\\nComo esse cliente não foi compilado com suporte a chamadas de voz, se você aceitar, você poderá entrar em contato com os outros participantes da sessão somente via IM.\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"quer convidá-lo para uma teleconferência %s\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"Esta conferência não está mais bloqueada. Demais participantes podem se conectar agora.\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"Esta conferência está bloqueada. Nenhum novo participante pode se conectar enquanto a mesma se encontrar bloqueada.\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"Você foi desconectado desta conferência.\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"Info de discagem\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"Número\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"ID da conferência\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"Link da reunião\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"Organizador\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"Números de discagem alternativos\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"Um plugin desenvolvido por terceiros que implementa uma versão do protocolo SIP/SIMPLE usado por vários produtos\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"Homepage\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"Apoio\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"Fórum de ajuda\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"Reportar problemas\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"Acompanhamento de bugs\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"Traduções\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"Licença\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"Por favor nos ajude a traduzir o SIPE para seu idioma nativo em \"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \"usando uma conveniente interface web\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"Autores\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"Textos originais em Português (pt_BR): ?\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"O nome de usuário SIP Exchange contém caracteres inválidos\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"O nome de usuário deve ser uma URI SIP válida\\nExemplo: usuario@dominio.com\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"A senha é necessária quando o Single Sign-On está habilitado\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"O endereço de email deve ser válido, se fornecido\\nExemplo: usuario@dominio.com\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"O nome de usuario SIP Exchange contém espaços em branco\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"Quando fornecida, a URL de serviços de email deve ser válida\\nExemplo: https://exchange.corp.com/EWS/Exchange.asmx\\nExemplo: https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"Localização:\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"Leitura do socket falhou\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"A chave de criptografia recebida possui um tamanho incorreto.\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"A chave de hash recebida possui um tamanho incorreto.\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"Não foi possível criar socket de escuta\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"Ocorreu um erro\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"Erro ao criar fluxo de dados\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"Escrita no socket falhou\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"O tamanho do arquivo é diferente do valor anunciado.\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"O MAC recebido está corrompido\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"O arquivo recebido está corrompido\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"A inicialização da transferência de arquivo falhou.\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"A autenticação da transferência de arquivos falhou.\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"Esgotamento de memória\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Outros contatos\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"As configurações de proxy para conversas em grupo está incorreta:\\n\\n»%s\\n\\nPor favor, atualize sua conta.\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"Não foi possível encontrar o servidor de conversas em grupo!\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"Esta mensagem não foi enviada a %s porque o serviço se encontra indisponível\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"Falha em obter a lista de salas\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"Erro ao ingressar na conversa\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"O convite a %s falhou\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"Uma mensagem com conteúdo desconhecido for recebida de %s\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"Não foi possível criar transmissão\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"Tempo de conexão esgotado\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"Tempo de requisição esgotado\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"A ligação não pôde ser atendida\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"Não foi possível realizar uma ligação\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"As configurações de criptografia dos pares são incompatíveis com as nossas.\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"O usuário %s rejeitou a ligação\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"Ligação rejeitada\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"Erro ao criar fluxo de áudio\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"Erro ao criar fluxo de vídeo\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"Participar de conferência\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"Teleconferências não são suportadas nesse servidor.\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"Número de telefone inválido\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"O serviço de Teste de Áudio está indisponível.\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"Usuário indisponível\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s não quer ser incomodado\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"O usuário %s está indisponível\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"Tipo de mídia não suportada\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"Erro na mídia\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"Erro durante a leitura do fluxo\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"você já se encontra conectado em outro lugar\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"usuário desabilitado\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"usuário movido\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"Bloqueados\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"Pessoal\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"Equipe\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Empresa\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"Público\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"Desconhecido\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"Indeterminado\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"As pessoas na minha empresa\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"Pessoas em domínios conectados a minha empresa\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"Pessoas em domínios públicos\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"Pessoas em %s\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"Adicionar novo domínio...\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"Ajuda Online\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"Grupos de acesso\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Inativo\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"Ocupado-inativo\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Volto já\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"Saí para almoçar\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"Em uma ligação\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"Em uma conferência\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"Em uma reunião\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"Apenas interrupções urgentes\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"Apresentando\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"Falha na inscrição de assinatura!\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"Um ou mais contatos estão permanentemente offline.\\n\\nVerifique se não há URIs de SIP corrompidas na sua lista de contatos.\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"Inicialização UCS falhou!\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"Não foi possível encontrar um servidor Exchange com as configurações de E-mail padrão. Portanto, a lista de contatos não funcionará.\\nVocê precisa realizar as configurações de E-mail nas configurações de conta.\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"Não foi possível encontrar um servidor Exchange com as configurações providas na configuração de conta. Portanto, a lista de contatos não funcionará.\\n\\nPor favor corrija suas configurações de E-mail.\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"Sua mensagem ou o convite não foi entregue, possivelmente porque ele contém um hiperlink, ou outro conteúdo que o administrador do sistema tenha bloqueado.\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"Esta mensagem não foi enviada a %s porque o serviço se encontra indisponível\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"Esta mensagem não foi enviada a %s porque um ou mais destinatários não querem ser incomodados\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"Esta mensagem não foi entregue ao %s porque um ou mais destinatários não possuem suporte a esse tipo de mensagem\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"Esta mensagem não foi enviada a %s porque um ou mais destinatários estão desconectados\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Nome\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"Cargo\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"Cidade\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"Estado\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"Escritório\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"País\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"Telefone comercial\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"Email\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"Site\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"Apelido\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"Dispositivo\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"você\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"Domínio\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"Adicionar novo domínio\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"Adicionar\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"Cancelar\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"Copiar para\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Bloquear\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Desbloquear\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"Mostrar apresentação\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"Informação de entrada de reunião\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"_URI:\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"Usuários\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"Convidar\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"Privado\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"Log\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"Descrição\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"Assunto da conversa: %s\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Mensagem\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"Conectando\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"Senha requerida\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"usuario@dominio.com\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"Número de telefone\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"Ligar para um número de telefone\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"_Ligar\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"_Cancelar\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"Local da reunião\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"Alternativamente\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"E-mail do organizador\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"ID da reunião\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"Participar da conferência\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"Participar de uma conferência agendada\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"Insira a string de localização da reunião que você recebeu no convite.\\n\\nUma localização válida deve ser algo como\\nmeet:sip:alguem@companhia.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nconf:sip:alguem@companhia.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nou\\nhttps://meet.companhia.com/alguem/abcdef1234\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"_Participar\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"A publicação de informação no calendário foi desabilitada\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"Sobre o plugin SIPE\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"Busca de contatos...\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"Ligar para um número de telefone...\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"Teste de ligação\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"Participar de uma conferência agendada ...\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"Republicar Calendário\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"Reinicializar status\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Servidor[:Porta]\\n(deixar vazio para autoconfiguração)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"Tipo de conexão\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Automático\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"Agente do Usuário\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"Esquema de autenticação\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"Kerberos\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Usar Single Sign-On\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"Não publicar minha informação de calendário\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"Mostrar fotos de perfil da web\\n(potencialmente perigoso)\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"URL dos serviços de Email\\n(deixar vazio para autoconfiguração)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"Endereço de email\\n(se diferente do Nome do Usuário)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"Login do email\\n(se diferente do Login)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"Senha do email\\n(se diferente da Senha)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"Proxy para Conversas em Grupo\\n   companhia.com ou usuario@companhia.com\\n(deixe em branco para determinar a partir de nome do Usuário)\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"Cliente de área de trabalho remota\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"Criptografia de mídia\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"Obedecer a política do servidor\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"Sempre\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"Opcional\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"Desativado\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"Login\\n   usuario ou DOMINIO\\\\usuario ou\\n   usuario@dominio.com\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"Usuário\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"Nome\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"E-mail\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"Nome\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Sobrenome\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"ID SIP\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Buscar\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"Buscar por um contato\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"Insira os dados da pessoa que você deseja encontrar. Campos vazios serão ignorados\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_Buscar\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"Erro de leitura\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"O servidor se desconectou\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"Não foi possível se conectar\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"Não foi possível criar contexto SSL\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"Não foi possível criar socket\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"Erro de gravação\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"OK\"\n"
  },
  {
    "path": "po/ro.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Cristian Măgherușan-Stanciu <cristi.magherusan@gmail.com>, 2012-2013,2015\n# Stefan Becker <chemobejk@gmail.com>, 2013\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 16:09+0000\\n\"\n\"Last-Translator: Stefan Becker <chemobejk@gmail.com>\\n\"\n\"Language-Team: Romanian (http://www.transifex.com/stefanb/pidgin-sipe/language/ro/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: ro\\n\"\n\"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"Nu s-a putut face autentificarea la server\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"Nu s-a putut cere certificatul de la %s\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"Nu a fost configurat nici un URI pentru serviciul de distribuție a certificatelor\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"Autentificarea a eșuat\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"Schema de autentificare este incompatibilă\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"Ați fost refuzat de către server: %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"nu s-a dat nici un motiv\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"Nu s-a putut găsi: %s. Contactați administratorul sistemului\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"Protocolul SIP este dezactivat pentru URI-ul destinație sau acesta nu există\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"Serviciu indisponibil: %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"A fost recepționat un mesaj corupt\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"Semnătura mesajului primit este invalidă\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"Acceptă\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"Refuză\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"Mobil\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"Stare\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Calendar\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"Ședință în\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"Ședință despre\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"Mesaj de absență\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"Notă\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"Nivel de acces\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"S-a găsit %d contact%s:\"\nmsgstr[1] \"S-au găsit %d contacte%s:\"\nmsgstr[2] \"S-au găsit %d contacte%s:\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \"(căutarea a avut mai multe rezultate)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"Nu s-a găsit nimic\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"Nu s-au putut afișa rezultatele căutării\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"Căutarea contactelor a eșuat\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"Căutarea de contacte este invalidă\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"Setează lider pentru '%s'\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"Elimină din '%s'\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"Invită în '%s'\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"Convorbire nouă\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"Muncă\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Acasă\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"Altceva\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"Personalizat1\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"Trimite e-mail\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Liber\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"Încerc\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Ocupat\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"În afara serviciului\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"Nu există date\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"Momentan %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"În afara programului de lucru pentru următoarele 8 ore\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s pentru următoarele 8 ore\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"Nu lucrez\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s până la %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s. În afara orelor de serviciu la %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s. %s la %.2d:%.2d\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"Cererea certificatului către %s a eșuat\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"Cererea pentru ticketul web către %s a eșuat\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"Conversație #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"Nu s-a putut conecta in conferință\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\\\"%s\\\" este un URI de conferință invalid\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\\n\\nDeoarece clientul a fost compilat fără suport audio, în cazul în care acceptați, veți putea contacta pe ceilalți participanți doar prin mesaje scrise.\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"Această conferință nu mai este închisă. Alți participanți pot să se alăture începând de acum.\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"Această conferință este închisă. Nimeni nu mai poate să se alăture până la deschidere.\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"Ați fost deconectat din această conferință\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"Un modul adițional care implementează o versiune extinsă a protocolului  SIP/SIMPLE utilizat de diverse produse\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"Pagină de start\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"Suport tehnic\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"Forum de ajutor\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"Raportați Probleme\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"Urmărirea Erorilor\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"Traduceri\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"Licență\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"Vă rugăm să ne ajutați traducând SIPE în limba dvs. aici \"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \" folosind o interfață web prietenoasă\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"Autori\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"Texte originale în engleză(en): dezvoltatorii SIPE\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"Numele de utilizator SIP Exchange conține caractere invalide\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"Numele de utilizator ar trebui să fie un URI valid de SIP\\nExemplu: utilizator@companie.com\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"Parola este necesară dacă opțiunea Single Sign-On nu este activată\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"Adresa de e-mail ar trebui să fie validă, dacă a fost introdusă\\nExemplu: utilizator@companie.com\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"Numele de utilizator SIP Exchange conține spații\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"URL-ul serviciilor de e-mail trebuie să fie valid, dacă a fost introdus\\nExemplu: https://exchange.corp.com/EWS/Exchange.asmx\\nExemplu: https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"Locație:\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"Primirea datelor prin rețea a eșuat\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"Cheia de criptare primită are dimensiunea greșită.\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"Suma de control primită are dimensiunea greșită.\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"Nu s-a putut crea soclul de ascultare prin rețea\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"Trimiterea datelor prin rețea a eșuat\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"Dimensiunea fișierului este diferită față de cea așteptată\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"MAC-ul primit este corupt\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"Fișierul primit este corupt\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"Inițializarea transferului de fișiere a eșuat.\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"Autentificarea pentru transferul de fișiere a eșuat\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"Memorie insuficientă\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Alte contacte\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"Opțiunea de proxy pentru conversațiile în grup este greșită:\\n\\n\\t%s\\n\\nVă rog să vă actualizați configurația contului.\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"Nu s-a putut găsi serverul pentru conversațiile în grup!\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"Acest mesaj nu a fost livrat in camera de chat '%s'\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"Eroare la primirea listei camerelor de chat\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"Eroare la intrarea in camera de chat\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"Nu s-a putut invita %s\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"S-a primit un mesaj cu conținut recunoscut de la %s\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"Nu s-a putut stabili apelul\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"Configurarea de criptare a partenerului de conversație este incompatibilă cu a dvs.\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"Utilizatorul %s a respins apelul\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"Apel respins\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"Eroare la crearea semnalului audio\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"Eroare la crearea semnalului video\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"Sună în conferință\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"Acest server nu oferă suport pentru teleconferințe\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"Număr de telefon invalid\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"Serviciul de testare a apelurilor audio este indisponibil\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"Utilizator indisponibil\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s nu dorește să fie deranjat\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"Utilizatorul %s nu este disponibil\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"Tip nesuportat\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"sunteți deja conectat dintr-o altă locație\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"utilizator dezactivat\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"utilizator mutat\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"Blocat\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"Personal\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"Echipă\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Companie\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"Public\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"Necunoscut\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"Elimină\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"Oameni din companie\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"Oameni din domenii conectate cu compania mea\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"Oameni din domenii publice\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"Oameni de la %s\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"Adaugă domeniu nou...\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"Ajutor online\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"Grupuri de acces\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Inactiv\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"Ocupat-Absent\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Revin imediat\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"La masă\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"Într-un apel\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"Într-o conferință\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"Într-o ședință\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"Întrerupeți doar în caz de urgență\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"Mesajul sau invitația nu s-a putut trimite, probabil conține un link sau alt tip de conținut care este blocat de către administratorul sistemului.\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"Acest mesaj nu a fost livrat la %s deoarece serviciul este indisponibil\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"Acest mesaj nu a fost livrat la %s deoarece cel puțin unul dintre destinatari nu dorește să fie deranjat\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"Acest mesaj nu a fost livrat la %s deoarece unul dintre destinatari nu suportă acest tip de mesaj\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"Acest mesaj nu a fost livrat la %s deoarece cel puțin unul dintre destinatari este deconectat\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Nume de afișat\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"Titlul job-ului\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"Oraș\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"Județ\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"Birou\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"Țara\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"Telefon de serviciu\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"Adresă de e-mail\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"Site\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"Alias\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"Dispozitiv\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"dvs.\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"Domeniu\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"Adaugă domeniu nou\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"Adaugă\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"Anulează\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"Copiază în\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Blochează\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Deblochează\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"_URI:\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"Utilizatori\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"Invită\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"Privat\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"Jurnal\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"Descriere\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"Subiectul conversației: %s\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Mesaj\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"Conectare\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"Parola este necesară\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"utilizator@companie.com\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"Număr de telefon\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"Apelează un număr de telefon\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"_Apelează\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"_Anulează\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"Locația întâlnirii\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"Intră în conferință\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"Intră în conferință planificată\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"Introduceți locația întâlnirii pe care ați primit-o în invitație.\\n\\nExemplu de locație validă: \\nmeet:sip:cineva@companie.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nconf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nsau\\nhttps://meet.companie.com/cineva/abcdef1234\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"_Intră\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"Publicarea orarului personal a fost dezactivată\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"Despre modulul SIPE...\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"Caută contacte...\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"Apelează un număr de telefon...\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"Apel de test\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"Intră într-o conferință planificată...\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"Publică din nou calendarul\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"Resetează statusul\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Server[:Port]\\n(lăsați gol pentru a se descoperi in mod automat)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"Tipul conexiunii\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Automat\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"Agent de utilizator\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"Un modul adițional care implementează o versiune extinsă a protocolului  SIP/SIMPLE utilizat de diverse produse\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"Kerberos\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Utilizați autentificarea unică\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"Nu publica orarul personal\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"URL-ul serviciilor de e-mail\\n(lăsați gol pentru a se descoperi in mod automat)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"Adresă de e-mail\\n(dacă diferă de numele de utilizator)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"Nume de utilizator pentru e-mail\\n(dacă diferă de numele de utilizator SIPE)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"Parola de e-mail\\n(dacă diferă de parola SIPE)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"Proxy pentru convorbiri de grup\\n   companie.com  say  utilizator@companie.com\\n(lăsați liber pentru a se determina din numele de utilizator)\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"Autentificare\\n   utilizator  sau  DOMENIU\\\\utilizator  sau\\n   utilizator@companie.com\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"Nume de utilizator\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"Numele\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"E-mail\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"Prenumele\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Numele\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"Identificator SIP\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Caută\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"Caută un contact\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"Introduceți informații despre persoana pe care o căutați. Câmpurile goale vor fi ignorate.\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_Caută\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"Eroare la citire\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"Serverul s-a deconectat\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"Nu s-a putut conecta\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"Nu s-a putut stabili sesiunea SSL\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"Nu s-a putut crea slotul\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"Eroare la scriere\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"\"\n"
  },
  {
    "path": "po/ru.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Amber <amber.really@gmail.com>, 2011\n# Gennadiy Zolotaryov <g.zolotaryov@gmail.com>, 2018\n# Ivan Gromov <summer.is.gone@gmail.com>, 2016\n# someone328 <someone328@gmail.com>, 2011\n# Stefan Becker <chemobejk@gmail.com>, 2011\n# Ivan Gromov <summer.is.gone@gmail.com>, 2015\n# G0LDEN_key <the.golden.key@gmail.com>, 2013,2015\n# Дмитрий Д. <dalinger4life@gmail.com>, 2017\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-25 10:11+0000\\n\"\n\"Last-Translator: Gennadiy Zolotaryov <g.zolotaryov@gmail.com>\\n\"\n\"Language-Team: Russian (http://www.transifex.com/stefanb/pidgin-sipe/language/ru/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: ru\\n\"\n\"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"Не удалось проверить подлинность сервера\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"Невозможно запросить сертификат от %s\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"Нет URI для сертификата\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"Ошибка аутентификации\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"Выбрана несовместимая схема проверки подлинности пользователя\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"Вы были отклонены сервером: %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"причина не указана\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"Не найден: %s. Пожалуйста, обратитесь к администратору\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"SIP-адрес либо не включен для URI назначения либо не существует\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"Сервис недоступен: %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"Получено искажённое сообщение\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"Получена недопустимая подпись сообщения\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"%s желает начать презентацию\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"Принять\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"Отклонить\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"Ошибка совместного использования приложения\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"Неизвестный клиент удаленного рабочего стола настроен.\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"Не удалось подключить общий доступ к приложению\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"Не удалось создать RDP-сервер.\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"Не удалось инициализировать RDP-сервер.\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"Не удалось запустить RDP-сервер.\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"Совместное использование рабочего стола с %s\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"Остановить представление\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"Не удалось инициализировать совместное использование приложения\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"Весь рабочий стол\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"Монитор для совместного использования\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"Мобильный\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"Состояние\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Календарь\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"Место собрания\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"Тема собрания\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"Сообщение \\\"Нет на работе\\\"\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"Личное сообщение\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"Уровень доступа\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"Найден %d один контакт %s :\"\nmsgstr[1] \"Найдено несколько %d контактов %s :\"\nmsgstr[2] \"Найдены %d другие контакты %s :\"\nmsgstr[3] \"Найдены %d другие контакты %s :\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" (большее соответствие вашему запросу)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"Контакты не найдены\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"Не удается отобразить результаты поиска\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"Поиск контактов неудачен\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"Неверный запрос поиска контакта\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"Сделать ведущим '%s'\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"Удалить из '%s'\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"Пригласить в '%s'\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"Новый чат\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"Рабочий\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Домашняя страница\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"Другой\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"Свой тип\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"Отправить сообщение электронной почты...\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"Получить управление рабочим столом\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"Предоставить управление рабочим столом\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"Совместное использование моего рабочего стола\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Свободен\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"Под вопросом\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Занят\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"Нет на месте\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"Нет данных\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"в настоящий момент %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"Нерабочее время в течение следующих 8 часов\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s в течение следующих 8 часов\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"не работаю\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s до %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s. Нерабочее время в %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s. %s в %.2d:%.2d\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"Не удалось запросить сертификат %s\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"Не удачный запрос вебтикета %s \"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"Чат #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"Не удалось присоединиться к конференции\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"URL aдрес конференции отсутствует на этой странице:\\n\\n%s\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\\\"%s\\\" не верный URI конференции\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"Предоставлена неполная информация о конференции\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\\n\\nДанное приложение не поддерживает голосовых звонков, если вы согласитесь, вы будете иметь возможность связаться с другими участниками только через сеанс обмена мгновенными сообщениями.\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"хочет пригласить вас на конференцию %s\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"Конференция разблокирована. Новые участники могут присоединиться.\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"Конференция заблокирована. Пока доступ к конференции заблокирован, к ней не могут присоединяться новые участники.\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"Ведущий конференции удалил вас из конференции.\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"Информация о подключении по телефону\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"Номер\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"Идентификатор конференции\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"Сылка на собрание\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"Организатор\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"Другие номера для дозвона\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"Независимый плагин реализующий расширенную версию SIP/SIMPLE используемую в таких продуктах, как\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"Домашняя страничка\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"Поддержка\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"Форум\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"Сообщить о проблеме\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"База дефектов\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"Страница локализации\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"Лицензия\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"Пожалуйста, помогите нам перевести SIPE на Ваш родной язык здесь \"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \" с помощью удобного веб-интерфейса\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"Авторы\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"Русский перевод (ru): pier11, g.zolotaryov@gmail.com\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"Имя пользователя содержит недопустимые символы\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"Имя пользователя должно быть верным SIP URI\\nПример: user@company.com\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"Если не включен Single Sign-On, требуется пароль\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"Адрес электронной почты должен быть верным если введен\\nПример: user@company.com\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"Имя пользователя не может содержать пробелы\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"URL службы электронной почты должен быть верным, если введен\\nПример: https://exchange.corp.com/EWS/Exchange.asmx\\nПример: https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"Место:\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"Не удалось прочитать из сокета\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"Принятый ключ шифрования имеет неверный размер.\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"Принятый ключ хеширования имеет неверный размер.\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"Не удалось создать сокет для прослушивания\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"Произошла ошибка\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"Ошибка при создании потока данных\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"Не удалось записать в сокет\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"Размер файла отличается от заявленного.\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"Принятая подпись повреждена\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"Принятый файл поврежден\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"Инициализация передачи файлов не удалась.\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"Не удалось проверить подлинность при передаче файла.\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"Недостаточно памяти\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Другие контакты\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"Настройки прокси для групппового чата не верны:\\n\\n»%s\\n\\nПожалуйста измените настройки аккаунта.\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"Сервер группового чата не найден!\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"Сообщение не было доставлено в чат канал '%s'\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"Не удалось \"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"Ошибка подключения к чату\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"Не удалось пригласить %s\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"Поступило сообщение неподдерживаемого типа от %s\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"Не удалось создать стрим\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"Время на соединение истекло\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"Истекло время запроса\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"Не удалось ответить на вызов\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"Не удалось сделать вызов\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"Настройки шифрования собеседника несовместимы с нашими.\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"Пользователь %s отклонил вызов\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"Вызов отклонен\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"Ошибка при создании аудио потокa\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"Ошибка при создании видео потокa\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"Присоединиться к конференции\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"Этот сервер не поддерживает конференции\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"Неверный номер телефона\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"Служба аудиотеста недоступна\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"Пользователь недоступен\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s не хочет, чтобы его беспокоили\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"Пользователь %s недоступен\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"Неподдерживаемый тип носителя\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"Ошибка данных\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"Ошибка чтения из потока\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"Вы уже вошли в систему в другом месте\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"пользователь отключен\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"пользователь перемещен\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"Заблокирован\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"Личный\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"Группа\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Компания\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"Общедоступный\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"Неизвестный\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"Не определять\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"Пользователи в моей организации\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"Пользователи в доменах, подключенных к моей организации\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"Пользователи в общедоступных доменах\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"Пользователи в %s\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"Добавить новый домен...\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"Онлайн помощь...\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"Группы доступа\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Неактивен\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"Занят-Неактивен\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Скоро вернусь\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"На обеде\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"Говорю по телефону\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"На конференции\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"На собрании\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"Беспокоить только по срочным делам\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"Представление\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"Ошибка присутствия!\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"Поэтому один или несколько собеседников будут постоянно отображаться как офлайн.\\n\\nУбедитесь, что в списке контактов нет некорректных SIP URI.\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"Ошибка инициализации USC.\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"Не удалось найти сервер Exchange с настройками Email по умолчанию. Из-за этого список контактов не будет работать.\\n\\nНеобходимо указать настройки Email в конфигурации учётной записи.\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"Не удалось найти сервер Exchange с указанными настройками Email. Из-за этого список контактов не будет работать.\\n\\nНеобходимо исправить настройки Email.\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"Ваше сообщение или приглашение не было доставлено. Возможно, оно содержит гиперссылку или другое содержимое, заблоктрованное системным администратором.\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"Сообщение не доставлено %s, потому что сервис недоступен\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"Сообщение не доставлено %s, поскольку один или нескольно получателей были недоступны\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"Это сообщение не было доставлено %s, поскольку один или нескольно получателей не поддерживают данный тип сообщения\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"Сообщение не доставлено %s, поскольку один или нескольно получателей были не в сети\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Отображаемое имя\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"Должность\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"Город\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"Штат\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"Офис\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"Страна\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"Рабочий телефон\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"Адрес электронной почты\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"Сайт\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"Псевдоним\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"Устройство\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"Вас\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=%D0%A3%D1%80%D0%BE%D0%B2%D0%BD%D0%B8_%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF%D0%B0\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"Домен\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"Добавить новый домен\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"Добавить\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"Отмена\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"Скопировать в\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Заблокировать\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Разблокировать\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"Показать презентацию\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"Информация о собрании\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"_URI:\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"Пользователи\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"Пригласить\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"Приват\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"Лог\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"Описание\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"Тема обсуждения: %s\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Сообщение\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"Установка соединения\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"Требуется пароль\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"user@company.com\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"Номер телефона\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"Позвонить по номеру телефона\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"_Вызов\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"О_тменить\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"Место совещания\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"Другие варианты\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"Email организатора\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"Идентификатор собрания\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"Присоединиться к конференции\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"Присоедениться к запланированной конференции\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"Укажите место встречи из полученного Вами приглашения\\nКорректное место встречи выглядит примерно так:\\nmeet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nconf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nлибо\\nhttps://meet.company.com/someone/abcdef1234\\n \"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"_Регистрация\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"Публикация данных из календаря выключена\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"О плагине SIPE...\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"Поиск контактов...\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"Позвонить по номеру телефона...\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"Тестовый звонок\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"Регистрация на запланированной конференции ...\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"Опубликовать календарь\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"Сбросить состояние\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Сервер[:Порт]\\n(оставьте пустым для авто-обнаружения)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"Тип подключения\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Автоматически\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"Агент пользователя\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"Схема проверки подлинности \"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"Kerberos\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Использовать Single Sign-On\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"Не публиковать данные из моего календаря\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"Показывать картинки профиля из web\\n(потенциально опасно)\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"URL службы электронной почты\\n(оставьте пустым для авто-обнаружения)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"Адрес электронной почты\\n(если отличен от Имени пользователя)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"Логин электронной почты\\n(если отличен от Логина)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"Пароль электронной почты\\n(если отличен от Пароля)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"Прокси пруппового чата \\ncompany.com или user@company.com \\n(оставьте пустым, чтобы использовать \\\"Имя пользователя\\\")\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"Клиент удалённого рабочего стола\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"Шифрование данных\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"Следовать политике сервера\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"Всегда\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"Не обязательно\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"Отключен\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"Логин\\n   user  или  DOMAIN\\\\user  или\\n   user@company.com\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"Имя пользователя\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"Имя\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"Email\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"Имя\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Фамилия\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"SIP ID\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Искать\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"Поиск контактов\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"Введите информацию о человеке, которого вы хотите найти. Пустые поля будут игнорироваться.\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_Искать\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"Ошибка чтения\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"Сервер прервал соединение\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"Не удалось установить соединение\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"Не удалось создать контекст SSL\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"Не удалось создать сокет\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"Ошибка записи\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"OK\"\n"
  },
  {
    "path": "po/sv.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Göran Uddeborg <goeran@uddeborg.se>, 2014-2015,2017-2018\n# Karl-Johan Karlsson <karl.johan.karlsson@gmail.com>, 2015-2016\n# Stefan Becker <chemobejk@gmail.com>, 2011\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 20:43+0000\\n\"\n\"Last-Translator: Göran Uddeborg <goeran@uddeborg.se>\\n\"\n\"Language-Team: Swedish (http://www.transifex.com/stefanb/pidgin-sipe/language/sv/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: sv\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"Misslyckades att autentisera till servern\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"Kan inte begära certifikat ifrån %s\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"Ingen URI för tjänsten som tillhandahåller certifikat gavs\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"Autentiseringen misslyckades\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"Inkompatibelt autentiseringsschema valt\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"Du nekades av servern: %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"ingen motivering angiven\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"Hittades inte: %s. Vänligen kontakta administratören\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"SIP är antingen inte aktiverad för den destinationen (URI) eller så den finns inte\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"Tjänsten är ej tillgänglig: %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"Ett trasigt meddelande togs emot\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"En ogiltig meddelandesignatur togs emot\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"%s vill börja presentera\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"Godta\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"Neka\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"Programdelningsfel\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"Okänd klient för fjärrskrivbord konfigurerad.\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"Kunde inte ansluta till programdelning\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"Kunde inte skapa en RDP-server.\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"Kunde inte initiera RDP-servern.\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"Kunde inte starta RDP-servern.\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"Delar skrivbord med %s\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"Avsluta presentationen\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"Kunde inte initiera delningen av programmet\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"Hela skrivbordet\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"Monitor att dela\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"Mobil\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"Status\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Kalender\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"Möte om\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"Möte gällande\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"Inte på kontoret - Notifiering\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"Notifiering\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"Åtkomst nivå\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"Hittade %d kontakt%s:\"\nmsgstr[1] \"Hittade %d kontakter%s:\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" (flera matchade din fråga)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"Inga kontakter hittade\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"Det går inte att visa sökresultatet.\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"Kontaktsökningen misslyckades\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"Ogiltig kontaktsökningsfråga\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"Gör ledare av ”%s”\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"Ta bort från ”%s”\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"Bjud in till ”%s”\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"Ny chatt\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"Arbete\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Hem\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"Annat\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"Anpassad1\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"Skicka e-post …\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"Ta kontroll över skrivbordet\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"Ge bort kontrollen över skrivbordet\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"Dela mitt skrivbord\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Ledig\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"Preliminärt\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Upptagen\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"Inte på kontoret\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"Inga uppgifter\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"För närvarande %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"Utanför arbetstid (närmsta 8 timmarna)\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s (närmsta 8 timmarna)\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"Fungerar ej\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s till och med %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s. Utanför arbetstid mellan %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s. %s till %.2d%.2d\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"Certifikatsbegäran av %s misslyckades\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"Webbiljettsbegäran av %s misslyckades\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"Chatt nr. %d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"Misslyckades att gå med i konferensen\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"Kan inte hitta någon konferens-URI på denna sida:\\n\\n%s\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"”%s” är inte en giltig konferens-URI\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"Ofullständig konferens information angiven\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\\n\\nEftersom denna klient inte kompilerades med stöd för röstsamtal kommer du, om du godtar, bara kunna kontakta de andra deltagarna via IM-sessioner.\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"vill bjuda in dig till ett konferenssamtal%s\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"Denna konferens är inte längre låst. Ytterligare deltagare kan nu gå med.\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"Denna konferens är låst. Ingen annan kan delta i konferensen medan den är låst.\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"Du har kopplats bort från denna konferens.\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"Inkommande information\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"Nummer\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"Konferens-ID\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"Möteslänk\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"Organisatör\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"Alternativa inkommande nummer\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"En tredje parts tillägg med stöd för den utökade versionen av SIP/SIMPLE som kan användas av olika produkter\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"Hemsida\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"Support\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"Hjälpforum\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"Rapportera fel\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"Felhanteringssystem\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"Översättningar\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"Licenser\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"Hjälp oss att översätta sipe till ditt modersmål här på \"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \" med ett bekvämt webbgränssnitt\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"Författare\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"Originaltexter på Engelska (en): SIPE-utvecklarna\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"SIP Exchange-användarnamn innehåller ogiltiga tecken\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"Användarnamnet måste vara ett giltigt SIP URI\\nExempel: user@company.com\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"Lösenord krävs när Single Sign-on inte är aktiverat\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"E-postadressen bör vara giltig enligt nedan\\n\\nExempel: user@company.com\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"SIP Exchange-användarnamn får inte innehålla blanksteg\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"E-tjänstens webbadress ska vara giltig om det föreskrivs\\n\\nExempel: https://exchange.corp.com/EWS/Exchange.asmx\\n Exempel: https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"Plats:\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"Uttagsläsning misslyckades\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"Mottagen krypteringsnyckel har fel storlek.\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"Mottagen hash-nyckel har fel storlek.\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"Det gick inte att skapa lyssnaruttag\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"Ett fel inträffade\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"Fel när dataström skapades\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"Uttagsskrivning misslyckades\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"Filstorleken skiljer sig från dess annonserade värde.\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"Mottagen MAC är felaktig\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"Mottagna filen är skadad\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"Filöverföringens initiering misslyckades.\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"Filöverföringens autentisering misslyckades.\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"Slut på minne\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Övriga Kontakter\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"Inställningen för mellanserver för gruppchatt är felaktig:\\n\\n\\t%s\\n\\nUppdatera ditt konto.\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"Kunde inte hitta gruppchattservern!\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"Detta meddelande levererades inte till chattrummet ”%s”\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"Fel när rumslistan hämtades\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"Fel vid anslutning till chattrummet\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"Misslyckades att bjuda in %s\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"Meddelande mottaget med okänt innehåll från %s\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"Kunde inte skapa en ström\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"Anslutningen gick ut\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"Begäran gick ut\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"Anropet kunde inte besvaras\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"Kan inte etablera ett samtal\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"Krypteringsinställningarna hos motparten är inkompatibla med våra.\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"Användare %s avvisade samtalet\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"Samtalet avvisades\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"Fel när audioströmmen skapades\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"Fel när videoströmmen skapades\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"Anslut till konferenssamtal\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"Konferenssamtal stödjs inte av denna servern\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"Felaktigt telefonnummer\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"Audiotesttjänsten är inte tillgänglig.\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"Användare ej tillgänglig\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s vill inte bli störd\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"Användare %s är inte tillgänglig\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"Ej stödd mediatyp\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"Mediafel\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"Fel vid läsning från strömmen\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"du är redan är inloggad på en annan plats\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"användaren inaktiverad\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"användaren flyttad\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"Blockerad\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"Personligt\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"Team\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Företag\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"Publikt\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"Okänt\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"Ospecificerad\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"Personer i mitt företag\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"Personer i domäner kopplade till mitt företag\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"Personer i offentliga domäner\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"Personer i %s\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"Lägg till en ny domän …\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"Online hjälp …\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"Anslut grupper\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Inaktiv\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"Upptagen\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Strax tillbaka\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"På lunch\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"I ett telefonsamtal\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"I en konferens\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"I ett möte\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"Enbart brådskade ärenden får avbryta\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"Presenterar\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"Närvaroprenumerationen misslyckades!\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"En eller flera kompisar kommer därför att permanent visas som frånkopplade.\\n\\nKontrollera att det inte finns några trasiga SIP URI:er i din kontaktlista.\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"UCS-initiering misslyckades!\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"Kunde inte hitta en Exchange-server med standard E-postinställningar.  Därför kommer kontaktlistan inte att fungera.\\n\\nDu behöver ange E-postinställningar i kontoinställningen.\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"Kunde inte hitta en Exchange-server med E-postinställningarna som gavs i kontoinställningen.  Därför kommer kontaktlistan inte att fungera.\\n\\nRätta dina E-postinställningar.<\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"Ditt meddelande eller en inbjudan har inte levererats, möjligen eftersom den innehåller en hyperlänk eller annat innehåll som systemadministratören har blockerat.\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"Detta meddelande har inte levererats till %s eftersom tjänsten tillfälligt inte är tillgänglig.\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"Detta meddelande har inte levereras till %s eftersom en eller flera mottagare inte vill bli störda.\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"Detta meddelande har inte levererats till %s eftersom en eller flera mottagare inte stödjer denna typ av meddelande\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"Detta meddelande har inte levereras till %s eftersom en eller flera mottagare är inte tillgängliga (Offline)\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Visa namn\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"Befattning\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"Stad\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"Stat/Region\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"Kontor\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"Land\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"Arbetstelefon\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"E-postadress\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"Plats\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"Initialer\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"Enhet\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"Du\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"Domän\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"Lägg till ny domän\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"Lägg till\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"Avbryt\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"Kopiera till\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Lås\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Lås upp\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"Visa presentationen\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"Mötespostinformation\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"_URI:\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"Användare\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"Bjud in\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"Privat\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"Logg\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"Beskrivning\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"Konversationsämne: %s\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Meddelande\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"Ansluter\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"Lösenord krävs\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"anvandare@foretag.se\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"Telefonnummer\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"Ring ett telefonnummer\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"_Ring\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"_Avbryt\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"Mötesplats\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"Alternativt\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"Organisatörens e-post\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"Mötes-ID\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"Gå med i konferens\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"Gå med i en schemalagd konferens\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"Ange mötesplatssträngen du tog emot i inbjudan.\\n\\nGiltig plats skall vara någonting som\\nmeet:sip:person@foretag.se;gruu;opaque=app:conf:focus:id:abcdef1234\\nconf:sip:person@foretag.se;gruu;opaque=app:conf:focus:id:abcdef1234\\neller\\nhttps://meet.foretag.se/person/abcdef1234\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"_Gå med\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"Publicering av kalenderinformation har inaktiverats\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"Om SIPe plugin …\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"Kontaktsökning …\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"Ring ett telefonnummer …\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"Testring\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"Gå med i en schemalagd konferens …\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"Återpublicera kalender\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"Återställ status\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Server[:port]\\n(lämna tomt för automatiskt upptäckande)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"Anslutningstyp\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Automatiskt\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"Användaragent\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"Autenticeringsmetod\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"Kerberos\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Använd ”Single Sign-On”\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"Publicera inte min kalenderinformation\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"Visa profilbilder från webben\\n(potentiellt farligt)\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"E-post tjänstens URL\\n(lämna tomt för automatiskt upptäckande)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"E-post adress\\n(om annan än Användarnamn)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"E-post inloggningsnamn\\n (om annan än Inloggningsnamn)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"E-post lösenord\\n(om annan än lösenord)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"Mellanserver för gruppchatt\\n   foretag.se  eller  person@foretag.se\\n(lämna tomt för att bestämma från Username)\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"Fjärrskrivbordsklient\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"Mediakryptering\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"Följ serverpolicyn\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"Alltid\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"Optionell\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"Avstängd\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"Inloggningsnamn\\n user eller DOMÄN\\\\ \\\\user eller\\n user@company.com\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"Användarnamn\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"Namn\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"E-post\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"Förnamn\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Efternamn\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"SIP ID\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Sök\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"Sök efter kontakt\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"Ange information om personen som du vill hitta. Tomma fält ignoreras.\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_Sök\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"Läsfel\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"Servern har kopplat ifrån\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"Det gick inte att ansluta\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"Det gick inte att skapa SSL-kontext\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"Kunde inte skapa en socket\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"Skrivfel\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"OK\"\n"
  },
  {
    "path": "po/ta.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Navaneethasankar K, 2018\n# Stefan Becker <chemobejk@gmail.com>, 2011\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 16:09+0000\\n\"\n\"Last-Translator: Stefan Becker <chemobejk@gmail.com>\\n\"\n\"Language-Team: Tamil (http://www.transifex.com/stefanb/pidgin-sipe/language/ta/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: ta\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"உள்நுழைவு தோல்வியடைந்தது\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"வழங்கியால் நீங்கள் மறுக்கப்பட்டீர்கள்: %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"காரணம் தரப்படவில்லை\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"ஏற்க\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"மறு\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"கைபேசி\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"நிலை\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"நாட்காட்டி\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"குறிப்பு\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"அணுகல் நிலை\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"தொடர்புகள் ஏதும் இல்லை\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"தேடல் முடிவுகளை காட்ட முடியவில்லை\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"தொடர்புகளுக்கான தேடல் தோல்வியடைந்தது\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"தவறான தொடர்புகளுக்கான தேடல்\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"%s ஐ தலைவராக்கு\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"%s ல் இருந்து நீக்கு\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"%s க்கு அழை\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"புதிய அரட்டை\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"பணி\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"வீடு\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"மற்றவை\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"தனிப்பயன்1\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"மின்னஞ்சல் அனுப்பு...\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"வெட்டி\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"தற்காலிகம்\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"பிஸி\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"அலுவலகத்தில் இல்லை\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"தகவல் இல்லை\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"தற்போது %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"அடுத்த 8 மணி நேரத்திற்கு வேலை நேரம் இல்லை\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s அடுத்த 8 மணி நேரத்திற்கு\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"வேலை செய்யவில்லை\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s %.2d:%.2d வரை\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%.2d:%.2dல்%s.%s \"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"%sக்கு சான்றிதழ் கோரிக்கை தோல்வியடைந்தது\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"%sக்கு இணைய சீட்டு கோரிக்கை தோல்வியடைந்தது\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"அரட்டை #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"கூட்டாலோசனை சேர்க்கை தோல்வியடைந்தது\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"எண்\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"கூட்டாலோசனை அடையாள எண்\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"சந்திப்பு உரலி\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"அமைப்பாளர்\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"வேறு தொடர்பு எண்கள்\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"உதவி\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"\"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \"\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"கேட்கும் கொள்குழி (சாக்கெட்) ஐ உருவாக்க முடியவில்லை!\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"நிறுவனம்\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"நாடு\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"செய்தி\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"இணைத்தல்\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"தானாக\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"பயனர் உதவியாளர்\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"பெயர்\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"மின் அஞ்சல்\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"தேடுக\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_தேடுக\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"இணைக்க முடியவில்லை\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"\"\n"
  },
  {
    "path": "po/te.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 16:09+0000\\n\"\n\"Last-Translator: Stefan Becker <chemobejk@gmail.com>\\n\"\n\"Language-Team: Telugu (http://www.transifex.com/stefanb/pidgin-sipe/language/te/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: te\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"\"\nmsgstr[1] \"\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"\"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \"\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"\"\n"
  },
  {
    "path": "po/tr.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# onur <astrosmurfie@yahoo.co.uk>, 2013,2015-2018\n# onur <astrosmurfie@yahoo.co.uk>, 2012\n# Stefan Becker <chemobejk@gmail.com>, 2013\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-11-06 20:57+0000\\n\"\n\"Last-Translator: onur <astrosmurfie@yahoo.co.uk>\\n\"\n\"Language-Team: Turkish (http://www.transifex.com/stefanb/pidgin-sipe/language/tr/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: tr\\n\"\n\"Plural-Forms: nplurals=2; plural=(n > 1);\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"Sunucuda kimlik doğrulaması yapılamadı\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"%s'den sertifika istenemiyor \"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"Sertifika sağlama servisi için URI belirtilmedi\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"Kimlik doğrulaması başarısız oldu\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"Seçilen kimlik doğrulama düzeni uygun değildir\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"Sunucu tarafından reddedildiniz: %s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"bir neden bildirilmedi\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"Bulunamadı: %s. Lütfen yöneticinize başvurun\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"SIP, hedef URI için etkin değil veya mevcut değil\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"Servis kullanılamıyor: %s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"Hatalı bir ileti alındı\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"Geçersiz ileti imzası alındı\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"%s sunum yapmak istiyor\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"Kabul et\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"Reddet\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"Uygulama paylaşım hatası\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"Bilinmeyen bir uzak masaüstü istemcisi tanımlanmış.\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"Uygulama paylaşımına bağlanılamıyor.\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"RDP sunucusu oluşturulamadı.\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"RDP sunucusu başlatılamadı.\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"RDP sunucusu başlatılamadı.\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"Masaüstü %s ile paylaşılıyor\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"Sunumu durdur\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"Uygulama paylaşımı başlatılamadı\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"Tüm masaüstü\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"Paylaşılacak ekran\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"Cep\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"Durum\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"Takvim\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"Toplantı yeri\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"Toplantı konusu\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"\\\"Ofis dışında\\\" notu\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"Not\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"Erişim düzeyi\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"%d kişi bulundu%s:\\n%d kişi bulundu%s:\"\nmsgstr[1] \"%d kişi bulundu%s:\\n%d kişi bulundu%s:\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \"(aramanız daha fazla sonuç verdi)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"Aranan kişi bulunamadı\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"Arama sonuçları görüntülenemiyor\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"Kişi araması başarısız oldu\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"Hatalı  kişi arama sorgusu\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"'%s' adlı kişiyi lider yap\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"'%s'den çıkar\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"'%s'e davet et\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"Yeni sohbet\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"İş\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"Ev\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"Diğer\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"Özel1\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"E-posta gönder...\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"Masaüstü kontrolünü devral\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"Masaüstü kontrolünü devret\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"Masaüstümü paylaş\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"Serbest\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"Kesin değil\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"Meşgul\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"Ofis dışında\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"Veri yok\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"Şu anda %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"Gelecek 8 saat boyunca çalışma saatleri dışında\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"Gelecek 8 saat boyunca %s\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"Çalışmıyor\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%.2d:%.2d'e kadar %s\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s. %.2d:%.2d çalışma saatleri dışında\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s. %.2d:%.2d itibarıyla %s\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"%s için sertifika isteği başarısız oldu\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"%s için web bileti isteği başarısız oldu\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"Sohbet #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"Konferansa katılım yapılamadı\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"Bu sayfada konferans için bir URI bulunamadı:\\n\\n\\n%s\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\\\"%s\\\" geçerli bir konferans URI değil\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"Girilen konferans bilgisi yetersiz\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\\n\\nBu program ses desteği olmadan derlenmiş olduğundan, eğer kabul ederseniz, diğer kişilerle sadece mesajlaşarak iletişim kurabileceksiniz.\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"seni %s konferans görüşmesine davet etmek istiyor\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"Bu görüşme artık kilitli değil. Başkaları da katılabilir. \"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"Bu görüşme kilitli. Görüşme kilitli olduğu sürece başka kimse katılamaz.\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"Bu görüşmeyle bağlantınız kesildi.\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"Arama bilgisi\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"Numara\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"Konferans kimliği\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"Toplantı bağlantısı\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"Düzenleyen\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"Alternatif arama numaraları\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"Birçok ürün tarafından kullanılan SIP/SIMPLE'ın genişletilmiş sürümünü uygulayan bir üçüncü taraf eklentisi\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"Kişisel Web Sayfası\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"Destek\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"Yardım Forumu\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"Sorun Bildir\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"Hata Takibi\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"Çeviriler\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"Lisans\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"Lütfen burada pratik web arayüzünü kullanarak SIPE'ı anadilinize çevirmemize yardımcı olun\"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \"pratik web arayüzünü kullanarak\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"Yazarlar\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"Orijinal metinler İngilizce (en): SIPE geliştiricileri\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"SIP Exchange kullanıcı adı geçersiz karakterler içeriyor\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"Kullanıcı adı geçerli bir SIP URI olmalıdır\\nÖrnek: kullanıcı@firma.com\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"Tek yerden oturum açma etkin değilken şifre gerekmektedir\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"E-posta adresi girilmişse geçerli olmalıdır\\nÖrnek: kullanıcı@firma.com\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"SIP Exchange kullanıcı adı boşluk içeriyor\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"Eğer verilmişse, e-posta servis URLsi geçerli olmalıdır\\nÖrnek: https://exchange.corp.com/EWS/Exchange.asmx\\nÖrnek: https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"Konum:\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"Soketi okurken hata oluştu\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"Alınan şifreleme anahtarının boyutu hatalı.\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"Alınan karma anahtarının boyutu hatalı.\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"Dinleme soketi oluşturulamadı\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"Hata oluştu\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"Veri akışını gerçekleştirirken hata oluştu\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"Sokete yazarken hata oluştu\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"Dosya boyutu belirtilenden farklı.\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"Alınan MAC bozuk durumda\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"Alınan dosya bozuk durumda\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"Dosya aktarımı başlatılamadı.\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"Dosya aktarımı kimlik doğrulaması başarısız oldu.\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"Bellek yetersiz\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"Diğer Kişiler\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"Grup Sohbet Proxy ayarı hatalı:\\n\\n»%s\\n\\nLütfen hesabınızı güncelleyin.\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"Grup Sohbet sunucusu bulunamadı!\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"Bu mesaj '%s' sohbet odasına iletilemedi\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"Oda listesi alınırken hata oluştu\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"Sohbet odasına katılırken hata oluştu\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"%s davet edilemedi\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"%s adresinden tanınmayan içerikli bir mesaj alındı\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"Akış oluşturulamadı\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"Bağlantı zaman aşımına uğradı\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"İstem zaman aşımına uğradı\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"Çağrı cevaplanamadı\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"Çağrı yapılamıyor\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"Karşı tarafın şifreleme ayarları bizimkiyle uyumsuz.\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"%s adlı kullanıcı çağrıyı reddetti\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"Çağrı reddedildi\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"Ses akışını gerçekleştirirken hata oluştu\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"Video akışını gerçekleştirirken hata oluştu\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"Konferans çağrısına katıl\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"Bu sunucuda konferans görüşmeleri desteklenmemektedir.\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"Geçersiz telefon numarası\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"Ses Test Servisi mevcut değil.\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"Kullanıcıya ulaşılamıyor\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s rahatsız edilmek istemiyor\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"%s adlı kullanıcıya ulaşılamıyor\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"Desteklenmeyen ortam türü\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"Ortam hatası\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"Akışı okurken hata oluştu\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"başka bir yerden oturum açmış durumdasınız\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"kullanıcı devre dışı\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"kullanıcı taşınmış\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"Bloke edilmiş\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"Kişisel\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"Takım\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"Şirket\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"Genel\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"Bilinmeyen\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"Belirtme\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"Şirketimdeki kişiler\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"Şirketime bağlı alanlardaki kişiler\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"Genel alanlardaki kişiler\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"%s konumundaki kişiler\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"Yeni alan ekle...\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"Çevrimiçi yardım...\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"Erişim grupları\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"Etkin değil\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"Meşgul-Yerinde değil\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"Hemen dönecek\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"Yemekte\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"Telefonda\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"Konferansta\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"Toplantıda\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"Sadece acil durumlarda\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"Sunum yapılıyor\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"Durum bildiriminde hata oluştu!\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"Bu yüzden bir veya daha fazla arkadaş sürekli olarak çevrimdışı görünecektir.\\nLütfen kişi listenizde hatalı SIP URI'leri olmadığından emin olun.\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"UCS başlatılamadı.\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"Varsayılan E-posta ayarlarıyla bir Exchange sunucusu bulunamadı. Bu nedenle kişi listesi çalışmayacaktır.\\n\\nHesap detaylarında E-posta ayarlarını girmeniz gerekmektedir.\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"Hesap ayarlarında girdiğiniz E-posta ayarlarıyla bir Exchange sunucusu bulunamadı. Bu nedenle kişi listesi çalışmayacaktır.\\n\\nLütfen E-posta ayarlarınızı düzeltin.\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"Mesajınız veya davetiniz iletilemedi. Bunun nedeni sistem yöneticisinin bloke ettigi bir bağlantı veya içerik olabilir.\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"Bu mesaj %s adlı kişiye iletilemedi çünkü servis kullanılamıyor\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"Bu mesaj %s adlı kişiye iletilemedi çünkü bir veya daha fazla alıcı rahatsız edilmek istemiyor\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"Bu mesaj %s adlı kişiye iletilemedi çünkü bir veya daha fazla alıcı bu mesaj türünü desteklemiyor\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"Bu mesaj %s adlı kişiye iletilemedi çünkü bir veya daha fazla alıcı çevrim dışı\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"Görüntü adı\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"İş unvanı\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"Şehir\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"Eyalet\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"Ofis\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"Ülke\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"İş telefonu\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"E-posta adresi\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"Yer\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"Takma ad \"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"Cihaz\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"sen\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"Alan\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"Yeni alan ekle\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"Ekle\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"İptal et\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"Kopyala\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"Kilitle\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"Kilidi kaldır\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"Sunum göster.\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"Toplantı girişi bilgileri\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"_URI:\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"Kullanıcılar\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"Davet et\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"Özel\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"Sistem günlüğü\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"Açıklama\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"Görüşme konusu: %s\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"Mesaj\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"Bağlanıyor\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"Şifre gerekiyor\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"kullanıcı@firma.com\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"Telefon numarası\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"Bir telefon numarası ara\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"_Ara\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"_İptal et\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"Toplantı yeri\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"Alternatif olarak\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"Düzenleyenin e-postası\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"Toplantı kimliği\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"Konferansa katıl\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"Planlanmış konferansa katıl\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"Davetiyede almış olduğunuz toplantı yeri dizinini giriniz.\\n\\nGeçerli toplantı yeri şu şekilde olacaktır:\\nmeet:sip:kişi@firma.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nconf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nveya\\nhttps://meet.firma.com/kişi/abcdef1234\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"_Katıl\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"Takvim bilgisinin yayımlanması durdurulmuştur\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"SIPE eklentisi hakkında...\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"Kişi araması...\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"Bir telefon numarası ara...\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"Test çağrısı\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"Planlanmış konferansa katıl...\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"Takvimi tekrar yayımla\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"Durumu yenile\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"Sunucu[:Bağlantı noktası]\\n(otomatik-bulma için boş bırakın)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"Bağlantı türü\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"Otomatik\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"Kullanıcı Aracısı\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"Kimlik doğrulama düzeni\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"Kerberos\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"Tek yerden oturum açmayı kullan\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"Takvim bilgimi yayımlama\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"Ağdan profil resimlerini göster\\n(güvenlik açığı oluşturabilir)\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"E-posta hizmetleri URL'si\\n(otomatik-bulma için boş bırakın)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"E-posta adresi\\n(Kullanıcı Adı ile aynı değilse)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"E-posta girişi\\n(Giriş Adı ile aynı değilse)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"E-posta şifresi\\n(Şifre ile aynı değilse)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"Grup Sohbet Proxy'si\\nfirma.com veya kullanıcı@firma.com\\n(Kullanıcı Adı üzerinden belirlemek için boş bırakın)\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"Uzak masaüstü istemcisi\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"Ortam şifrelemesi\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"Sunucu ilkerine uy\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"Her zaman\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"İsteğe bağlı\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"Devre dışı\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"Giriş Adı\\nkullanıcı veya ALAN\\\\kullanıcı veya\\nkullanıcı@firma.com\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"Kullanıcı adı\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"İsim\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"E-posta\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"Ad\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"Soyad\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"SIP Kimliği\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"Ara\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"Bir kişiyi ara\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"Bulmak istediğiniz kişiyle ilgili bilgileri girin. Boş alanlar göz ardı edilecektir.\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"_Ara\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"Okuma hatası\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"Sunucu bağlantısını kesti\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"Bağlanamadı\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"SSL ortamı oluşturulamadı\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"Soket oluşturulamadı\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"Yazma hatası\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"Tamam\"\n"
  },
  {
    "path": "po/transifex-pot-fixup.pl",
    "content": "#!/usr/bin/perl -w\n#\n# Fix up pidgin-sipe.pot after an update to make it acceptable for Transifex\n#\n# Transifex update procedure:\n#\n#    $ cd po\n#    $ intltool-update --pot -g pidgin-sipe     # update POT file\n#    $ ./transifex-pot-fixup.pl                 # this script\n#    $ cd ..\n#    $ tx push -s                               # update POT file on Transifex\n#\n#    [optional: update the languages you know on Transifex]\n#\n#    $ tx pull -s                               # fetch updated translations\n#    $ git add -u po/*.po po/*.pot              # add files to next commit\n#    $ git commit -e\n#\nuse 5.008;\nuse strict;\nuse warnings;\n\nopen(my $fh, \"+<\", \"pidgin-sipe.pot\")\n  or die \"$0: can't open POT file: $!\\n\";\n\nmy $date;\n{\n  my(undef, $min, $hour, $mday, $mon, $year) = gmtime(time());\n  $date = sprintf(\"%4d-%02d-%02d %02d:%02d+0000\",\n\t\t  $year + 1900, $mon + 1, $mday, $hour, $min);\n}\n\n# Must be 19 lines (same as header created by intltool-update)\nmy @lines = ( <<\"END_OF_HEADER\"\n# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n#\n#\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\\\n\"\n\"PO-Revision-Date: $date\\\\n\"\n\"Last-Translator: Stefan Becker <chemobejk\\@gmail.com>\\\\n\"\n\"Language-Team: English (http://www.transifex.com/stefanb/pidgin-sipe/language/en/)\\\\n\"\n\"MIME-Version: 1.0\\\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\\\n\"\n\"Content-Transfer-Encoding: 8bit\\\\n\"\n\"Language: en\\\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\\\n\"\nEND_OF_HEADER\n\t    );\n\nwhile (<$fh>) {\n  # skip header\n  next if $. < 20;\n\n  push(@lines, $_);\n}\n\n# Update pot file\nseek($fh, 0, 0)\n  or die \"$0: can't rewind POT file: $!\\n\";\nprint $fh @lines;\nclose($fh)\n  or die \"$0: can't write to POT file: $!\\n\";\n\n# That's all folks\nexit 0;\n"
  },
  {
    "path": "po/zh_CN.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Kyle Wang, 2014-2018\n# Stefan Becker <chemobejk@gmail.com>, 2011\n# Tommy He <lovenemesis@gmail.com>, 2015\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-11-12 09:58+0000\\n\"\n\"Last-Translator: Kyle Wang\\n\"\n\"Language-Team: Chinese (China) (http://www.transifex.com/stefanb/pidgin-sipe/language/zh_CN/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: zh_CN\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"到服务器的认证失败\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"无法从 %s 请求证书\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"未提供证书置备服务的URI\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"认证失败\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"选择了不兼容的认证方案\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"您已被服务器拒绝：%s\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"未给出原因\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"没找到：%s。请和您的管理员联系\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"目标 URI 没有启用 SIP 或不存在\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"服务不可用：%s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"收到损坏的消息\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"收到无效消息签名\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"%s 想要开始演示\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"接受\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"拒绝\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"程序共享错误\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"未知的远程桌面客户端已配置。\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"无法连接程序共享\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"无法创建RDP服务器。\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"无法初始化RDP服务器。\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"无法启动RDP服务器。\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"与%s共享桌面\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"停止演示\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"无法初始化程序共享\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"整个桌面\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"要共享的显示器\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"手机\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"状态\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"日历\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"会议场所\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"会议内容\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"不在办公室备注\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"备注\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"访问级别\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"找到 %d 个联系人%s：\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" （与您的查询越匹配）\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"未找到联系人\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"无法显示搜索结果\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"联系人搜索失败\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"无效的联系人搜索请求\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"设置为“%s”的领导者\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"从“%s”中删除\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"邀请到“%s”\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"新建聊天\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"工作\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"家庭\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"其他\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"自定义 1\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"发送邮件...\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"获取桌面控制\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"授予桌面控制\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"共享我的桌面\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"空闲\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"待定\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"忙碌\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"不在办公室\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"无数据\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"目前为 %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"未来 8 小时为工作以外时间\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"未来 8 小时 %s\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"不工作\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s 直到 %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s。%.2d:%.2d 为工作以外时间\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%1$s。%3$.2d:%4$.2d 为 %2$s\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"向 %s 请求证书失败\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"向 %s 请求票据凭证失败\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"聊天 #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"加入会议失败\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"此页未发现会议 URI：\\n\\n%s\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"“%s”不是合法的会议URI\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"未提供完整的会议信息\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\\n\\n因本客户端编译时未加入语音通话支持，如果您接受，您将只能通过即时消息会话与其他与会者进行联系。\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"想邀请您加入电话会议 %s\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"此会议不再锁定。其他参与者可以加入。\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"此会议被锁定。被锁定时其他人不能加入会议。\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"您已被从会议中断开。\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"拨入信息\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"号码\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"会议 ID\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"会议连接\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"组织者\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"备选拨入号码\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"实现用于多个产品的 SIP/SIMPLE 扩展版本的第三方插件\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"主页\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"支持\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"帮助论坛\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"报告问题\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"缺陷追踪\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"翻译\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"许可证\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"请到这里帮助我们将 SIPE 翻译为您的母语 \"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \" 使用方便的 web 界面\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"作者\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"中文化 (zh_CN): 神州散人，Kyle Wang\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"SIP Exchange 用户名包含无效字符\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"用户名必须是有效的 SIP URI\\n例如：user@company.com\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"禁用单点登录时，需要输入密码\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"如果提供了电子邮件地址那么它应该是有效的\\n例如：user@company.com\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"SIP Exchange 用户名包含空格\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"如果提供电子邮件服务 URL 那么它应该是有效的\\n例如：https://exchange.corp.com/EWS/Exchange.asmx\\n例如：https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"位置：\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"套接字读取失败\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"收到的加密密钥尺寸错误。\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"收到的散列密钥尺寸错误。\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"无法创建侦听套接字\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"发生了错误\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"创建数据流错误\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"套接字写入失败\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"文件尺寸与告知的值不同。\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"收到的 MAC 已损坏\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"收到的文件已损坏\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"文件传输初始化失败。\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"文件传输认证失败。\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"内存不足\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"其他联系人\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"群组聊天代理设置错误：\\n\\n\\t%s\\n\\n请更新您的帐号\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"未找到群组聊天服务器！\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"此消息没有被发送到聊天室“%s”\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"获取聊天室列表发生错误\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"加入聊天室时发生错误\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"邀请 %s 失败\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"从 %s 收到含有无法识别的内容的消息\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"无法创建流\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"连接超时\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"请求超时\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"呼叫无应答\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"无法建立通话\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"节点的加密设置和我们的不兼容。\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"用户 %s 拒绝了通话\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"通话被拒绝\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"创建音频流错误\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"创建视频流错误\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"加入电话会议\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"此服务器不支持电话会议。\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"无效的电话号码\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"音频测试服务不可用。\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"用户不可用\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s 不想被打扰\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"用户 %s 不可用\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"不支持的媒体类型\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"媒体错误\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"流读取错误\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"您已经在另一地点登入\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"用户已禁止\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"用户已移动\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"被屏蔽\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"个人\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"团队\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"公司\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"公共\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"未知\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"未指定\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"我公司里的人\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"连接至我公司的域里的人\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"公共域里的人\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"在 %s 的人\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"新增域...\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"在线帮助...\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"访问组\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"不活动\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"忙碌-发呆\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"马上回来\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"外出就餐\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"接电话中\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"在会议中\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"在会谈中\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"非紧急事件勿扰\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"正在演示\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"在线情况订阅错误！\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"有些好友将一直显示为离线状态。\\n\\n请检查您的联系人列表中有无损坏的SIP URI。\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"UCS初始化失败！\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"未找到默认电子邮件设置的 Exchange 服务器，联系人列表将无法使用。\\n\\n您需要在帐户设置中提供电子邮件设置。\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"未找到帐户设置中电子邮件的 Exchange 服务器，联系人列表将无法使用。\\n\\n请更正您的电子邮件设置。\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"您的消息或邀请没有被发送，原因可能是它包含了被系统管理员屏蔽的链接或其他内容。\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"此消息没有被发送到 %s，因为服务不可用\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"此消息没有被发送到 %s，因为有的收信人不想被打扰\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"此消息没有被发送到 %s，因为有的收信人不支持此消息类型\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"此消息没有被发送到 %s，因为有的收信人不在线\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"显示名称\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"职称\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"城市\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"省份\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"办公室\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"国家\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"工作电话\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"电子邮件地址\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"站点\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"别名\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"设备\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"您\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"域\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"新增域\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"添加\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"取消\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"复制到\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"锁定\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"解锁\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"显示演示\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"会议信息\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"_URI:\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"用户\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"邀请\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"私人\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"日志\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"描述\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"会话主题：%s\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"消息\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"正在连接\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"需要提供密码\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"user@company.com\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"电话号码\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"拨打电话号码\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"拨号(_C)\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"取消(_C)\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"会议地点\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"备选\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"组织者邮件\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"会议 ID\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"加入会议\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"加入预定会议\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"输入您收到的邀请中的会议地点字符串。\\n\\n合法的地址可能为\\nmeet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\nconf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n或者\\nhttps://meet.company.com/someone/abcdef1234\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"加入(_J)\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"已禁用发布日历信息\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"关于 SIPE 插件\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"联系人搜索...\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"拨打电话号码...\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"测试呼叫\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"加入预定会议...\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"重新发布日历\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"复位状态\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"服务器[:端口]\\n(留空使用自动发现)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"连接类型\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"自动\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"用户代理\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"认证方案\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"NTLM\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"Kerberos\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"TLS-DSK\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"使用单点登录\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"不发布我的日历信息\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"显示来自网络的资料图片\\n（有潜在危险）\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"电子邮件服务 URL\\n(留空使用自动发现)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"电子邮件地址\\n(如果与用户名不同)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"电子邮件登录名\\n(如果与登录名不同)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"电子邮件密码\\n(如果与密码不同)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"群组聊天代理\\ncompany.com 或 user@company.com\\n(留空表示根据用户名决定)\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"远程桌面客户端\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"媒体加密\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"遵从服务器策略\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"始终\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"可选\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"禁用\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"登录\\n   用户  或  域\\\\用户  或\\n   user@company.com\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"用户名\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"姓名\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"电子邮件\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"姓\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"名\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"SIP ID\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"搜索\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"搜索联系人\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"输入您要查找的人的信息。空字段将被忽略。\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"搜索(_S)\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"读取错误\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"服务器已断开连接\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"无法连接\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"无法创建 SSL 环境\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"无法创建套接字\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"写入错误\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"确定\"\n"
  },
  {
    "path": "po/zh_TW.po",
    "content": "# (English) English User Interface strings for pidgin-sipe.\n# Copyright (C) 2008-2018 SIPE Project <http://sipe.sourceforge.net/>\n# This file is distributed under the same license as the pidgin-sipe package.\n# \n# \n# \n# Translators:\n# Stefan Becker <chemobejk@gmail.com>, 2011\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pidgin sipe\\n\"\n\"Report-Msgid-Bugs-To: https://sourceforge.net/p/sipe/bugs/\\n\"\n\"POT-Creation-Date: 2010-11-30 23:36+0200\\n\"\n\"PO-Revision-Date: 2018-10-18 16:09+0000\\n\"\n\"Last-Translator: Stefan Becker <chemobejk@gmail.com>\\n\"\n\"Language-Team: Chinese (Taiwan) (http://www.transifex.com/stefanb/pidgin-sipe/language/zh_TW/)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: zh_TW\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\n#: ../src/core/sip-transport.c:241\nmsgid \"Failed to authenticate to server\"\nmsgstr \"由伺服器認證時失敗\"\n\n#: ../src/core/sip-transport.c:299\n#, c-format\nmsgid \"Can't request certificate from %s\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:309\nmsgid \"No URI for certificate provisioning service provided\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1225\nmsgid \"Authentication failed\"\nmsgstr \"認證失敗\"\n\n#: ../src/core/sip-transport.c:1282\nmsgid \"Incompatible authentication scheme chosen\"\nmsgstr \"選擇了不相容的認證方案\"\n\n#: ../src/core/sip-transport.c:1299 ../src/core/sipe-notify.c:1159\n#, c-format\nmsgid \"You have been rejected by the server: %s\"\nmsgstr \"您已被伺服器 %s 拒絕\"\n\n#: ../src/core/sip-transport.c:1300 ../src/core/sip-transport.c:1316\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#: ../src/core/sipe-conf.c:267 ../src/core/sipe-notify.c:1159\nmsgid \"no reason given\"\nmsgstr \"沒有給予原因\"\n\n#: ../src/core/sip-transport.c:1315\n#, c-format\nmsgid \"Not found: %s. Please contact your Administrator\"\nmsgstr \"找不到：%s。請與您的管理員聯絡\"\n\n#: ../src/core/sip-transport.c:1317\nmsgid \"SIP is either not enabled for the destination URI or it does not exist\"\nmsgstr \"SIP 若非未對目的 URI 啟用或是它並不存在\"\n\n#: ../src/core/sip-transport.c:1340 ../src/core/sip-transport.c:1364\n#, c-format\nmsgid \"Service unavailable: %s\"\nmsgstr \"不提供該項服務︰%s\"\n\n#: ../src/core/sip-transport.c:1717\nmsgid \"Corrupted message received\"\nmsgstr \"\"\n\n#: ../src/core/sip-transport.c:1741\nmsgid \"Invalid message signature received\"\nmsgstr \"收到的訊息簽章無效\"\n\n#: ../src/core/sipe-appshare.c:494\n#, c-format\nmsgid \"%s wants to start presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:498 ../src/core/sipe-conf.c:1102\nmsgid \"Accept\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:499 ../src/core/sipe-conf.c:1103\nmsgid \"Decline\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:537 ../src/core/sipe-appshare.c:635\n#: ../src/core/sipe-appshare.c:780 ../src/core/sipe-appshare.c:901\nmsgid \"Application sharing error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:538\nmsgid \"Unknown remote desktop client configured.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:636\nmsgid \"Couldn't connect application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:753\nmsgid \"Could not create RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:770\nmsgid \"Could not initialize RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:772\nmsgid \"Could not start RDP server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:863\n#, c-format\nmsgid \"Sharing desktop with %s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:867\nmsgid \"Stop presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:902\nmsgid \"Couldn't initialize application sharing\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:960\nmsgid \"Whole desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-appshare.c:973\nmsgid \"Monitor to share\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:543 ../src/core/sipe-buddy.c:2334\nmsgid \"Mobile\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:831\nmsgid \"Status\"\nmsgstr \"狀態\"\n\n#: ../src/core/sipe-buddy.c:834\nmsgid \"Calendar\"\nmsgstr \"行事曆\"\n\n#: ../src/core/sipe-buddy.c:839\nmsgid \"Meeting in\"\nmsgstr \"會議舉行於\"\n\n#: ../src/core/sipe-buddy.c:843\nmsgid \"Meeting about\"\nmsgstr \"會議關於\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Out of office note\"\nmsgstr \"不在辦公室註記\"\n\n#: ../src/core/sipe-buddy.c:848\nmsgid \"Note\"\nmsgstr \"註記\"\n\n#: ../src/core/sipe-buddy.c:853 ../src/core/sipe-buddy.c:2407\n#: ../src/purple/purple-buddy.c:634\nmsgid \"Access level\"\nmsgstr \"存取等級\"\n\n#: ../src/core/sipe-buddy.c:1076\n#, c-format\nmsgid \"Found %d contact%s:\"\nmsgid_plural \"Found %d contacts%s:\"\nmsgstr[0] \"找到 %d 位聯絡人%s︰\"\n\n#: ../src/core/sipe-buddy.c:1078\nmsgid \" (more matched your query)\"\nmsgstr \" (更多符合您查詢的項目)\"\n\n#: ../src/core/sipe-buddy.c:1124 ../src/core/sipe-buddy.c:1262\n#: ../src/core/sipe-ucs.c:318\nmsgid \"No contacts found\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1137 ../src/core/sipe-buddy.c:1275\n#: ../src/core/sipe-ucs.c:282\nmsgid \"Unable to display the search results\"\nmsgstr \"無法顯示搜尋結果\"\n\n#: ../src/core/sipe-buddy.c:1240 ../src/core/sipe-buddy.c:1252\n#: ../src/core/sipe-ucs.c:395\nmsgid \"Contact search failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:1415 ../src/core/sipe-ucs.c:399\nmsgid \"Invalid contact search query\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2271\n#, c-format\nmsgid \"Make leader of '%s'\"\nmsgstr \"成為「%s」的召集人\"\n\n#: ../src/core/sipe-buddy.c:2284\n#, c-format\nmsgid \"Remove from '%s'\"\nmsgstr \"從「%s」移除\"\n\n#: ../src/core/sipe-buddy.c:2298\n#, c-format\nmsgid \"Invite to '%s'\"\nmsgstr \"邀請參加「%s」\"\n\n#: ../src/core/sipe-buddy.c:2314\nmsgid \"New chat\"\nmsgstr \"新的聊天室\"\n\n#: ../src/core/sipe-buddy.c:2327\nmsgid \"Work\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2342\nmsgid \"Home\"\nmsgstr \"首頁\"\n\n#: ../src/core/sipe-buddy.c:2350\nmsgid \"Other\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2358\nmsgid \"Custom1\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2368\nmsgid \"Send email...\"\nmsgstr \"發送電子郵件…\"\n\n#: ../src/core/sipe-buddy.c:2385\nmsgid \"Take desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2390\nmsgid \"Give desktop control\"\nmsgstr \"\"\n\n#: ../src/core/sipe-buddy.c:2396 ../src/purple/purple-chat.c:370\nmsgid \"Share my desktop\"\nmsgstr \"\"\n\n#: ../src/core/sipe-cal.c:907\nmsgid \"Free\"\nmsgstr \"免費\"\n\n#: ../src/core/sipe-cal.c:908\nmsgid \"Tentative\"\nmsgstr \"臨時\"\n\n#. SIPE_ACTIVITY_BUSY\n#: ../src/core/sipe-cal.c:909 ../src/core/sipe-status.c:57\nmsgid \"Busy\"\nmsgstr \"忙碌\"\n\n#. SIPE_ACTIVITY_OOF\n#: ../src/core/sipe-cal.c:910 ../src/core/sipe-status.c:68\nmsgid \"Out of office\"\nmsgstr \"不在辦公室\"\n\n#: ../src/core/sipe-cal.c:911\nmsgid \"No data\"\nmsgstr \"沒有資料\"\n\n#: ../src/core/sipe-cal.c:1019 ../src/core/sipe-cal.c:1046\n#, c-format\nmsgid \"Currently %s\"\nmsgstr \"目前 %s\"\n\n#: ../src/core/sipe-cal.c:1025\nmsgid \"Outside of working hours for next 8 hours\"\nmsgstr \"在下一個 8 小時工作時數之外\"\n\n#: ../src/core/sipe-cal.c:1027\n#, c-format\nmsgid \"%s for next 8 hours\"\nmsgstr \"%s 用於下一個 8 小時\"\n\n#: ../src/core/sipe-cal.c:1036\nmsgid \"Not working\"\nmsgstr \"不在工作中\"\n\n#: ../src/core/sipe-cal.c:1040\n#, c-format\nmsgid \"%s until %.2d:%.2d\"\nmsgstr \"%s 直到 %.2d:%.2d\"\n\n#: ../src/core/sipe-cal.c:1048\n#, c-format\nmsgid \"%s. Outside of working hours at %.2d:%.2d\"\nmsgstr \"%s。於 %.2d:%.2d 的工作時數之外\"\n\n#: ../src/core/sipe-cal.c:1053\n#, c-format\nmsgid \"%s. %s at %.2d:%.2d\"\nmsgstr \"%s。%s 於 %.2d:%.2d\"\n\n#: ../src/core/sipe-certificate.c:233 ../src/core/sipe-certificate.c:277\n#, c-format\nmsgid \"Certificate request to %s failed\"\nmsgstr \"\"\n\n#: ../src/core/sipe-certificate.c:284\n#, c-format\nmsgid \"Web ticket request to %s failed\"\nmsgstr \"\"\n\n#. Generate next ID\n#: ../src/core/sipe-chat.c:251\n#, c-format\nmsgid \"Chat #%d\"\nmsgstr \"聊天室 #%d\"\n\n#: ../src/core/sipe-conf.c:266 ../src/core/sipe-conf.c:420\n#: ../src/core/sipe-conf.c:462 ../src/core/sipe-conf.c:514\nmsgid \"Failed to join the conference\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:416\n#, c-format\nmsgid \"\"\n\"Can't find a conference URI on this page:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:459\n#, c-format\nmsgid \"\\\"%s\\\" is not a valid conference URI\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:515\nmsgid \"Incomplete conference information provided\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1122\nmsgid \"\"\n\"\\n\"\n\"\\n\"\n\"As this client was not compiled with voice call support, if you accept, you will be able to contact the other participants only via IM session.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1127\n#, c-format\nmsgid \"wants to invite you to a conference call%s\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1469\nmsgid \"\"\n\"This conference is no longer locked. Additional participants can now join.\"\nmsgstr \"這個會議已不再鎖定。額外參與者現在可以加入。\"\n\n#: ../src/core/sipe-conf.c:1473\nmsgid \"\"\n\"This conference is locked. Nobody else can join the conference while it is \"\n\"locked.\"\nmsgstr \"這個會議已被鎖定。當它被鎖定時，其他任何人都不可以加入會議。\"\n\n#: ../src/core/sipe-conf.c:1506\nmsgid \"You have been disconnected from this conference.\"\nmsgstr \"您已經從這個會議結束連線。\"\n\n#: ../src/core/sipe-conf.c:1661\nmsgid \"Dial-in info\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1662\nmsgid \"Number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1664\nmsgid \"Conference ID\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1666\nmsgid \"Meeting link\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1668\nmsgid \"Organizer\"\nmsgstr \"\"\n\n#: ../src/core/sipe-conf.c:1670\nmsgid \"Alternative dial-in numbers\"\nmsgstr \"\"\n\n#. The next 13 texts make up the SIPE about note text\n#. About note, part 1/13: introduction\n#: ../src/core/sipe-core.c:236\nmsgid \"\"\n\"A third-party plugin implementing extended version of SIP/SIMPLE used by \"\n\"various products\"\nmsgstr \"一個協力廠商的外掛程式，實作了由不同產品所使用的 SIP/SIMPLE 進階版本\"\n\n#. About note, part 2/13: home page URL (label)\n#: ../src/core/sipe-core.c:238\nmsgid \"Home Page\"\nmsgstr \"\"\n\n#. About note, part 3/13: support forum URL (label)\n#: ../src/core/sipe-core.c:240\nmsgid \"Support\"\nmsgstr \"\"\n\n#. About note, part 4/13: support forum name (hyperlink text)\n#: ../src/core/sipe-core.c:242\nmsgid \"Help Forum\"\nmsgstr \"說明論壇\"\n\n#. About note, part 5/13: bug tracker URL (label)\n#: ../src/core/sipe-core.c:244\nmsgid \"Report Problems\"\nmsgstr \"報告問題\"\n\n#. About note, part 6/13: bug tracker URL (hyperlink text)\n#: ../src/core/sipe-core.c:246\nmsgid \"Bug Tracker\"\nmsgstr \"錯誤追蹤者\"\n\n#. About note, part 7/13: translation service URL (label)\n#: ../src/core/sipe-core.c:248\nmsgid \"Translations\"\nmsgstr \"翻譯\"\n\n#. About note, part 8/13: license type (label)\n#: ../src/core/sipe-core.c:250\nmsgid \"License\"\nmsgstr \"授權\"\n\n#. About note, part 9/13: (REMOVED)\n#. About note, part 10/13: translation request, text before Transifex.com URL\n#. append a space if text is not empty\n#: ../src/core/sipe-core.c:254\nmsgid \"Please help us to translate SIPE to your native language here at \"\nmsgstr \"請幫助我們將 SIPE 翻譯為您的原生語言，並在\"\n\n#. About note, part 11/13: translation request, text after Transifex.com URL\n#. start with a space if text is not empty\n#: ../src/core/sipe-core.c:257\nmsgid \" using convenient web interface\"\nmsgstr \" 使用方便的網頁介面\"\n\n#. About note, part 12/13: author list (header)\n#: ../src/core/sipe-core.c:259\nmsgid \"Authors\"\nmsgstr \"作者\"\n\n#. About note, part 13/13: Localization credit\n#. PLEASE NOTE: do *NOT* simply translate the english original\n#. but write something similar to the following sentence:\n#. \"Localization for <language name> (<language code>): <name>\"\n#: ../src/core/sipe-core.c:264\nmsgid \"Original texts in English (en): SIPE developers\"\nmsgstr \"傳統漢語本地化 (zh_TW)：趙惟倫 <chaoweilun@gmail.com>\"\n\n#: ../src/core/sipe-core.c:288\nmsgid \"SIP Exchange user name contains invalid characters\"\nmsgstr \"SIP Exchange 的使用者名稱不可含有無效字元\"\n\n#: ../src/core/sipe-core.c:296 ../src/purple/purple-buddy.c:486\n#: ../src/telepathy/telepathy-protocol.c:89\n#: ../src/telepathy/telepathy-protocol.c:197\n#, c-format\nmsgid \"\"\n\"User name should be a valid SIP URI\\n\"\n\"Example: user@company.com\"\nmsgstr \"使用者名稱應該是有效的 SIP URI\\n範例：user@company.com\"\n\n#: ../src/core/sipe-core.c:303\nmsgid \"Password is required when Single Sign-On is not enabled\"\nmsgstr \"\"\n\n#: ../src/core/sipe-core.c:313\nmsgid \"\"\n\"Email address should be valid if provided\\n\"\n\"Example: user@company.com\"\nmsgstr \"如果提供電子郵件地址應該是有效的\\n範例：user@company.com\"\n\n#: ../src/core/sipe-core.c:322\nmsgid \"SIP Exchange user name contains whitespace\"\nmsgstr \"SIP Exchange 的使用者名稱不可含有空白字元\"\n\n#: ../src/core/sipe-core.c:336\nmsgid \"\"\n\"Email services URL should be valid if provided\\n\"\n\"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\"Example: https://domino.corp.com/maildatabase.nsf\"\nmsgstr \"如果提供電子郵件服務網址應該是有效的\\n範例：https://exchange.corp.com/EWS/Exchange.asmx\\n範例：https://domino.corp.com/maildatabase.nsf\"\n\n#. Translators: (!) should be as in localized Lotus Notes to be able to\n#. extract meeting location\n#: ../src/core/sipe-domino.c:260 ../src/core/sipe-domino.c:261\nmsgid \"Location:\"\nmsgstr \"位置：\"\n\n#: ../src/core/sipe-ft.c:264 ../src/core/sipe-ft-tftp.c:109\n#: ../src/core/sipe-ft-tftp.c:393 ../src/core/sipe-ft-tftp.c:422\n#: ../src/core/sipe-ft-tftp.c:481\nmsgid \"Socket read failed\"\nmsgstr \"通訊端讀取失敗\"\n\n#: ../src/core/sipe-ft.c:412\nmsgid \"Received encryption key has wrong size.\"\nmsgstr \"接收到的加密金鑰大小有誤。\"\n\n#: ../src/core/sipe-ft.c:427\nmsgid \"Received hash key has wrong size.\"\nmsgstr \"接收到的雜湊鍵大小有誤。\"\n\n#: ../src/core/sipe-ft.c:447\nmsgid \"Could not create listen socket\"\nmsgstr \"無法建立監聽通訊端\"\n\n#: ../src/core/sipe-ft-lync.c:762 ../src/core/sipe-media.c:1485\n#: ../src/core/sipe-media.c:1496 ../src/core/sipe-media.c:1576\n#: ../src/core/sipe-media.c:2096\nmsgid \"Error occurred\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-lync.c:763\nmsgid \"Error creating data stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ft-tftp.c:115 ../src/core/sipe-ft-tftp.c:525\n#: ../src/core/sipe-ft-tftp.c:534\nmsgid \"Socket write failed\"\nmsgstr \"通訊端寫入失敗\"\n\n#: ../src/core/sipe-ft-tftp.c:208\nmsgid \"File size is different from the advertised value.\"\nmsgstr \"檔案大小與宣稱的數值不同。\"\n\n#: ../src/core/sipe-ft-tftp.c:247\nmsgid \"Received MAC is corrupted\"\nmsgstr \"接收到的 MAC 已損壞\"\n\n#: ../src/core/sipe-ft-tftp.c:258\nmsgid \"Received file is corrupted\"\nmsgstr \"接收到的檔案已損壞\"\n\n#: ../src/core/sipe-ft-tftp.c:287\nmsgid \"File transfer initialization failed.\"\nmsgstr \"檔案傳送初始化失敗。\"\n\n#: ../src/core/sipe-ft-tftp.c:318\nmsgid \"File transfer authentication failed.\"\nmsgstr \"檔案傳送認證失敗。\"\n\n#: ../src/core/sipe-ft-tftp.c:414 ../src/core/sipe-ft-tftp.c:432\n#: ../src/core/sipe-ft-tftp.c:495\nmsgid \"Out of memory\"\nmsgstr \"記憶體不足\"\n\n#: ../src/core/sipe-group.c:168 ../src/core/sipe-notify.c:1173\n#: ../src/core/sipe-notify.c:1207 ../src/core/sipe-notify.c:1311\n#: ../src/purple/purple-search.c:128\nmsgid \"Other Contacts\"\nmsgstr \"其他聯絡人\"\n\n#: ../src/core/sipe-groupchat.c:329\n#, c-format\nmsgid \"\"\n\"Group Chat Proxy setting is incorrect:\\n\"\n\"\\n\"\n\"\\t%s\\n\"\n\"\\n\"\n\"Please update your Account.\"\nmsgstr \"群組聊天室代理伺服器設不正確：\\n\\n\\t%s\\n\\n請更新您的帳戶。\"\n\n#: ../src/core/sipe-groupchat.c:332\nmsgid \"Couldn't find Group Chat server!\"\nmsgstr \"無法找到\"\n\n#: ../src/core/sipe-groupchat.c:508\n#, c-format\nmsgid \"This message was not delivered to chat room '%s'\"\nmsgstr \"這個訊息未被投遞到聊天室 '%s'\"\n\n#: ../src/core/sipe-groupchat.c:616\nmsgid \"Error retrieving room list\"\nmsgstr \"擷取聊天室清單時發生錯誤\"\n\n#: ../src/core/sipe-groupchat.c:720\nmsgid \"Error joining chat room\"\nmsgstr \"加入聊天室時發生錯誤\"\n\n#. generate one error and remove all unprocessed messages\n#: ../src/core/sipe-im.c:197\n#, c-format\nmsgid \"Failed to invite %s\"\nmsgstr \"邀請 %s 時失敗\"\n\n#: ../src/core/sipe-incoming.c:763\n#, c-format\nmsgid \"Received a message with unrecognized contents from %s\"\nmsgstr \"從 %s 接收到內容無法辨識的訊息\"\n\n#: ../src/core/sipe-media.c:870\nmsgid \"Couldn't create stream\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:871\nmsgid \"Connection timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:915\nmsgid \"Request timed out\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:916\nmsgid \"Call could not be answered\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1007 ../src/core/sipe-media.c:1644\n#: ../src/core/sipe-media.c:1654 ../src/core/sipe-media.c:2074\n#: ../src/core/sipe-media.c:2097\nmsgid \"Unable to establish a call\"\nmsgstr \"無法建立呼叫\"\n\n#: ../src/core/sipe-media.c:1008 ../src/core/sipe-media.c:2075\nmsgid \"Encryption settings of peer are incompatible with ours.\"\nmsgstr \"對方的加密設定值與我們的不相容。\"\n\n#: ../src/core/sipe-media.c:1103\n#, c-format\nmsgid \"User %s rejected call\"\nmsgstr \"使用者 %s 已拒絕呼叫\"\n\n#: ../src/core/sipe-media.c:1104\nmsgid \"Call rejected\"\nmsgstr \"呼叫被拒絕\"\n\n#: ../src/core/sipe-media.c:1486 ../src/core/sipe-media.c:1577\nmsgid \"Error creating audio stream\"\nmsgstr \"建立音訊串流時發生錯誤\"\n\n#: ../src/core/sipe-media.c:1497\nmsgid \"Error creating video stream\"\nmsgstr \"建立視訊串流時發生錯誤\"\n\n#: ../src/core/sipe-media.c:1542 ../src/purple/purple-chat.c:353\nmsgid \"Join conference call\"\nmsgstr \"加入會議談話\"\n\n#: ../src/core/sipe-media.c:1543\nmsgid \"Conference calls are not supported on this server.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1645\nmsgid \"Invalid phone number\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:1655\nmsgid \"Audio Test Service is not available.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2040\nmsgid \"User unavailable\"\nmsgstr \"使用者無法聯繫\"\n\n#: ../src/core/sipe-media.c:2043\n#, c-format\nmsgid \"%s does not want to be disturbed\"\nmsgstr \"%s 不想被打擾\"\n\n#: ../src/core/sipe-media.c:2045\n#, c-format\nmsgid \"User %s is not available\"\nmsgstr \"使用者 %s 無法聯繫\"\n\n#: ../src/core/sipe-media.c:2057\nmsgid \"Unsupported media type\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2421\nmsgid \"Media error\"\nmsgstr \"\"\n\n#: ../src/core/sipe-media.c:2422\nmsgid \"Error while reading from stream\"\nmsgstr \"\"\n\n#. reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n#: ../src/core/sipe-notify.c:1151\nmsgid \"you are already signed in at another location\"\nmsgstr \"您已經在另一個地點登入了\"\n\n#: ../src/core/sipe-notify.c:1153\nmsgid \"user disabled\"\nmsgstr \"使用者已停用\"\n\n#: ../src/core/sipe-notify.c:1155\nmsgid \"user moved\"\nmsgstr \"使用者已移動\"\n\n#: ../src/core/sipe-ocs2007.c:462 ../src/purple/purple-buddy.c:641\n#: ../src/purple/purple-buddy.c:648\nmsgid \"Blocked\"\nmsgstr \"已阻斷\"\n\n#: ../src/core/sipe-ocs2007.c:463 ../src/purple/purple-buddy.c:637\n#: ../src/purple/purple-buddy.c:644\nmsgid \"Personal\"\nmsgstr \"個人\"\n\n#. index 0\n#: ../src/core/sipe-ocs2007.c:464 ../src/purple/purple-buddy.c:638\n#: ../src/purple/purple-buddy.c:645\nmsgid \"Team\"\nmsgstr \"小組\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_COMPANY\n#: ../src/core/sipe-ocs2007.c:465 ../src/purple/purple-buddy.c:76\n#: ../src/purple/purple-buddy.c:639 ../src/purple/purple-buddy.c:646\n#: ../src/purple/purple-search.c:66 ../src/purple/purple-search.c:229\nmsgid \"Company\"\nmsgstr \"公司\"\n\n#: ../src/core/sipe-ocs2007.c:466 ../src/purple/purple-buddy.c:640\n#: ../src/purple/purple-buddy.c:647\nmsgid \"Public\"\nmsgstr \"公用\"\n\n#: ../src/core/sipe-ocs2007.c:468\nmsgid \"Unknown\"\nmsgstr \"不明\"\n\n#. Translators: remove (clear) previously assigned access level\n#: ../src/core/sipe-ocs2007.c:2590\nmsgid \"Unspecify\"\nmsgstr \"未定義\"\n\n#: ../src/core/sipe-ocs2007.c:2609\nmsgid \"People in my company\"\nmsgstr \"公司同事\"\n\n#: ../src/core/sipe-ocs2007.c:2619\nmsgid \"People in domains connected with my company\"\nmsgstr \"與公司有連結的認證域名中的人\"\n\n#: ../src/core/sipe-ocs2007.c:2628\nmsgid \"People in public domains\"\nmsgstr \"位於公共認證域名中的人\"\n\n#: ../src/core/sipe-ocs2007.c:2638\n#, c-format\nmsgid \"People at %s\"\nmsgstr \"位於 %s 中的人\"\n\n#: ../src/core/sipe-ocs2007.c:2663\nmsgid \"Add new domain...\"\nmsgstr \"加入新的認證域名…\"\n\n#: ../src/core/sipe-ocs2007.c:2692\nmsgid \"Online help...\"\nmsgstr \"線上說明…\"\n\n#: ../src/core/sipe-ocs2007.c:2700\nmsgid \"Access groups\"\nmsgstr \"存取群組\"\n\n#. * This has nothing to do with Availability numbers, like 3500 (online).\n#. * Just a mapping of Communicator Activities to tokens/translations\n#. @TODO: NULL means \"default translation from Pidgin\"?\n#. *        What about other backends?\n#. SIPE_ACTIVITY_UNSET\n#. SIPE_ACTIVITY_AVAILABLE\n#. SIPE_ACTIVITY_ONLINE\n#. SIPE_ACTIVITY_INACTIVE\n#: ../src/core/sipe-status.c:56\nmsgid \"Inactive\"\nmsgstr \"非作用中\"\n\n#. SIPE_ACTIVITY_BUSYIDLE\n#: ../src/core/sipe-status.c:58\nmsgid \"Busy-Idle\"\nmsgstr \"忙碌-空閒\"\n\n#. SIPE_ACTIVITY_DND\n#. SIPE_ACTIVITY_BRB\n#: ../src/core/sipe-status.c:60\nmsgid \"Be right back\"\nmsgstr \"馬上回來\"\n\n#. SIPE_ACTIVITY_AWAY\n#. SIPE_ACTIVITY_LUNCH\n#: ../src/core/sipe-status.c:62\nmsgid \"Out to lunch\"\nmsgstr \"外出午餐\"\n\n#. SIPE_ACTIVITY_INVISIBLE\n#. SIPE_ACTIVITY_OFFLINE\n#. SIPE_ACTIVITY_ON_PHONE\n#: ../src/core/sipe-status.c:65\nmsgid \"In a call\"\nmsgstr \"電話中\"\n\n#. SIPE_ACTIVITY_IN_CONF\n#: ../src/core/sipe-status.c:66\nmsgid \"In a conference\"\nmsgstr \"會議中\"\n\n#. SIPE_ACTIVITY_IN_MEETING\n#: ../src/core/sipe-status.c:67\nmsgid \"In a meeting\"\nmsgstr \"談話中\"\n\n#. SIPE_ACTIVITY_URGENT_ONLY\n#: ../src/core/sipe-status.c:69\nmsgid \"Urgent interruptions only\"\nmsgstr \"非急勿擾\"\n\n#. SIPE_ACTIVITY_IN_PRES\n#: ../src/core/sipe-status.c:70\nmsgid \"Presenting\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:193\nmsgid \"Presence subscription failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-subscriptions.c:194\nmsgid \"\"\n\"One or more buddies will therefore permanently show as offline.\\n\"\n\"\\n\"\n\"Please check that there are no corrupted SIP URIs in your contacts list.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:678\nmsgid \"UCS initialization failed!\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:680\nmsgid \"\"\n\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"You'll need to provide Email settings in the account setup.\"\nmsgstr \"\"\n\n#: ../src/core/sipe-ucs.c:681\nmsgid \"\"\n\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\"\n\"\\n\"\n\"Please correct your Email settings.\"\nmsgstr \"\"\n\n#. Service unavailable; Server Internal Error; Server Time-out\n#. Not acceptable all.\n#. Message contents not allowed by policy\n#: ../src/core/sipe-user.c:78\nmsgid \"\"\n\"Your message or invitation was not delivered, possibly because it contains a\"\n\" hyperlink or other content that the system administrator has blocked.\"\nmsgstr \"您的訊息或邀請未被投遞，可能因為它含有超連結或其他內容，所以被系統管理員阻斷。\"\n\n#: ../src/core/sipe-user.c:82\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because the service is not available\"\nmsgstr \"這個訊息未被投遞到 %s，因為服務無法使用\"\n\n#. Busy Here\n#: ../src/core/sipe-user.c:84\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients do not \"\n\"want to be disturbed\"\nmsgstr \"這個訊息未被投遞到 %s，因為一或多位收訊者不想被打擾\"\n\n#. Unsupported media type\n#: ../src/core/sipe-user.c:86\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients don't \"\n\"support this type of message\"\nmsgstr \"這個訊息未被投遞到 %s，因為一或多位收訊者不支援這個訊息型態\"\n\n#: ../src/core/sipe-user.c:88\n#, c-format\nmsgid \"\"\n\"This message was not delivered to %s because one or more recipients are \"\n\"offline\"\nmsgstr \"這個訊息未被投遞到 %s，因為一或多位收訊者在離線狀態\"\n\n#. SIPE_BUDDY_INFO_DISPLAY_NAME\n#: ../src/purple/purple-buddy.c:67\nmsgid \"Display name\"\nmsgstr \"顯示名稱\"\n\n#. SIPE_BUDDY_INFO_JOB_TITLE\n#: ../src/purple/purple-buddy.c:68\nmsgid \"Job title\"\nmsgstr \"職稱\"\n\n#. SIPE_BUDDY_INFO_CITY\n#: ../src/purple/purple-buddy.c:69\nmsgid \"City\"\nmsgstr \"城市\"\n\n#. SIPE_BUDDY_INFO_STATE\n#: ../src/purple/purple-buddy.c:70\nmsgid \"State\"\nmsgstr \"省/州\"\n\n#. SIPE_BUDDY_INFO_OFFICE\n#: ../src/purple/purple-buddy.c:71\nmsgid \"Office\"\nmsgstr \"辦公室\"\n\n#. SIPE_BUDDY_INFO_DEPARTMENT\n#. SIPE_BUDDY_INFO_COUNTRY\n#: ../src/purple/purple-buddy.c:73 ../src/purple/purple-search.c:69\n#: ../src/purple/purple-search.c:231\nmsgid \"Country\"\nmsgstr \"國家/地區\"\n\n#. SIPE_BUDDY_INFO_WORK_PHONE\n#: ../src/purple/purple-buddy.c:74\nmsgid \"Business phone\"\nmsgstr \"業務電話\"\n\n#. SIPE_BUDDY_INFO_EMAIL\n#: ../src/purple/purple-buddy.c:77\nmsgid \"Email address\"\nmsgstr \"電子郵件地址\"\n\n#. SIPE_BUDDY_INFO_SITE\n#: ../src/purple/purple-buddy.c:78\nmsgid \"Site\"\nmsgstr \"站臺\"\n\n#. SIPE_BUDDY_INFO_ZIPCODE\n#. SIPE_BUDDY_INFO_STREET\n#. SIPE_BUDDY_INFO_MOBILE_PHONE\n#. SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_HOME_PHONE\n#. SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_OTHER_PHONE\n#. SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE\n#. SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY\n#. SIPE_BUDDY_INFO_ALIAS\n#: ../src/purple/purple-buddy.c:89\nmsgid \"Alias\"\nmsgstr \"別名\"\n\n#. SIPE_BUDDY_INFO_DEVICE\n#: ../src/purple/purple-buddy.c:90\nmsgid \"Device\"\nmsgstr \"裝置\"\n\n#: ../src/purple/purple-buddy.c:260 ../src/purple/purple-buddy.c:278\nmsgid \"you\"\nmsgstr \"您\"\n\n#: ../src/purple/purple-buddy.c:585\nmsgid \"\"\n\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\nmsgstr \"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"\n\n#: ../src/purple/purple-buddy.c:627\nmsgid \"Domain\"\nmsgstr \"認證域名\"\n\n#: ../src/purple/purple-buddy.c:656 ../src/purple/purple-buddy.c:657\nmsgid \"Add new domain\"\nmsgstr \"加入新的認證域名\"\n\n#: ../src/purple/purple-buddy.c:658\nmsgid \"Add\"\nmsgstr \"加入\"\n\n#: ../src/purple/purple-buddy.c:659 ../src/purple/purple-user.c:141\nmsgid \"Cancel\"\nmsgstr \"取消\"\n\n#: ../src/purple/purple-buddy.c:839\nmsgid \"Copy to\"\nmsgstr \"複製到\"\n\n#: ../src/purple/purple-chat.c:330\nmsgid \"Lock\"\nmsgstr \"鎖定\"\n\n#: ../src/purple/purple-chat.c:335\nmsgid \"Unlock\"\nmsgstr \"解除鎖定\"\n\n#: ../src/purple/purple-chat.c:363\nmsgid \"Show presentation\"\nmsgstr \"\"\n\n#: ../src/purple/purple-chat.c:378\nmsgid \"Meeting entry info\"\nmsgstr \"\"\n\n#: ../src/purple/purple-groupchat.c:56\nmsgid \"_URI:\"\nmsgstr \"網址(_U)：\"\n\n#: ../src/purple/purple-groupchat.c:160\nmsgid \"Users\"\nmsgstr \"使用者\"\n\n#: ../src/purple/purple-groupchat.c:163\nmsgid \"Invite\"\nmsgstr \"邀請\"\n\n#: ../src/purple/purple-groupchat.c:166\nmsgid \"Private\"\nmsgstr \"私人\"\n\n#: ../src/purple/purple-groupchat.c:169\nmsgid \"Log\"\nmsgstr \"記錄\"\n\n#: ../src/purple/purple-groupchat.c:172\nmsgid \"Description\"\nmsgstr \"描述\"\n\n#: ../src/purple/purple-im.c:86\n#, c-format\nmsgid \"Conversation subject: %s\"\nmsgstr \"\"\n\n#. Macro to reduce code repetition\n#. Translators: noun\n#: ../src/purple/purple-plugin-common.c:193\nmsgid \"Message\"\nmsgstr \"訊息\"\n\n#: ../src/purple/purple-plugin-common.c:440\nmsgid \"Connecting\"\nmsgstr \"連線中\"\n\n#: ../src/purple/purple-plugin-common.c:470\nmsgid \"Password required\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:629\nmsgid \"user@company.com\"\nmsgstr \"user@company.com\"\n\n#: ../src/purple/purple-plugin-common.c:748\nmsgid \"Phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:752\n#: ../src/purple/purple-plugin-common.c:753\nmsgid \"Call a phone number\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:756\nmsgid \"_Call\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:757\n#: ../src/purple/purple-plugin-common.c:805 ../src/purple/purple-search.c:240\nmsgid \"_Cancel\"\nmsgstr \"取消(_C)\"\n\n#: ../src/purple/purple-plugin-common.c:784\nmsgid \"Meeting location\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:786\nmsgid \"Alternatively\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:788\nmsgid \"Organizer email\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:790\nmsgid \"Meeting ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:794\nmsgid \"Join conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:795\nmsgid \"Join scheduled conference\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:796\nmsgid \"\"\n\"Enter meeting location string you received in the invitation.\\n\"\n\"\\n\"\n\"Valid location will be something like\\n\"\n\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\"or\\n\"\n\"https://meet.company.com/someone/abcdef1234\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:804\nmsgid \"_Join\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:819\n#: ../src/purple/purple-plugin-common.c:837\nmsgid \"Publishing of calendar information has been disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:856\nmsgid \"About SIPE plugin...\"\nmsgstr \"關於 SIPE 外掛程式…\"\n\n#: ../src/purple/purple-plugin-common.c:859\nmsgid \"Contact search...\"\nmsgstr \"聯絡人搜尋…\"\n\n#: ../src/purple/purple-plugin-common.c:863\nmsgid \"Call a phone number...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:866\nmsgid \"Test call\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:870\nmsgid \"Join scheduled conference...\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:873\nmsgid \"Republish Calendar\"\nmsgstr \"重新發布行事曆\"\n\n#: ../src/purple/purple-plugin-common.c:876\nmsgid \"Reset status\"\nmsgstr \"重置狀態\"\n\n#. *\n#. * When adding new string settings please make sure to keep these\n#. * in sync:\n#. *\n#. *     api/sipe-backend.h\n#. *     purple-settings.c:setting_name[]\n#: ../src/purple/purple-plugin-common.c:894\nmsgid \"\"\n\"Server[:Port]\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"伺服器[:通訊埠]\\n(留空表示自動搜索)\"\n\n#: ../src/purple/purple-plugin-common.c:897\nmsgid \"Connection type\"\nmsgstr \"連線類型\"\n\n#: ../src/purple/purple-plugin-common.c:898\n#: ../src/purple/purple-plugin-common.c:910\nmsgid \"Auto\"\nmsgstr \"自動\"\n\n#: ../src/purple/purple-plugin-common.c:899\nmsgid \"SSL/TLS\"\nmsgstr \"SSL/TLS\"\n\n#: ../src/purple/purple-plugin-common.c:900\nmsgid \"TCP\"\nmsgstr \"TCP\"\n\n#. option = purple_account_option_bool_new(_(\"Publish status (note: everyone\n#. may watch you)\"), \"doservice\", TRUE);\n#. sipe_prpl_info.protocol_options =\n#. g_list_append(sipe_prpl_info.protocol_options, option);\n#: ../src/purple/purple-plugin-common.c:906\nmsgid \"User Agent\"\nmsgstr \"使用者代理\"\n\n#: ../src/purple/purple-plugin-common.c:909\nmsgid \"Authentication scheme\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:911\nmsgid \"NTLM\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:913\nmsgid \"Kerberos\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:915\nmsgid \"TLS-DSK\"\nmsgstr \"\"\n\n#. * When the user selects Single Sign-On then SIPE will ignore the\n#. * settings for \"login name\" and \"password\". Instead it will use the\n#. * default credentials provided by the OS.\n#. *\n#. * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n#. *       SIPE that it is OK to use Single Sign-On or not.\n#. *\n#. * Configurations that are known to support Single Sign-On:\n#. *\n#. *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n#. *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n#. *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n#: ../src/purple/purple-plugin-common.c:933\nmsgid \"Use Single Sign-On\"\nmsgstr \"使用單一登入\"\n\n#. * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n#. *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n#: ../src/purple/purple-plugin-common.c:940\nmsgid \"Don't publish my calendar information\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:943\nmsgid \"\"\n\"Show profile pictures from web\\n\"\n\"(potentially dangerous)\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:946\nmsgid \"\"\n\"Email services URL\\n\"\n\"(leave empty for auto-discovery)\"\nmsgstr \"電子郵件服務網址\\n(留空表示自動搜索)\"\n\n#: ../src/purple/purple-plugin-common.c:949\nmsgid \"\"\n\"Email address\\n\"\n\"(if different from Username)\"\nmsgstr \"電子郵件地址\\n(如果與使用者名稱不同)\"\n\n#. * Example (Exchange): DOMAIN\\user  or  user@company.com\n#. *  Example (Domino)  : email_address\n#: ../src/purple/purple-plugin-common.c:955\nmsgid \"\"\n\"Email login\\n\"\n\"(if different from Login)\"\nmsgstr \"電子郵件帳號\\n(如果與本帳號不同)\"\n\n#: ../src/purple/purple-plugin-common.c:958\nmsgid \"\"\n\"Email password\\n\"\n\"(if different from Password)\"\nmsgstr \"電子郵件密碼\\n(如果與本密碼不同)\"\n\n#. * Example (federated domain): company.com      (i.e. ocschat@company.com)\n#. *  Example (non-default user): user@company.com\n#: ../src/purple/purple-plugin-common.c:965\nmsgid \"\"\n\"Group Chat Proxy\\n\"\n\"   company.com  or  user@company.com\\n\"\n\"(leave empty to determine from Username)\"\nmsgstr \"群組聊天室代理伺服器\\n   company.com  或  user@company.com\\n(留空表示由使用者名稱決定)\"\n\n#: ../src/purple/purple-plugin-common.c:969\nmsgid \"Remote desktop client\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:974\nmsgid \"Media encryption\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:975\nmsgid \"Obey server policy\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:976\nmsgid \"Always\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:977\nmsgid \"Optional\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:978\nmsgid \"Disabled\"\nmsgstr \"\"\n\n#: ../src/purple/purple-plugin-common.c:988\nmsgid \"\"\n\"Login\\n\"\n\"   user  or  DOMAIN\\\\user  or\\n\"\n\"   user@company.com\"\nmsgstr \"帳號\\n  使用者  或  認證域名\\\\使用者  或\\n  user@company.com\"\n\n#: ../src/purple/purple-search.c:60\nmsgid \"User name\"\nmsgstr \"使用者名稱\"\n\n#: ../src/purple/purple-search.c:63\nmsgid \"Name\"\nmsgstr \"名稱\"\n\n#: ../src/purple/purple-search.c:72 ../src/purple/purple-search.c:225\nmsgid \"Email\"\nmsgstr \"電子郵件\"\n\n#: ../src/purple/purple-search.c:221\nmsgid \"First name\"\nmsgstr \"名字\"\n\n#: ../src/purple/purple-search.c:223\nmsgid \"Last name\"\nmsgstr \"姓氏\"\n\n#: ../src/purple/purple-search.c:227\nmsgid \"SIP ID\"\nmsgstr \"\"\n\n#: ../src/purple/purple-search.c:235\nmsgid \"Search\"\nmsgstr \"搜尋\"\n\n#: ../src/purple/purple-search.c:236\nmsgid \"Search for a contact\"\nmsgstr \"搜尋聯絡人\"\n\n#: ../src/purple/purple-search.c:237\nmsgid \"\"\n\"Enter the information for the person you wish to find. Empty fields will be \"\n\"ignored.\"\nmsgstr \"輸入想要尋找的人員資訊。將忽略空白欄位。\"\n\n#: ../src/purple/purple-search.c:239\nmsgid \"_Search\"\nmsgstr \"搜尋(_S)\"\n\n#: ../src/purple/purple-transport.c:153\nmsgid \"Read error\"\nmsgstr \"讀取錯誤\"\n\n#: ../src/purple/purple-transport.c:157\n#: ../src/telepathy/telepathy-transport.c:96\nmsgid \"Server has disconnected\"\nmsgstr \"伺服器已斷線\"\n\n#: ../src/purple/purple-transport.c:285\nmsgid \"Could not connect\"\nmsgstr \"無法連線\"\n\n#: ../src/purple/purple-transport.c:355\nmsgid \"Could not create SSL context\"\nmsgstr \"無法建立 SSL 內容\"\n\n#: ../src/purple/purple-transport.c:377\nmsgid \"Could not create socket\"\nmsgstr \"無法建立通訊端\"\n\n#: ../src/purple/purple-transport.c:473\nmsgid \"Write error\"\nmsgstr \"寫入錯誤\"\n\n#: ../src/purple/purple-user.c:140\nmsgid \"OK\"\nmsgstr \"\"\n"
  },
  {
    "path": "siplcs.vcxproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup Label=\"ProjectConfigurations\">\r\n    <ProjectConfiguration Include=\"Debug Unicode|Win32\">\r\n      <Configuration>Debug Unicode</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Debug|Win32\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release Unicode|Win32\">\r\n      <Configuration>Release Unicode</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|Win32\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n  </ItemGroup>\r\n  <PropertyGroup Label=\"Globals\">\r\n    <ProjectName>siplcs</ProjectName>\r\n    <ProjectGuid>{B86C74FF-7A76-46EA-860C-9AEDD070CEAB}</ProjectGuid>\r\n    <RootNamespace>libsipe</RootNamespace>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\r\n    <UseOfMfc>false</UseOfMfc>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release Unicode|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\r\n    <UseOfMfc>false</UseOfMfc>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <CharacterSet>MultiByte</CharacterSet>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <CharacterSet>MultiByte</CharacterSet>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\r\n  <ImportGroup Label=\"ExtensionSettings\">\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release Unicode|Win32'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <PropertyGroup Label=\"UserMacros\" />\r\n  <PropertyGroup>\r\n    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>\r\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">$(SolutionDir)$(Configuration)/plugins\\</OutDir>\r\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">$(Configuration)\\</IntDir>\r\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">$(SolutionDir)$(Configuration)/Plugins\\</OutDir>\r\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">$(Configuration)\\</IntDir>\r\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Release Unicode|Win32'\">$(SolutionDir)$(Configuration)/Plugins\\</OutDir>\r\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Release Unicode|Win32'\">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\\</IntDir>\r\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'\">$(SolutionDir)$(Configuration)/Plugins\\</OutDir>\r\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'\">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\\</IntDir>\r\n  </PropertyGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <ClCompile>\r\n      <Optimization>Disabled</Optimization>\r\n      <AdditionalIncludeDirectories>$(SolutionDir)/../include;$(ProjectDir)/src/api;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n      <MinimalRebuild>true</MinimalRebuild>\r\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r\n      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r\n      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n    </ClCompile>\r\n    <Link>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <TargetMachine>MachineX86</TargetMachine>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <ClCompile>\r\n      <Optimization>MaxSpeed</Optimization>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r\n      <FunctionLevelLinking>true</FunctionLevelLinking>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r\n    </ClCompile>\r\n    <Link>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <TargetMachine>MachineX86</TargetMachine>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release Unicode|Win32'\">\r\n    <ClCompile>\r\n      <Optimization>Full</Optimization>\r\n      <AdditionalIncludeDirectories>$(SolutionDir)/../include;$(ProjectDir)/src/api;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;PACKAGE_NAME=\"pidgin-sipe\";PACKAGE_VERSION=\"1.25.0\";PACKAGE_URL=\"http://sipe.sourceforge.net/\";PACKAGE_BUGREPORT=\"https://sourceforge.net/p/sipe/bugs/\";SIPE_VERSION=\"1.25.0\";_CRT_SECURE_NO_WARNINGS;HAVE_NSS;HAVE_GMIME;HAVE_VV;ENABLE_NLS;MIRANDA;HAVE_GSSAPI_GSSAPI_H;HAVE_SSPI;SECURITY_WIN32;SIPE_TRANSLATIONS_URL=\"https://www.transifex.com/stefanb/pidgin-sipe/\";%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r\n    </ClCompile>\r\n    <Link>\r\n      <AdditionalDependencies>glib-2.0.lib;gobject-2.0.lib;libxml2.lib;Ws2_32.lib;nss3.lib;smime3.lib;iconv.lib;intl.lib;gmime-2.6.lib;nspr4.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <TargetMachine>MachineX86</TargetMachine>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'\">\r\n    <ClCompile>\r\n      <Optimization>Disabled</Optimization>\r\n      <AdditionalIncludeDirectories>$(SolutionDir)/../include;$(ProjectDir)/src/core;$(ProjectDir)/src/api;$(ProjectDir)/src/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;PACKAGE_NAME=\"pidgin-sipe\";PACKAGE_VERSION=\"1.25.0\";PACKAGE_URL=\"http://sipe.sourceforge.net/\";SIPE_TRANSLATIONS_URL=\"https://www.transifex.com/stefanb/pidgin-sipe/\";PACKAGE_BUGREPORT=\"https://sourceforge.net/p/sipe/bugs/\";SIPE_VERSION=\"1.25.0\";_CRT_SECURE_NO_WARNINGS;HAVE_NSS;HAVE_GMIME;HAVE_VV;ENABLE_NLS;MIRANDA;HAVE_GSSAPI_GSSAPI_H;SECURITY_WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <MinimalRebuild>true</MinimalRebuild>\r\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r\n      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r\n      <ProgramDataBaseFileName>$(TargetDir)$(TargetName).pdb</ProgramDataBaseFileName>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r\n    </ClCompile>\r\n    <Link>\r\n      <AdditionalDependencies>glib-2.0.lib;gobject-2.0.lib;libxml2.lib;Ws2_32.lib;nss3.lib;smime3.lib;nspr4.lib;gmime-2.6-debug.lib;iconv.lib;intl.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <TargetMachine>MachineX86</TargetMachine>\r\n      <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"src\\core\\md4.c\" />\r\n    <ClCompile Include=\"src\\core\\sdpmsg.c\" />\r\n    <ClCompile Include=\"src\\core\\sip-csta.c\" />\r\n    <ClCompile Include=\"src\\core\\sip-sec-basic.c\" />\r\n    <ClCompile Include=\"src\\core\\sip-sec-digest.c\" />\r\n    <ClCompile Include=\"src\\core\\sip-sec-gssapi.c\" />\r\n    <ClCompile Include=\"src\\core\\sip-sec-negotiate.c\" />\r\n    <ClCompile Include=\"src\\core\\sip-sec-ntlm.c\" />\r\n    <ClCompile Include=\"src\\core\\sip-sec-sspi.c\" />\r\n    <ClCompile Include=\"src\\core\\sip-sec-tls-dsk.c\" />\r\n    <ClCompile Include=\"src\\core\\sip-sec.c\" />\r\n    <ClCompile Include=\"src\\core\\sip-soap.c\" />\r\n    <ClCompile Include=\"src\\core\\sip-transport.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-buddy.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-cal.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-certificate.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-cert-crypto-nss.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-chat.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-conf.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-core.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-crypt-nss.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-dialog.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-digest-nss.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-domino.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-ews.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-ews-autodiscover.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-ft-tftp.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-ft.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-group.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-groupchat.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-http.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-http-request.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-http-transport.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-im.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-incoming.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-lync-autodiscover.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-media.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-mime.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-notify.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-ocs2005.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-ocs2007.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-schedule.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-session.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-sign.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-status.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-subscriptions.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-svc.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-tls.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-ucs.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-user.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-utils.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-webticket.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-win32dep.c\" />\r\n    <ClCompile Include=\"src\\core\\sipe-xml.c\" />\r\n    <ClCompile Include=\"src\\core\\sipmsg.c\" />\r\n    <ClCompile Include=\"src\\core\\uuid.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-buddy.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-chat.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-connection.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-debug.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-dnsquery.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-ft.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-groupchat.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-im.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-input.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-markup.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-media.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-network.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-notify.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-plugin.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-schedule.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-search.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-setting.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-status.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-transport.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-user.c\" />\r\n    <ClCompile Include=\"src\\miranda\\miranda-utils.c\" />\r\n    <ClCompile Include=\"src\\miranda\\sipe-miranda.c\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"src\\core\\md4.h\" />\r\n    <ClInclude Include=\"src\\core\\sdpmsg.h\" />\r\n    <ClInclude Include=\"src\\core\\sip-csta.h\" />\r\n    <ClInclude Include=\"src\\core\\sip-sec-basic.h\" />\r\n    <ClInclude Include=\"src\\core\\sip-sec-digest.h\" />\r\n    <ClInclude Include=\"src\\core\\sip-sec-gssapi.h\" />\r\n    <ClInclude Include=\"src\\core\\sip-sec-mech.h\" />\r\n    <ClInclude Include=\"src\\core\\sip-sec-negotiate.h\" />\r\n    <ClInclude Include=\"src\\core\\sip-sec-ntlm.h\" />\r\n    <ClInclude Include=\"src\\core\\sip-sec-sspi.h\" />\r\n    <ClInclude Include=\"src\\core\\sip-sec-tls-dsk.h\" />\r\n    <ClInclude Include=\"src\\core\\sip-sec.h\" />\r\n    <ClInclude Include=\"src\\core\\sip-soap.h\" />\r\n    <ClInclude Include=\"src\\core\\sip-transport.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-buddy.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-cal.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-certificate.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-cert-crypto.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-chat.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-conf.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-core-private.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-crypt.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-dialog.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-digest.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-domino.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-ews.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-ews-autodiscover.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-ft.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-group.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-groupchat.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-http.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-http-request.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-http-transport.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-im.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-incoming.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-lync-autodiscover.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-media.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-notify.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-ocs2005.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-ocs2007.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-schedule.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-session.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-sign.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-status.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-subscriptions.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-svc.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-tls.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-ucs.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-utils.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-webticket.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-win32dep.h\" />\r\n    <ClInclude Include=\"src\\core\\sipe-xml.h\" />\r\n    <ClInclude Include=\"src\\core\\sipmsg.h\" />\r\n    <ClInclude Include=\"src\\core\\uuid.h\" />\r\n    <ClInclude Include=\"src\\api\\sipe-backend.h\" />\r\n    <ClInclude Include=\"src\\api\\sipe-common.h\" />\r\n    <ClInclude Include=\"src\\api\\sipe-core.h\" />\r\n    <ClInclude Include=\"src\\api\\sipe-mime.h\" />\r\n    <ClInclude Include=\"src\\api\\sipe-nls.h\" />\r\n    <ClInclude Include=\"src\\miranda\\miranda-private.h\" />\r\n    <ClInclude Include=\"src\\miranda\\miranda-resource.h\" />\r\n    <ClInclude Include=\"src\\miranda\\miranda-version.h\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ResourceCompile Include=\"src\\miranda\\miranda.rc\" />\r\n  </ItemGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\r\n  <ImportGroup Label=\"ExtensionTargets\">\r\n  </ImportGroup>\r\n</Project>\n"
  },
  {
    "path": "siplcs.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup>\r\n    <Filter Include=\"core\">\r\n      <UniqueIdentifier>{0f7082ea-15e2-4067-b9ba-b9b12a41ef5d}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"api\">\r\n      <UniqueIdentifier>{0e9e11e0-1f11-49f8-8f6c-403264973d12}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"miranda\">\r\n      <UniqueIdentifier>{1985067e-9fcc-4a0e-a02a-79ae17f356cf}</UniqueIdentifier>\r\n    </Filter>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"src\\core\\md4.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sdpmsg.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sip-csta.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sip-sec-gssapi.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sip-sec-ntlm.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sip-sec.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sip-soap.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sip-transport.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-buddy.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-cal.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-certificate.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-cert-crypto-nss.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-chat.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-conf.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-core.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-crypt-nss.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-dialog.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-digest-nss.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-domino.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-ews.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-ft-tftp.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-ft.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-group.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-groupchat.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-im.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-incoming.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-media.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-mime.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-notify.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-ocs2005.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-ocs2007.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-schedule.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-session.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-sign.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-status.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-subscriptions.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-svc.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-tls.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-ucs.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-user.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-utils.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-win32dep.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-xml.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipmsg.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\uuid.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-buddy.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-chat.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-connection.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-debug.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-dnsquery.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-ft.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-groupchat.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-im.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-input.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-markup.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-media.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-network.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-notify.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-plugin.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-schedule.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-setting.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-transport.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-user.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-utils.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\sipe-miranda.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-search.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\miranda\\miranda-status.c\">\r\n      <Filter>miranda</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sipe-webticket.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sip-sec-tls-dsk.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sip-sec-sspi.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"src\\core\\sip-sec-negotiate.c\">\r\n      <Filter>core</Filter>\r\n    </ClCompile>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"src\\core\\md4.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sdpmsg.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sip-csta.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sip-sec-gssapi.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sip-sec-mech.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sip-sec-ntlm.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sip-sec.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sip-soap.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sip-transport.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-buddy.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-cal.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-certificate.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-cert-crypto.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-chat.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-conf.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-core-private.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-crypt.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-dialog.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-digest.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-domino.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-ews.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-ft.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-group.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-groupchat.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-im.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-incoming.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-media.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-notify.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-ocs2005.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-ocs2007.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-schedule.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-session.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-sign.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-status.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-subscriptions.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-svc.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-tls.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-ucs.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-utils.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-win32dep.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-xml.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipmsg.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\uuid.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\api\\sipe-backend.h\">\r\n      <Filter>api</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\api\\sipe-common.h\">\r\n      <Filter>api</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\api\\sipe-core.h\">\r\n      <Filter>api</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\api\\sipe-mime.h\">\r\n      <Filter>api</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\api\\sipe-nls.h\">\r\n      <Filter>api</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\miranda\\miranda-private.h\">\r\n      <Filter>miranda</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\miranda\\miranda-resource.h\">\r\n      <Filter>miranda</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\miranda\\miranda-version.h\">\r\n      <Filter>miranda</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sipe-webticket.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sip-sec-tls-dsk.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sip-sec-sspi.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"src\\core\\sip-sec-negotiate.h\">\r\n      <Filter>core</Filter>\r\n    </ClInclude>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ResourceCompile Include=\"src\\miranda\\miranda.rc\">\r\n      <Filter>miranda</Filter>\r\n    </ResourceCompile>\r\n  </ItemGroup>\r\n</Project>\r\n"
  },
  {
    "path": "src/Makefile.am",
    "content": "SUBDIRS = core api\n\nif SIPE_INCLUDE_PURPLE\nSUBDIRS += purple\nendif\n\nif SIPE_INCLUDE_TELEPATHY\nSUBDIRS += telepathy\nendif\n\nEXTRA_DIST = \\\n\tadium \\\n\tmiranda \\\n\tMakefile.mingw\n\nMAINTAINERCLEANFILES = \\\n\tMakefile.in\n"
  },
  {
    "path": "src/Makefile.mingw",
    "content": "OLD_PIDGIN_TREE_TOP := $(PIDGIN_TREE_TOP)\nPIDGIN_TREE_TOP := ../$(OLD_PIDGIN_TREE_TOP)\n\ninclude $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak\n\n\n.PHONY: all clean install\n\nall:\n\t$(MAKE) -C core -f $(MINGW_MAKEFILE)\n\nclean:\n\t$(MAKE) -C core -f $(MINGW_MAKEFILE) clean\n\nrmbak:\n\trm -f *~\n\t$(MAKE) -C core -f $(MINGW_MAKEFILE) rmbak\n\ninstall: all\n\t$(MAKE) -C core -f $(MINGW_MAKEFILE) install\n\t\ntests: all\n\t$(MAKE) -C core -f $(MINGW_MAKEFILE) tests\n"
  },
  {
    "path": "src/adium/DCPurpleSIPEJoinChatViewController.h",
    "content": "//\n//  DCPurpleSIPEJoinChatViewController.h\n//  SIPEAdiumPlugin\n//\n//  Created by Michael Lamb on 02/10/12.\n//  Copyright 2012 Michael Lamb. All rights reserved.\n//\n\n#import <Adium/DCJoinChatViewController.h>\n#import <AIUtilities/AITextFieldWithDraggingDelegate.h>\n\n\n@class AICompletingTextField;\n\n@interface DCPurpleSIPEJoinChatViewController : DCJoinChatViewController <NSComboBoxDataSource> {\n    \n\tIBOutlet\tNSComboBox\t\t\t*combo_rooms;\n\tIBOutlet\tNSProgressIndicator *progress_fetch;\n\n\tNSTimer\t\t\t\t\t\t\t*timer;\n\tNSMutableDictionary\t\t\t\t*room_dict;\n\tstruct _PurpleRoomlist\t\t\t*room_list;\n}\n\n@end\n"
  },
  {
    "path": "src/adium/DCPurpleSIPEJoinChatViewController.m",
    "content": "//\n//  DCPurpleSIPEJoinChatViewController.m\n//  SIPEAdiumPlugin\n//\n//  Copyright (C) 2015 SIPE Project <http://sipe.sourceforge.net/>\n//\n//  Created by Michael Lamb on 02/10/12.\n//  Copyright 2012 Michael Lamb. All rights reserved.\n//\n\n#import \"DCPurpleSIPEJoinChatViewController.h\"\n#import <Adium/AIChatControllerProtocol.h>\n#import <Adium/DCJoinChatWindowController.h>\n#import <Adium/AIAccount.h>\n#import <Adium/ESDebugAILog.h>\n#import <AdiumLibPurple/CBPurpleAccount.h>\n#import \"roomlist.h\"\n\n@implementation DCPurpleSIPEJoinChatViewController\n\n- (id)init\n{\n    self = [super init];\n    if (self) {\n        room_dict = [[NSMutableDictionary alloc] init];\n        combo_rooms.usesDataSource = YES;\n        combo_rooms.completes  = YES;\n        combo_rooms.dataSource = self;\n    }\n    return self;\n}\n\n- (void)dealloc\n{\n    [timer invalidate];\n    timer = nil;\n    if (room_list != NULL) {\n        purple_roomlist_unref(room_list);\n        room_list = NULL;\n    }\n    [room_dict release];\n    [super dealloc];\n}\n\n- (void)configureForAccount:(AIAccount *)inAccount\n{\n    [super configureForAccount:inAccount];\n    if ( delegate ) {\n        [(DCJoinChatWindowController *)delegate setJoinChatEnabled:YES];\n    }\n\n    // get room list\n    if (room_list == NULL) {\n        // we want to run that code only once (configureForAccount is called twice actually)\n        CBPurpleAccount *pinAccount = (CBPurpleAccount*)inAccount;\n        room_list = purple_roomlist_get_list(pinAccount.purpleAccount->gc);\n        if (room_list) {\n            purple_roomlist_ref(room_list);\n            [progress_fetch startAnimation:self];\n            // start a timer to control when the fetching is done\n            timer = [NSTimer scheduledTimerWithTimeInterval:0.5\n                                                     target:self\n                                                   selector:@selector(checkForRoomlistFetchCompletion:)\n                                                   userInfo:nil\n                                                    repeats:YES];\n        } else {\n            [progress_fetch setHidden:YES];\n            AILog(@\"(DCPurpleSIPEJoinChatViewController) Can't fetch room list.\");\n        }\n    }\n}\n\n- (void)joinChatWithAccount:(AIAccount *)inAccount\n{\n    NSString *uri = nil;\n    NSInteger idx = [combo_rooms indexOfSelectedItem];\n\n    if (idx >= 0 && [room_dict count]) {\n        // get selected entry\n        NSString *key = [[room_dict allKeys] objectAtIndex:idx];\n\n        if (key)\n            uri = [room_dict valueForKey:key];\n\n    } else\n        uri = [combo_rooms stringValue];\n\n    if (uri && [uri length]) {\n        NSRange res = [uri rangeOfString:@\"ma-chan://\" options:NSCaseInsensitiveSearch];\n\n        if (res.location != 0) {\n            NSAlert *alert = [[NSAlert alloc] init];\n\n            [alert setMessageText:@\"Invalid room URI\"];\n            [alert setInformativeText:[combo_rooms toolTip]];\n            [alert addButtonWithTitle:@\"Ok\"];\n            [alert runModal];\n            [alert release];\n\n        } else {\n\n            [self doJoinChatWithName:[NSString stringWithFormat:@\"%@\",uri]\n                           onAccount:inAccount\n                    chatCreationInfo:[NSDictionary dictionaryWithObjectsAndKeys:\n                                      uri, @\"uri\",\n                                      nil]\n                    invitingContacts:nil\n               withInvitationMessage:nil];\n\n        }\n    } else {\n        AILog(@\"(DCPurpleSIPEJoinChatViewController) No URI specified.\");\n    }\n\n    // TODO: allow creation of OCS \"Conference\" (different from group-chat)\n    // Add a text field (UI should have radio buttons to enable/disable\n    // create a PurpleBuddy* based off of the username entered in the text field\n    // then call:\n    //        sipe_core_buddy_new_chat(PURPLE_BUDDY_TO_SIPE_CORE_PUBLIC, purple_buddy_get_name(buddy));\n    // which should kick off the Adium code to open a chat window.\n\n}\n\n- (void)checkForRoomlistFetchCompletion:(NSTimer*) aTimer\n{\n    if (room_list && purple_roomlist_get_in_progress(room_list) == FALSE) {\n        [progress_fetch stopAnimation:self];\n        [progress_fetch setHidden:YES];\n        [timer invalidate];\n        timer = nil;\n\n        // finally copy the list into our dict\n        for (GList *rooms = room_list->rooms; rooms != NULL; rooms = rooms->next) {\n            PurpleRoomlistRoom *room = rooms->data;\n            gchar *roomName = room->name;\n            gchar *uriStr    = room->fields->data;\n            if (roomName != NULL && uriStr != NULL) {\n                NSString *nameStr = [NSString stringWithUTF8String:roomName];\n                if ([room_dict objectForKey:nameStr] == nil) {\n                    [room_dict setObject:[NSString stringWithUTF8String:uriStr] forKey:nameStr];\n                }\n            }\n        }\n\n        purple_roomlist_unref(room_list);\n        room_list = NULL;\n    }\n}\n\n#pragma mark NSComboBoxDataSource\n\n- (NSInteger) numberOfItemsInComboBox:(NSComboBox*) aComboBox\n{\n    return [room_dict count];\n}\n- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(NSInteger)index\n{\n    NSArray* keys = [room_dict allKeys];\n    return [keys objectAtIndex:index];\n}\n\n// String completion\n- (NSString *)comboBox:(NSComboBox *)aComboBox completedString:(NSString *)uncompletedString\n{\n    if ([room_dict count] == 0 || uncompletedString == nil) {\n        return @\"\";\n    }\n    NSArray *keys = [room_dict allKeys];\n    for (NSString *key in keys) {\n        NSRange res = [key rangeOfString:uncompletedString options:NSCaseInsensitiveSearch];\n        if (res.location != NSNotFound && res.location == 0) {\n            return key;\n        }\n    }\n\n    return @\"\";\n}\n\n- (NSUInteger)comboBox:(NSComboBox *)aComboBox indexOfItemWithStringValue:(NSString *)aString\n{\n    if ([room_dict count] == 0) {\n        return NSNotFound;\n    }\n    NSArray *keys = [room_dict allKeys];\n    return [keys indexOfObjectIdenticalTo:aString];\n}\n\n#pragma mark\n\n- (NSString *)nibName\n{\n    return @\"DCPurpleSIPEJoinChatView\";\n}\n\n@end\n"
  },
  {
    "path": "src/adium/ESPurpleSIPEAccount.h",
    "content": "//\n//  ESSIPEAccount.h\n//  SIPEAdiumPlugin\n//\n//  Created by Matt Meissner on 10/30/09.\n//  Modified by Michael Lamb on 2/27/13\n//  Copyright 2013 Michael Lamb/Harris Kauffman. All rights reserved.\n//\n\n#import <AdiumLibpurple/CBPurpleAccount.h>\n\n#define KEY_SIPE_WINDOWS_LOGIN          @\"SIPE:Windows Login\"\n#define KEY_SIPE_CONNECT_HOST           @\"SIPE:Connect Host\"\n#define KEY_SIPE_PASSWORD               @\"SIPE:Password\"  // TODO: Do we need to keep this key? PurpleAccount should store this for us\n#define KEY_SIPE_CONNECTION_TYPE        @\"SIPE:Connection Type\"\n#define KEY_SIPE_EMAIL                  @\"SIPE:Email\"\n#define KEY_SIPE_EMAIL_LOGIN            @\"SIPE:Email Login\"\n#define KEY_SIPE_EMAIL_URL              @\"SIPE:Email URL\"\n#define KEY_SIPE_EMAIL_PASSWORD         @\"SIPE:Email Password\"\n#define KEY_SIPE_GROUP_CHAT_PROXY       @\"SIPE:Group Chat Proxy\"\n#define KEY_SIPE_USER_AGENT             @\"SIPE:User Agent\"\n#define KEY_SIPE_SINGLE_SIGN_ON         @\"SIPE:Single Sign On\"\n#define KEY_SIPE_DONT_PUBLISH           @\"SIPE:Dont Publish\"\n#define KEY_SIPE_AUTH_SCHEME            @\"SIPE:Authentication Scheme\"\n#define KEY_SIPE_AUTODISCOVER           @\"SIPE:Autodiscover\"\n#define KEY_SIPE_BEAST_DISABLE          @\"SIPE:BEAST Disable\"\n#define KEY_SIPE_ALLOW_WEB_PHOTO        @\"SIPE:Allow Web Photo\"\n\n#define PURPLE_SSL_CDSA_BEAST_TLS_WORKAROUND \"ssl_cdsa_beast_tls_workaround\"\n\n\n@interface ESPurpleSIPEAccount : CBPurpleAccount <AIAccount_Files> {\n    NSDictionary *adium_to_sipe_status;\n    NSDictionary *sipe_to_adium_status;\n}\n@end\n"
  },
  {
    "path": "src/adium/ESPurpleSIPEAccount.m",
    "content": "//\n//  ESSIPEAccount.m\n//  SIPEAdiumPlugin\n//\n//  Copyright (C) 2015 SIPE Project <http://sipe.sourceforge.net/>\n//\n//  Created by Matt Meissner on 10/30/09.\n//  Modified by Michael Lamb on 2/27/13\n//  Copyright 2013 Michael Lamb/Harris Kauffman. All rights reserved.\n//\n\n#import <Adium/AISharedAdium.h>\n#import <Adium/AIStatus.h>\n#import <Adium/AIStatusControllerProtocol.h>\n#import <Adium/ESDebugAILog.h>\n#import <Adium/AIListContact.h>\n#import \"AIContactController.h\"\n\n#import \"ESPurpleSIPEAccount.h\"\n#import \"ESSIPEService.h\"\n\n#include \"sipe-core.h\"\n#include \"sipe-backend.h\"\n#include \"purple-private.h\"\n\n@class AICoreComponentLoader;\n\n@implementation ESPurpleSIPEAccount\n\n- (void)initAccount\n{\n    [super initAccount];\n\n    sipe_to_adium_status =\n    [[NSDictionary alloc] initWithObjectsAndKeys:\n     STATUS_NAME_AVAILABLE,         @\"available\",                 //SIPE_ACTIVITY_AVAILABLE\n     STATUS_NAME_AVAILABLE,         @\"online\",                    //SIPE_ACTIVITY_ONLINE\n     STATUS_NAME_AWAY,              @\"idle\",                      //SIPE_ACTIVITY_INACTIVE\n     STATUS_NAME_BUSY,              @\"busy\",                      //SIPE_ACTIVITY_BUSY\n     STATUS_NAME_BUSY,              @\"busyidle\",                  //SIPE_ACTIVITY_BUSYIDLE\n     STATUS_NAME_DND,               @\"do-not-disturb\",            //SIPE_ACTIVITY_DND\n     STATUS_NAME_BRB,               @\"be-right-back\",             //SIPE_ACTIVITY_BRB\n     STATUS_NAME_AWAY,              @\"away\",                      //SIPE_ACTIVITY_AWAY\n     STATUS_NAME_LUNCH,             @\"out-to-lunch\",              //SIPE_ACTIVITY_LUNCH\n     STATUS_NAME_INVISIBLE,         @\"invisible\",                 //SIPE_ACTIVITY_INVISIBLE\n     STATUS_NAME_OFFLINE,           @\"offline\",                   //SIPE_ACTIVITY_OFFLINE\n     STATUS_NAME_PHONE,             @\"on-the-phone\",              //SIPE_ACTIVITY_ON_PHONE\n     STATUS_NAME_NOT_AT_DESK,       @\"in-a-conference\",           //SIPE_ACTIVITY_IN_CONF\n     STATUS_NAME_NOT_AT_DESK,       @\"in-a-meeting\",              //SIPE_ACTIVITY_IN_MEETING\n     STATUS_NAME_NOT_IN_OFFICE,     @\"out-of-office\",             //SIPE_ACTIVITY_OOF\n     STATUS_NAME_AWAY_FRIENDS_ONLY, @\"urgent-interruptions-only\", //SIPE_ACTIVITY_URGENT_ONLY\n     nil\n     ];\n\n    adium_to_sipe_status =\n    [[NSDictionary alloc] initWithObjectsAndKeys:\n     @\"available\",                 STATUS_NAME_AVAILABLE,         //SIPE_ACTIVITY_AVAILABLE\n     @\"busy\",                      STATUS_NAME_BUSY,              //SIPE_ACTIVITY_BUSY\n     @\"do-not-disturb\",            STATUS_NAME_DND,               //SIPE_ACTIVITY_DND\n     @\"be-right-back\",             STATUS_NAME_BRB,               //SIPE_ACTIVITY_BRB\n     @\"away\",                      STATUS_NAME_AWAY,              //SIPE_ACTIVITY_AWAY\n     @\"out-to-lunch\",              STATUS_NAME_LUNCH,             //SIPE_ACTIVITY_LUNCH\n     @\"invisible\",                 STATUS_NAME_INVISIBLE,         //SIPE_ACTIVITY_INVISIBLE\n     @\"offline\",                   STATUS_NAME_OFFLINE,           //SIPE_ACTIVITY_OFFLINE\n     @\"on-the-phone\",              STATUS_NAME_PHONE,             //SIPE_ACTIVITY_ON_PHONE\n     @\"in-a-meeting\",              STATUS_NAME_NOT_AT_DESK,       //SIPE_ACTIVITY_IN_MEETING\n     @\"out-of-office\",             STATUS_NAME_NOT_IN_OFFICE,     //SIPE_ACTIVITY_OOF\n     @\"urgent-interruptions-only\", STATUS_NAME_AWAY_FRIENDS_ONLY, //SIPE_ACTIVITY_URGENT_ONLY\n     nil\n     ];\n}\n\n- (void)dealloc\n{\n    [adium_to_sipe_status release];\n    [sipe_to_adium_status release];\n    [super dealloc];\n}\n\n- (const char*)protocolPlugin\n{\n\treturn \"prpl-sipe\";\n}\n\n- (const char *)purpleAccountName\n{\n    NSString *completeUserName = [NSString stringWithUTF8String:[super purpleAccountName]];\n    NSString *windowsLogin =[self preferenceForKey:KEY_SIPE_WINDOWS_LOGIN group:GROUP_ACCOUNT_STATUS];\n\n    if ( ![windowsLogin isEqualToString:@\"\"] ) {\n        completeUserName = [NSString stringWithFormat:@\"%@,%@\", completeUserName, windowsLogin];\n    }\n\n\treturn [completeUserName UTF8String];\n}\n\n#pragma mark Account Configuration\n- (void)configurePurpleAccount\n{\n    // Account preferences\n    AILog(@\"(ESPurpleSIPEAccount) Configuring account: %s\\n\", self.purpleAccountName);\n\n    NSArray *myArray = [NSArray arrayWithObjects:@\"auto\", @\"tls\", @\"tcp\", nil];\n\n    NSDictionary *keys_to_account =\n    [NSDictionary dictionaryWithObjectsAndKeys:\n     @\"server\",                        KEY_SIPE_CONNECT_HOST,\n     @\"password\",                      KEY_SIPE_PASSWORD,\n     @\"transport\",                     KEY_SIPE_CONNECTION_TYPE,\n     @\"email\",                         KEY_SIPE_EMAIL,\n     @\"email_login\",                   KEY_SIPE_EMAIL_LOGIN,\n     @\"email_url\",                     KEY_SIPE_EMAIL_URL,\n     @\"email_password\",                KEY_SIPE_EMAIL_PASSWORD,\n     @\"groupchat_user\",                KEY_SIPE_GROUP_CHAT_PROXY,\n     @\"useragent\",                     KEY_SIPE_USER_AGENT,\n     @\"sso\",                           KEY_SIPE_SINGLE_SIGN_ON,\n     @\"dont-publish\",                  KEY_SIPE_DONT_PUBLISH,\n     @\"authentication\",                KEY_SIPE_AUTH_SCHEME,\n     @\"ssl_cdsa_beast_tls_workaround\", KEY_SIPE_BEAST_DISABLE,\n     @\"allow-web-photo\",               KEY_SIPE_ALLOW_WEB_PHOTO,\n     nil\n     ];\n\n    for (NSString* key in keys_to_account) {\n        NSString *prpl_key = [keys_to_account objectForKey:key];\n        id value = [self preferenceForKey:key group:GROUP_ACCOUNT_STATUS];\n\n        if ([value isKindOfClass:[NSString class]]) {\n            if ([key isEqualToString:KEY_SIPE_CONNECT_HOST]) {\n                if ([value isEqualToString:@\"\"]) {\n                    /*\n                     * We're using auto-discover, i.e. we can only\n                     * determine the real server name when we have a\n                     * valid network connection.\n                     *\n                     * Unfortunately Adiums' reachability feature\n                     * requires us to specify a host even when no\n                     * network is available:\n                     *\n                     *   * must be a valid DNS name\n                     *     (can't use [[NSHost currentHost] ...])\n                     *   * must only be reachable via network\n                     *     (can't use @\"localhost\")\n                     *\n                     * Hard-code a well-known host name instead. As\n                     * this is for Adium we use the obvious choice.\n                     *\n                     * NOTE: this will fail for Intranet-only users.\n                     *\n                     * See also: https://sourceforge.net/p/sipe/bugs/262\n                     */\n                    [self setPreference:@\"adium.im\" forKey:KEY_CONNECT_HOST group:GROUP_ACCOUNT_STATUS];\n                } else {\n                    // If the user entered server:port only give the server portion to adium\n                    // otherwise the DNS lookup will fail the reachability test\n                    NSArray *server = [value componentsSeparatedByString:@\":\"];\n                    [self setPreference:[server objectAtIndex:0] forKey:KEY_CONNECT_HOST group:GROUP_ACCOUNT_STATUS];\n                }\n            }\n\n            purple_account_set_string(account, [prpl_key UTF8String], [value UTF8String]);\n        } else if ([value isKindOfClass:[NSNumber class]]) {\n            if ([key isEqualToString:KEY_SIPE_CONNECTION_TYPE]) {\n                NSString *tmp = [myArray objectAtIndex:(NSUInteger)value];\n                purple_account_set_string(account, [prpl_key UTF8String], [tmp UTF8String]);\n            } else {\n                purple_account_set_bool(account, [prpl_key UTF8String], [value boolValue]);\n            }\n        } else {\n            AILog(@\"(ESPurpleSIPEAccount) Unknown class %@ for key %@\", [value class], key);\n        }\n    }\n\n    // Adium doesn't honor our \"optional\" password on account creation and will prompt if the password field is left blank, so we must force it to think there is one, but only if there isn't already a password saved\n    if ( [[self preferenceForKey:KEY_SIPE_SINGLE_SIGN_ON group:GROUP_ACCOUNT_STATUS] boolValue] &&\n        [[self preferenceForKey:KEY_SIPE_PASSWORD group:GROUP_ACCOUNT_STATUS] isEqualToString:@\"\"] )\n    {\n        [self setPasswordTemporarily:@\"placeholder\"];\n    }\n}\n\n#pragma mark File transfer\n\n- (BOOL)canSendFolders\n{\n\treturn NO;\n}\n\n- (void)beginSendOfFileTransfer:(ESFileTransfer *)fileTransfer\n{\n\t[super _beginSendOfFileTransfer:fileTransfer];\n}\n\n- (void)acceptFileTransferRequest:(ESFileTransfer *)fileTransfer\n{\n    [super acceptFileTransferRequest:fileTransfer];\n}\n\n- (void)rejectFileReceiveRequest:(ESFileTransfer *)fileTransfer\n{\n    [super rejectFileReceiveRequest:fileTransfer];\n}\n\n- (void)cancelFileTransfer:(ESFileTransfer *)fileTransfer\n{\n\t[super cancelFileTransfer:fileTransfer];\n}\n\n#pragma mark Status Messages\n/*!\n * @brief Status name to use for a Purple buddy\n */\n- (NSString *)statusNameForPurpleBuddy:(PurpleBuddy *)buddy\n{\n    NSString *statusName;\n    PurplePresence  *presence = purple_buddy_get_presence(buddy);\n    PurpleStatus    *status = purple_presence_get_active_status(presence);\n    NSString        *purpleStatusID = [NSString stringWithUTF8String:purple_status_get_id(status)];\n\n    if (!purpleStatusID) return nil;\n\n    if (sipe_to_adium_status[purpleStatusID])\n        statusName = sipe_to_adium_status[purpleStatusID];\n    else {\n        AILog(@\"(ESPurpleSIPEAccount) Unknown purpleStatusID in statusNameForPurpleBuddy: %@\", purpleStatusID);\n        statusName = STATUS_NAME_OFFLINE;\n    }\n\n    return statusName;\n}\n\n/*!\n * @brief Maps purple status IDs to Adium statuses\n */\n - (const char *)purpleStatusIDForStatus:(AIStatus *)statusState arguments:(NSMutableDictionary *)arguments\n {\n     const gchar    *statusID;\n     NSString\t\t*statusName = statusState.statusName;\n\n     if ( adium_to_sipe_status[statusName] )\n         statusID = [adium_to_sipe_status[statusName] UTF8String];\n     else {\n         AILog(@\"(ESPurpleSIPEAccount): Unknown statusName in purpleStatusIDForStatus: %@\", statusName);\n         statusID = [super purpleStatusIDForStatus:statusState arguments:arguments];\n     }\n\n     return statusID;\n }\n\n\n// Improve the formatting of displayed names\n - (AIListContact *)contactWithUID:(NSString *)sourceUID\n{\n    // give the inherited implementation a whack at finding a contact\n    AIListContact *contact = [super contactWithUID:sourceUID];\n\n    NSRange sipURI = [sourceUID rangeOfString:@\"sip:\"];\n    if (sipURI.location != NSNotFound) {\n        // sourceUID is of the form \"sip:<username>@<domain>\".\n        // strip out the sip: part, and try find a contact with the nice display name\n        NSString *displayName = [sourceUID substringFromIndex:sipURI.location + sipURI.length];\n\n        // check to see if we have a contact already with the non-sip'ified username\n        if([adium.contactController existingContactWithService:service account:self UID:displayName])\n        {\n            // if we do, lets return it!\n            contact = [adium.contactController existingContactWithService:service account:self UID:displayName];\n        }\n        else\n        {\n            // otherwise, return the contact from super, setting formattedUID with \"sip:\" chopped\n            [contact setFormattedUID:displayName notify:NotifyNow];\n        }\n\n\n    }\n\n    return contact;\n}\n\n\n// generate group chat's creation dictionary from purple conversation, e.g. for bookmarking\n- (NSDictionary *)extractChatCreationDictionaryFromConversation:(PurpleConversation *)conv\n{\n    NSDictionary *dict = nil;\n    struct sipe_core_public *sipe_public = PURPLE_ACCOUNT_TO_SIPE_CORE_PUBLIC;\n    // called during purple_serv_got_joined_chat()?\n    struct sipe_chat_session *session = sipe_public->backend_private->adium_chat_session;\n\n    // Adium might never call this method after creating the chat. Just in case...\n    if (!session)\n        session = sipe_purple_chat_get_session(conv);\n\n    if (session) {\n        const gchar *uri = sipe_core_chat_id(sipe_public, session);\n        dict = [NSDictionary dictionaryWithObjectsAndKeys:\n                [NSString stringWithUTF8String:uri], @\"uri\",\n                nil\n               ];\n    } else {\n        AILog(@\"(ESPurpleSIPEAccount) Can't determine chat session in extractChatCreationDictionaryFromConversation:\");\n    }\n\n    return dict;\n}\n\n@end\n"
  },
  {
    "path": "src/adium/ESSIPEAccountViewController.h",
    "content": "//\n//  ESSIPEAccountViewController.h\n//  SIPEAdiumPlugin\n//\n//  Created by Matt Meissner on 10/30/09.\n//  Modified by Michael Lamb on 2/27/13\n//  Copyright 2013 Michael Lamb/Harris Kauffman. All rights reserved.\n//\n\n\n#import <Adium/AIAccountViewController.h>\n#import <AdiumLibpurple/PurpleAccountViewController.h>\n\n@interface ESSIPEAccountViewController : PurpleAccountViewController {\n\n    IBOutlet    NSTextField     *textField_windowsLogin;\n    IBOutlet    NSTextField     *textField_server;\n    IBOutlet\tNSTextField\t\t*textField_userAgent;\n\tIBOutlet\tNSTextField\t\t*textField_emailURL;\n\tIBOutlet\tNSTextField\t\t*textField_email;\n\tIBOutlet\tNSTextField\t\t*textField_emailLogin;\n\tIBOutlet\tNSTextField\t\t*textField_emailPassword;\n\tIBOutlet\tNSTextField\t\t*textField_groupchatUser;\n    \n    IBOutlet\tNSButton\t\t*checkBox_autoDiscover;\n    IBOutlet\tNSButton\t\t*checkBox_singleSignOn;\n    IBOutlet\tNSButton\t\t*checkbox_dontPublish;\n    IBOutlet\tNSButton\t\t*checkbox_beastDisable;\n    IBOutlet\tNSButton\t\t*checkbox_allowWebPhoto;\n    \n\tIBOutlet\tNSPopUpButton\t*popup_connectionType;\n   \tIBOutlet\tNSPopUpButton\t*popup_authenticationScheme;\n    \n    NSDictionary *sipe_key_to_gui;\n}\n\n\n@end\n"
  },
  {
    "path": "src/adium/ESSIPEAccountViewController.m",
    "content": "//\n//  ESSIPEAccountViewController.m\n//  SIPEAdiumPlugin\n//\n//  Created by Matt Meissner on 10/30/09.\n//  Modified by Michael Lamb on 2/27/13\n//  Copyright 2013 Michael Lamb/Harris Kauffman. All rights reserved.\n//\n\n#import <AdiumLibpurple/CBPurpleAccount.h>\n#import <Adium/ESDebugAILog.h>\n#import \"ESSIPEAccountViewController.h\"\n\n#include \"prpl.h\"\n#include \"ESPurpleSIPEAccount.h\"\n\n// Gotta define these here, because they're not yet in the 10.9 SDK.  :(\n#define NSAppKitVersionNumber10_8 1187\n#define NSAppKitVersionNumber10_8_5 1187.4\n#define NSAppKitVersionNumber10_9 1265\n\n@implementation ESSIPEAccountViewController\n\n- (id)init {\n    self = [super init];\n    \n    if (self) {\n        sipe_key_to_gui =\n            [[NSDictionary alloc] initWithObjectsAndKeys:\n             textField_windowsLogin,     KEY_SIPE_WINDOWS_LOGIN,\n             textField_password,         KEY_SIPE_PASSWORD,\n             textField_server,           KEY_SIPE_CONNECT_HOST,\n             popup_connectionType,       KEY_SIPE_CONNECTION_TYPE,\n             popup_authenticationScheme, KEY_SIPE_AUTH_SCHEME,\n             textField_userAgent,        KEY_SIPE_USER_AGENT,\n             checkBox_singleSignOn,      KEY_SIPE_SINGLE_SIGN_ON,\n             checkbox_beastDisable,      KEY_SIPE_BEAST_DISABLE,\n             textField_groupchatUser,    KEY_SIPE_GROUP_CHAT_PROXY,\n             textField_emailURL,         KEY_SIPE_EMAIL_URL,\n             textField_email,            KEY_SIPE_EMAIL,\n             textField_emailLogin,       KEY_SIPE_EMAIL_LOGIN,\n             textField_emailPassword,    KEY_SIPE_EMAIL_PASSWORD,\n             checkbox_dontPublish,       KEY_SIPE_DONT_PUBLISH,\n             checkbox_allowWebPhoto,     KEY_SIPE_ALLOW_WEB_PHOTO,\n             nil\n             ];\n    }\n    \n    return self;\n}\n\n- (void)dealloc\n{\n    [sipe_key_to_gui release];\n    [super dealloc];\n}\n\n- (NSString *)nibName{\n    return @\"ESSIPEAccountView\";\n}\n\n#pragma mark Configuration methods\n- (void)configureForAccount:(AIAccount *)inAccount\n{\n    [super configureForAccount:inAccount];\n\n    // BEAST mitigation for Mavericks and 10.8.5 users (with Security Update 2014-001)\n    if (NSAppKitVersionNumber < NSAppKitVersionNumber10_8_5) {\n        // We are not running on an OS with BEAST mitigations - Don't display this as a configuration option\n        [checkbox_beastDisable setHidden:YES];\n    }\n    \n    // Only need 1 hash for both connection & auth since there are no overlapping keys\n    NSDictionary *conn_auth_dict =\n    [NSDictionary dictionaryWithObjectsAndKeys:\n     @\"NTLM\",@\"ntlm\",\n     @\"Kerberos\",@\"krb5\",\n     @\"TLS-DSK\",@\"tls-dsk\",\n     @\"Auto\",@\"auto\",\n     @\"SSL/TLS\",@\"tls\",\n     @\"TCP\",@\"tcp\",\n     nil];\n    \n    for (NSString* key in sipe_key_to_gui) {\n        id value = [sipe_key_to_gui objectForKey:key];\n        \n        if ([value isKindOfClass:[NSTextField class]]) {\n            NSString *tmp = [account preferenceForKey:key group:GROUP_ACCOUNT_STATUS];\n            [value setStringValue:(tmp ? tmp : @\"\")];\n        } else if ([value isKindOfClass:[NSPopUpButton class]]) {\n            // NSPopUpButton *MUST* appear before NSButton in the if/else\n            //   because  NSPopUpButton is a NSButton...\n            NSString *tmp_key = [account preferenceForKey:key group:GROUP_ACCOUNT_STATUS];\n            NSString *tmp = @\"auto\";\n            \n            if ([conn_auth_dict objectForKey:tmp_key])\n                tmp = [conn_auth_dict objectForKey:tmp_key];\n            \n            [value selectItemWithTitle:tmp];\n        } else if ([value isKindOfClass:[NSButton class]]) {\n            [value setState:[[account preferenceForKey:key group:GROUP_ACCOUNT_STATUS] boolValue]];\n        } else {\n            AILog(@\"(ESSIPEAccountViewController) Unknown class %@ for key %@\", [value class], key);\n        }\n    }\n}\n\n- (void)saveConfiguration\n{\n    [super saveConfiguration];\n    \n    // Only need 1 hash for both connection & auth since there are no overlapping keys\n    NSDictionary *conn_auth_dict =\n    [NSDictionary dictionaryWithObjectsAndKeys:\n     @\"ntlm\",@\"NTLM\",\n     @\"krb5\",@\"Kerberos\",\n     @\"tls-dsk\",@\"TLS-DSK\",\n     @\"auto\",@\"Auto\",\n     @\"tls\",@\"SSL/TLS\",\n     @\"tcp\",@\"TCP\",\n     nil];\n    \n    for (NSString* key in sipe_key_to_gui) {\n        id value = [sipe_key_to_gui objectForKey:key];\n        \n        if ([value isKindOfClass:[NSTextField class]]) {\n            [account\n             setPreference:[[value stringValue] length] ? [value stringValue] : @\"\"\n             forKey:key\n             group:GROUP_ACCOUNT_STATUS];\n        } else if ([value isKindOfClass:[NSPopUpButton class]]) {\n            // NSPopUpButton *MUST* appear before NSButton in the if/else\n            //   because  NSPopUpButton is a NSButton...\n            NSString *tmp = [conn_auth_dict objectForKey:[[value selectedItem] title]];\n            [account\n             setPreference:tmp\n             forKey:key\n             group:GROUP_ACCOUNT_STATUS];\n        } else if ([value isKindOfClass:[NSButton class]]) {\n            [account\n             setPreference:[NSNumber numberWithBool:[value state]]\n             forKey:key\n             group:GROUP_ACCOUNT_STATUS];\n        } else {\n            AILog(@\"(ESSIPEAccountViewController) Unknown class %@ for key %@\", [value class], key);\n        }\n    }\n}\n\n@end\n"
  },
  {
    "path": "src/adium/ESSIPELibpurpleServicePlugin.h",
    "content": "//\n//  ESSIPELibpurpleServicePlugin.h\n//  SIPEAdiumPlugin\n//\n//  Created by Matt Meissner on 10/30/09.\n//  Modified by Michael Lamb on 2/27/13\n//  Copyright 2013 Michael Lamb/Harris Kauffman. All rights reserved.\n//\n\n#import <Adium/AIPlugin.h>\n#import <AdiumLibpurple/AILibpurplePlugin.h>\n\n#import \"ESSIPEService.h\"\n\n@interface ESSIPELibpurpleServicePlugin : AIPlugin <AILibpurplePlugin> {\n\tESSIPEService *SIPEService;\n}\n\n@end\n"
  },
  {
    "path": "src/adium/ESSIPELibpurpleServicePlugin.m",
    "content": "//\n//  ESSIPELibpurpleServicePlugin.m\n//  SIPEAdiumPlugin\n//\n//  Copyright (C) 2015 SIPE Project <http://sipe.sourceforge.net/>\n//\n//  Created by Matt Meissner on 10/30/09.\n//  Modified by Michael Lamb on 2/27/13\n//  Copyright 2013 Michael Lamb/Harris Kauffman. All rights reserved.\n//\n\n#import \"ESSIPEService.h\"\n#import \"ESSIPELibpurpleServicePlugin.h\"\n\n// C declarations  \nextern void purple_init_sipe_plugin(void);\n\n@implementation ESSIPELibpurpleServicePlugin\n\n# pragma mark Plugin Load/Install \n- (void)installLibpurplePlugin {\n}\n\n- (void)loadLibpurplePlugin \n{\n}\n\n- (void)installPlugin\n{\n\tpurple_init_sipe_plugin();\n\t[ESSIPEService registerService];\n}\n\n#pragma mark Plugin Metadata\n- (NSString *)libpurplePluginPath\n{\n\treturn [[NSBundle bundleForClass:[self class]] resourcePath];\n}\n\n- (NSString*) pluginAuthor {\n    return @\"Harris Kauffman, Michael Lamb\";\n}\n\n- (NSString*) pluginVersion {\n    return @PACKAGE_VERSION;\n}\n\n- (NSString*) pluginDescription {\n    return @\"Allows Adium to connect to Office Communicator accounts\";\n}\n\n- (NSString*) pluginWebsite {\n    return @PACKAGE_URL;\n}\n\n@end\n"
  },
  {
    "path": "src/adium/ESSIPEService.h",
    "content": "//\n//  ESSIPEService.h\n//  SIPEAdiumPlugin\n//\n//  Created by Matt Meissner on 10/30/09.\n//  Modified by Michael Lamb on 2/27/13\n//  Copyright 2013 Michael Lamb/Harris Kauffman. All rights reserved.\n//\n\n//#import <Adium/AIService.h>\n#import <AdiumLibpurple/PurpleService.h>\n\n@interface ESSIPEService : PurpleService {\n    \n}\n\n@end\n"
  },
  {
    "path": "src/adium/ESSIPEService.m",
    "content": "//\n//  ESSIPEService.m\n//  SIPEAdiumPlugin\n//\n//  Created by Matt Meissner on 10/30/09.\n//  Modified by Michael Lamb on 2/27/13\n//  Copyright 2013 Michael Lamb/Harris Kauffman. All rights reserved.\n//  Copyright (C) 2014 SIPE Project <http://sipe.sourceforge.net/>\n//\n\n#import <AIUtilities/AICharacterSetAdditions.h>\n#import <AIUtilities/AIImageAdditions.h>\n#import <Adium/AIStatusControllerProtocol.h>\n#import <Adium/AISharedAdium.h>\n\n#import \"DCPurpleSIPEJoinChatViewController.h\"\n#import \"ESSIPEAccountViewController.h\"\n#import \"ESPurpleSIPEAccount.h\"\n#import \"ESSIPEService.h\"\n\n@implementation ESSIPEService\n\n#pragma mark Account/Chat Creation\n- (Class)accountClass\n{\n\treturn [ESPurpleSIPEAccount class];\n}\n\n- (AIAccountViewController *)accountViewController{\n    return [ESSIPEAccountViewController accountViewController];\n}\n\n- (DCJoinChatViewController *)joinChatView{\n\treturn [DCPurpleSIPEJoinChatViewController joinChatView];\n}\n\n- (BOOL)canCreateGroupChats{\n\treturn YES;\n}\n\n#pragma mark Service Description Metadata\n- (NSString *)serviceCodeUniqueID{\n    return @\"libpurple-SIPE\";\n}\n\n- (NSString *)serviceID{\n    return @\"SIPE\";\n}\n\n- (NSString *)serviceClass{\n\treturn @\"SIPE\";\n}\n\n- (NSString *)shortDescription{\n    return @\"OCS\";\n}\n\n- (NSString *)longDescription{\n    return @\"Office Communicator\";\n}\n\n- (BOOL)caseSensitive{\n\treturn NO;\n}\n- (AIServiceImportance)serviceImportance{\n\treturn AIServiceSecondary;\n}\n\n// Some auth schemes may not need a password\n- (BOOL)requiresPassword{\n\treturn NO;\n}\n\n- (NSImage *)defaultServiceIconOfType:(AIServiceIconType)iconType {\n\tNSImage *baseImage = [NSImage imageNamed:@\"sipe\" forClass:[self class]];\n\n\tif ((iconType == AIServiceIconSmall) || (iconType == AIServiceIconList)) { \n        [baseImage setSize:NSMakeSize(16, 16)];\n\t}\n\n\treturn baseImage;\n}\n\n\n#pragma mark Service Properties\n- (NSCharacterSet *)allowedCharacters\n{\n\tNSMutableCharacterSet *allowedCharacters = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];\n\tNSCharacterSet *returnSet;\n\n\t//\n\t// NOTE: needs to be in sync with sipe-utils.c:escape_uri_part()\n\t//\n\t// @     -   XXX@YYY\n\t// :     -   sip:XXX@YYY\n\t// ._-~  -   unreserved, see RFC 3986 Appendix A\n\t//\n\t[allowedCharacters addCharactersInString:@\"@:._-~\"];\n\treturnSet = [allowedCharacters immutableCopy];\n    [allowedCharacters release];\n    \n\treturn [returnSet autorelease];\n}\n\n#pragma mark Statuses\n- (void)registerStatuses{\n    \n    NSNumber *awayStatus, *availableStatus, *invisibleStatus, *offlineStatus;\n    \n    awayStatus = [NSNumber numberWithInt:AIAwayStatusType];\n    availableStatus = [NSNumber numberWithInt:AIAvailableStatusType];\n    invisibleStatus = [NSNumber numberWithInt:AIInvisibleStatusType];\n    offlineStatus = [NSNumber numberWithInt:AIOfflineStatusType];\n    \n    NSDictionary *statuses =\n    [NSDictionary dictionaryWithObjectsAndKeys:\n     availableStatus, STATUS_NAME_AVAILABLE,\n     awayStatus,      STATUS_NAME_AWAY,\n     awayStatus,      STATUS_NAME_BUSY,\n     invisibleStatus, STATUS_NAME_INVISIBLE,\n     awayStatus,      STATUS_NAME_BRB,\n     awayStatus,      STATUS_NAME_DND,\n     awayStatus,      STATUS_NAME_LUNCH,\n     offlineStatus,   STATUS_NAME_OFFLINE,\n     awayStatus,      STATUS_NAME_PHONE,\n     awayStatus,      STATUS_NAME_NOT_AT_DESK,\n     awayStatus,      STATUS_NAME_NOT_IN_OFFICE,\n     awayStatus,      STATUS_NAME_AWAY_FRIENDS_ONLY,\n     nil\n     ];\n\n    for (NSString* key in statuses) {\n        AIStatusType value = [[statuses objectForKey:key] intValue];\n\n        [adium.statusController\n         registerStatus:key\n         withDescription:[adium.statusController localizedDescriptionForCoreStatusName:key]\n         ofType:value\n         forService:self\n         ];\n    }\n}\n\n\n@end\n"
  },
  {
    "path": "src/adium/English.lproj/DCPurpleSIPEJoinChatView.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<archive type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"8.00\">\n\t<data>\n\t\t<int key=\"IBDocument.SystemTarget\">1080</int>\n\t\t<string key=\"IBDocument.SystemVersion\">14B25</string>\n\t\t<string key=\"IBDocument.InterfaceBuilderVersion\">6254</string>\n\t\t<string key=\"IBDocument.AppKitVersion\">1343.16</string>\n\t\t<string key=\"IBDocument.HIToolboxVersion\">755.00</string>\n\t\t<object class=\"NSMutableDictionary\" key=\"IBDocument.PluginVersions\">\n\t\t\t<string key=\"NS.key.0\">com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t<string key=\"NS.object.0\">6254</string>\n\t\t</object>\n\t\t<array key=\"IBDocument.IntegratedClassDependencies\">\n\t\t\t<string>IBNSLayoutConstraint</string>\n\t\t\t<string>NSComboBox</string>\n\t\t\t<string>NSComboBoxCell</string>\n\t\t\t<string>NSCustomObject</string>\n\t\t\t<string>NSCustomView</string>\n\t\t\t<string>NSProgressIndicator</string>\n\t\t\t<string>NSTextField</string>\n\t\t\t<string>NSTextFieldCell</string>\n\t\t</array>\n\t\t<array key=\"IBDocument.PluginDependencies\">\n\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t</array>\n\t\t<object class=\"NSMutableDictionary\" key=\"IBDocument.Metadata\">\n\t\t\t<string key=\"NS.key.0\">PluginDependencyRecalculationVersion</string>\n\t\t\t<integer value=\"1\" key=\"NS.object.0\"/>\n\t\t</object>\n\t\t<array class=\"NSMutableArray\" key=\"IBDocument.RootObjects\" id=\"1000\">\n\t\t\t<object class=\"NSCustomObject\" id=\"1001\">\n\t\t\t\t<string key=\"NSClassName\">DCPurpleSIPEJoinChatViewController</string>\n\t\t\t</object>\n\t\t\t<object class=\"NSCustomObject\" id=\"1003\">\n\t\t\t\t<string key=\"NSClassName\">FirstResponder</string>\n\t\t\t</object>\n\t\t\t<object class=\"NSCustomObject\" id=\"1004\">\n\t\t\t\t<string key=\"NSClassName\">NSApplication</string>\n\t\t\t</object>\n\t\t\t<object class=\"NSCustomView\" id=\"1005\">\n\t\t\t\t<reference key=\"NSNextResponder\"/>\n\t\t\t\t<int key=\"NSvFlags\">268</int>\n\t\t\t\t<array class=\"NSMutableArray\" key=\"NSSubviews\">\n\t\t\t\t\t<object class=\"NSProgressIndicator\" id=\"904615717\">\n\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"1005\"/>\n\t\t\t\t\t\t<int key=\"NSvFlags\">268</int>\n\t\t\t\t\t\t<string key=\"NSFrame\">{{461, 25}, {16, 16}}</string>\n\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"1005\"/>\n\t\t\t\t\t\t<reference key=\"NSWindow\"/>\n\t\t\t\t\t\t<string key=\"NSReuseIdentifierKey\">_NS:1432</string>\n\t\t\t\t\t\t<string key=\"NSHuggingPriority\">{750, 750}</string>\n\t\t\t\t\t\t<int key=\"NSpiFlags\">20750</int>\n\t\t\t\t\t\t<double key=\"NSMaxValue\">100</double>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"NSComboBox\" id=\"25351435\">\n\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"1005\"/>\n\t\t\t\t\t\t<int key=\"NSvFlags\">268</int>\n\t\t\t\t\t\t<string key=\"NSFrame\">{{99, 19}, {364, 26}}</string>\n\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"1005\"/>\n\t\t\t\t\t\t<reference key=\"NSWindow\"/>\n\t\t\t\t\t\t<string key=\"NSReuseIdentifierKey\">_NS:9</string>\n\t\t\t\t\t\t<bool key=\"NSEnabled\">YES</bool>\n\t\t\t\t\t\t<object class=\"NSComboBoxCell\" key=\"NSCell\" id=\"172129374\">\n\t\t\t\t\t\t\t<int key=\"NSCellFlags\">342884417</int>\n\t\t\t\t\t\t\t<int key=\"NSCellFlags2\">272630784</int>\n\t\t\t\t\t\t\t<string key=\"NSContents\"/>\n\t\t\t\t\t\t\t<object class=\"NSFont\" key=\"NSSupport\" id=\"437195165\">\n\t\t\t\t\t\t\t\t<bool key=\"IBIsSystemFont\">YES</bool>\n\t\t\t\t\t\t\t\t<double key=\"NSSize\">13</double>\n\t\t\t\t\t\t\t\t<int key=\"NSfFlags\">1044</int>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t<string key=\"NSCellIdentifier\">_NS:9</string>\n\t\t\t\t\t\t\t<reference key=\"NSControlView\" ref=\"25351435\"/>\n\t\t\t\t\t\t\t<bool key=\"NSDrawsBackground\">YES</bool>\n\t\t\t\t\t\t\t<object class=\"NSColor\" key=\"NSBackgroundColor\">\n\t\t\t\t\t\t\t\t<int key=\"NSColorSpace\">6</int>\n\t\t\t\t\t\t\t\t<string key=\"NSCatalogName\">System</string>\n\t\t\t\t\t\t\t\t<string key=\"NSColorName\">textBackgroundColor</string>\n\t\t\t\t\t\t\t\t<object class=\"NSColor\" key=\"NSColor\" id=\"681411898\">\n\t\t\t\t\t\t\t\t\t<int key=\"NSColorSpace\">3</int>\n\t\t\t\t\t\t\t\t\t<bytes key=\"NSWhite\">MQA</bytes>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t<object class=\"NSColor\" key=\"NSTextColor\" id=\"17203544\">\n\t\t\t\t\t\t\t\t<int key=\"NSColorSpace\">6</int>\n\t\t\t\t\t\t\t\t<string key=\"NSCatalogName\">System</string>\n\t\t\t\t\t\t\t\t<string key=\"NSColorName\">controlTextColor</string>\n\t\t\t\t\t\t\t\t<object class=\"NSColor\" key=\"NSColor\" id=\"480471040\">\n\t\t\t\t\t\t\t\t\t<int key=\"NSColorSpace\">3</int>\n\t\t\t\t\t\t\t\t\t<bytes key=\"NSWhite\">MAA</bytes>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t<int key=\"NSVisibleItemCount\">5</int>\n\t\t\t\t\t\t\t<bool key=\"NSHasVerticalScroller\">YES</bool>\n\t\t\t\t\t\t\t<array class=\"NSMutableArray\" key=\"NSPopUpListData\">\n\t\t\t\t\t\t\t\t<string>Item 1</string>\n\t\t\t\t\t\t\t\t<string>Item 2</string>\n\t\t\t\t\t\t\t\t<string>Item 3</string>\n\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t<reference key=\"NSDelegate\" ref=\"25351435\"/>\n\t\t\t\t\t\t\t<object class=\"NSComboTableView\" key=\"NSTableView\" id=\"1033044181\">\n\t\t\t\t\t\t\t\t<reference key=\"NSNextResponder\"/>\n\t\t\t\t\t\t\t\t<int key=\"NSvFlags\">274</int>\n\t\t\t\t\t\t\t\t<string key=\"NSFrameSize\">{13, 63}</string>\n\t\t\t\t\t\t\t\t<reference key=\"NSSuperview\"/>\n\t\t\t\t\t\t\t\t<reference key=\"NSWindow\"/>\n\t\t\t\t\t\t\t\t<string key=\"NSReuseIdentifierKey\">_NS:29</string>\n\t\t\t\t\t\t\t\t<bool key=\"NSEnabled\">YES</bool>\n\t\t\t\t\t\t\t\t<bool key=\"NSAllowsLogicalLayoutDirection\">NO</bool>\n\t\t\t\t\t\t\t\t<bool key=\"NSControlAllowsExpansionToolTips\">YES</bool>\n\t\t\t\t\t\t\t\t<string key=\"NSControlAction\">tableViewAction:</string>\n\t\t\t\t\t\t\t\t<reference key=\"NSControlTarget\" ref=\"172129374\"/>\n\t\t\t\t\t\t\t\t<array class=\"NSMutableArray\" key=\"NSTableColumns\">\n\t\t\t\t\t\t\t\t\t<object class=\"NSTableColumn\">\n\t\t\t\t\t\t\t\t\t\t<string key=\"NSIdentifier\">0</string>\n\t\t\t\t\t\t\t\t\t\t<double key=\"NSWidth\">10</double>\n\t\t\t\t\t\t\t\t\t\t<double key=\"NSMinWidth\">10</double>\n\t\t\t\t\t\t\t\t\t\t<double key=\"NSMaxWidth\">3.4028234663852886e+38</double>\n\t\t\t\t\t\t\t\t\t\t<object class=\"NSTableHeaderCell\" key=\"NSHeaderCell\">\n\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSCellFlags\">67108928</int>\n\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSCellFlags2\">2048</int>\n\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSContents\"/>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSFont\" key=\"NSSupport\">\n\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"IBIsSystemFont\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t<double key=\"NSSize\">11</double>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSfFlags\">3100</int>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSColor\" key=\"NSBackgroundColor\">\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSColorSpace\">6</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSCatalogName\">System</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSColorName\">headerColor</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSColor\" ref=\"681411898\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSColor\" key=\"NSTextColor\">\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSColorSpace\">6</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSCatalogName\">System</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSColorName\">headerTextColor</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSColor\" ref=\"480471040\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t<object class=\"NSTextFieldCell\" key=\"NSDataCell\">\n\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSCellFlags\">337641536</int>\n\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSCellFlags2\">268437504</int>\n\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSContents\">Item 3</string>\n\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSSupport\" ref=\"437195165\"/>\n\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSControlView\" ref=\"1033044181\"/>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSColor\" key=\"NSBackgroundColor\" id=\"953555594\">\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSColorSpace\">6</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSCatalogName\">System</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSColorName\">controlBackgroundColor</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSColor\" key=\"NSColor\" id=\"42579112\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSColorSpace\">3</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<bytes key=\"NSWhite\">MC42NjY2NjY2NjY3AA</bytes>\n\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSTextColor\" ref=\"17203544\"/>\n\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t<int key=\"NSResizingMask\">3</int>\n\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsResizeable\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t<reference key=\"NSTableView\" ref=\"1033044181\"/>\n\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t</array>\n\t\t\t\t\t\t\t\t<double key=\"NSIntercellSpacingWidth\">3</double>\n\t\t\t\t\t\t\t\t<double key=\"NSIntercellSpacingHeight\">2</double>\n\t\t\t\t\t\t\t\t<reference key=\"NSBackgroundColor\" ref=\"953555594\"/>\n\t\t\t\t\t\t\t\t<object class=\"NSColor\" key=\"NSGridColor\">\n\t\t\t\t\t\t\t\t\t<int key=\"NSColorSpace\">6</int>\n\t\t\t\t\t\t\t\t\t<string key=\"NSCatalogName\">System</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSColorName\">gridColor</string>\n\t\t\t\t\t\t\t\t\t<object class=\"NSColor\" key=\"NSColor\">\n\t\t\t\t\t\t\t\t\t\t<int key=\"NSColorSpace\">3</int>\n\t\t\t\t\t\t\t\t\t\t<bytes key=\"NSWhite\">MC41AA</bytes>\n\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<double key=\"NSRowHeight\">19</double>\n\t\t\t\t\t\t\t\t<string key=\"NSAction\">tableViewAction:</string>\n\t\t\t\t\t\t\t\t<int key=\"NSTvFlags\">-765427712</int>\n\t\t\t\t\t\t\t\t<reference key=\"NSDelegate\" ref=\"172129374\"/>\n\t\t\t\t\t\t\t\t<reference key=\"NSDataSource\" ref=\"172129374\"/>\n\t\t\t\t\t\t\t\t<reference key=\"NSTarget\" ref=\"172129374\"/>\n\t\t\t\t\t\t\t\t<int key=\"NSColumnAutoresizingStyle\">1</int>\n\t\t\t\t\t\t\t\t<int key=\"NSDraggingSourceMaskForLocal\">-1</int>\n\t\t\t\t\t\t\t\t<int key=\"NSDraggingSourceMaskForNonLocal\">0</int>\n\t\t\t\t\t\t\t\t<bool key=\"NSAllowsTypeSelect\">YES</bool>\n\t\t\t\t\t\t\t\t<int key=\"NSTableViewDraggingDestinationStyle\">0</int>\n\t\t\t\t\t\t\t\t<int key=\"NSTableViewGroupRowStyle\">1</int>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<bool key=\"NSAllowsLogicalLayoutDirection\">NO</bool>\n\t\t\t\t\t\t<int key=\"NSTextFieldAlignmentRectInsetsVersion\">1</int>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"NSTextField\" id=\"1013321320\">\n\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"1005\"/>\n\t\t\t\t\t\t<int key=\"NSvFlags\">268</int>\n\t\t\t\t\t\t<string key=\"NSFrame\">{{18, 25}, {74, 17}}</string>\n\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"1005\"/>\n\t\t\t\t\t\t<reference key=\"NSWindow\"/>\n\t\t\t\t\t\t<bool key=\"NSEnabled\">YES</bool>\n\t\t\t\t\t\t<object class=\"NSTextFieldCell\" key=\"NSCell\" id=\"633934428\">\n\t\t\t\t\t\t\t<int key=\"NSCellFlags\">67108864</int>\n\t\t\t\t\t\t\t<int key=\"NSCellFlags2\">71303168</int>\n\t\t\t\t\t\t\t<string key=\"NSContents\">Chat Room</string>\n\t\t\t\t\t\t\t<reference key=\"NSSupport\" ref=\"437195165\"/>\n\t\t\t\t\t\t\t<reference key=\"NSControlView\" ref=\"1013321320\"/>\n\t\t\t\t\t\t\t<object class=\"NSColor\" key=\"NSBackgroundColor\">\n\t\t\t\t\t\t\t\t<int key=\"NSColorSpace\">6</int>\n\t\t\t\t\t\t\t\t<string key=\"NSCatalogName\">System</string>\n\t\t\t\t\t\t\t\t<string key=\"NSColorName\">controlColor</string>\n\t\t\t\t\t\t\t\t<reference key=\"NSColor\" ref=\"42579112\"/>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t<reference key=\"NSTextColor\" ref=\"17203544\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<bool key=\"NSAllowsLogicalLayoutDirection\">NO</bool>\n\t\t\t\t\t\t<int key=\"NSTextFieldAlignmentRectInsetsVersion\">1</int>\n\t\t\t\t\t</object>\n\t\t\t\t</array>\n\t\t\t\t<string key=\"NSFrameSize\">{480, 62}</string>\n\t\t\t\t<reference key=\"NSSuperview\"/>\n\t\t\t\t<reference key=\"NSWindow\"/>\n\t\t\t\t<reference key=\"NSNextKeyView\" ref=\"1013321320\"/>\n\t\t\t\t<string key=\"NSClassName\">NSView</string>\n\t\t\t</object>\n\t\t</array>\n\t\t<object class=\"IBObjectContainer\" key=\"IBDocument.Objects\">\n\t\t\t<array key=\"connectionRecords\">\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">view</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1001\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"1005\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">233</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">combo_rooms</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1001\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"25351435\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">263</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">progress_fetch</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1001\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"904615717\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">264</int>\n\t\t\t\t</object>\n\t\t\t</array>\n\t\t\t<object class=\"IBMutableOrderedSet\" key=\"objectRecords\">\n\t\t\t\t<array key=\"orderedObjects\">\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">0</int>\n\t\t\t\t\t\t<array key=\"object\" id=\"0\"/>\n\t\t\t\t\t\t<reference key=\"children\" ref=\"1000\"/>\n\t\t\t\t\t\t<nil key=\"parent\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">-2</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1001\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"0\"/>\n\t\t\t\t\t\t<string key=\"objectName\">File's Owner</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">-1</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1003\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"0\"/>\n\t\t\t\t\t\t<string key=\"objectName\">First Responder</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">-3</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1004\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"0\"/>\n\t\t\t\t\t\t<string key=\"objectName\">Application</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">1</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1005\"/>\n\t\t\t\t\t\t<array class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<object class=\"IBNSLayoutConstraint\" id=\"765432424\">\n\t\t\t\t\t\t\t\t<reference key=\"firstItem\" ref=\"904615717\"/>\n\t\t\t\t\t\t\t\t<int key=\"firstAttribute\">10</int>\n\t\t\t\t\t\t\t\t<int key=\"relation\">0</int>\n\t\t\t\t\t\t\t\t<reference key=\"secondItem\" ref=\"25351435\"/>\n\t\t\t\t\t\t\t\t<int key=\"secondAttribute\">10</int>\n\t\t\t\t\t\t\t\t<float key=\"multiplier\">1</float>\n\t\t\t\t\t\t\t\t<string key=\"multiplierString\">1</string>\n\t\t\t\t\t\t\t\t<object class=\"IBLayoutConstant\" key=\"constant\">\n\t\t\t\t\t\t\t\t\t<double key=\"value\">0.0</double>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<float key=\"priority\">1000</float>\n\t\t\t\t\t\t\t\t<reference key=\"containingView\" ref=\"1005\"/>\n\t\t\t\t\t\t\t\t<int key=\"scoringType\">6</int>\n\t\t\t\t\t\t\t\t<float key=\"scoringTypeFloat\">24</float>\n\t\t\t\t\t\t\t\t<int key=\"contentType\">2</int>\n\t\t\t\t\t\t\t\t<bool key=\"placeholder\">NO</bool>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t<object class=\"IBNSLayoutConstraint\" id=\"441509874\">\n\t\t\t\t\t\t\t\t<reference key=\"firstItem\" ref=\"904615717\"/>\n\t\t\t\t\t\t\t\t<int key=\"firstAttribute\">4</int>\n\t\t\t\t\t\t\t\t<int key=\"relation\">0</int>\n\t\t\t\t\t\t\t\t<reference key=\"secondItem\" ref=\"1013321320\"/>\n\t\t\t\t\t\t\t\t<int key=\"secondAttribute\">4</int>\n\t\t\t\t\t\t\t\t<float key=\"multiplier\">1</float>\n\t\t\t\t\t\t\t\t<string key=\"multiplierString\">1</string>\n\t\t\t\t\t\t\t\t<object class=\"IBLayoutConstant\" key=\"constant\">\n\t\t\t\t\t\t\t\t\t<double key=\"value\">0.0</double>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<float key=\"priority\">1000</float>\n\t\t\t\t\t\t\t\t<reference key=\"containingView\" ref=\"1005\"/>\n\t\t\t\t\t\t\t\t<int key=\"scoringType\">6</int>\n\t\t\t\t\t\t\t\t<float key=\"scoringTypeFloat\">24</float>\n\t\t\t\t\t\t\t\t<int key=\"contentType\">2</int>\n\t\t\t\t\t\t\t\t<bool key=\"placeholder\">NO</bool>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t<object class=\"IBNSLayoutConstraint\" id=\"500291277\">\n\t\t\t\t\t\t\t\t<reference key=\"firstItem\" ref=\"1005\"/>\n\t\t\t\t\t\t\t\t<int key=\"firstAttribute\">6</int>\n\t\t\t\t\t\t\t\t<int key=\"relation\">0</int>\n\t\t\t\t\t\t\t\t<reference key=\"secondItem\" ref=\"904615717\"/>\n\t\t\t\t\t\t\t\t<int key=\"secondAttribute\">6</int>\n\t\t\t\t\t\t\t\t<float key=\"multiplier\">1</float>\n\t\t\t\t\t\t\t\t<string key=\"multiplierString\">1</string>\n\t\t\t\t\t\t\t\t<object class=\"IBLayoutConstant\" key=\"constant\">\n\t\t\t\t\t\t\t\t\t<double key=\"value\">3</double>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<float key=\"priority\">1000</float>\n\t\t\t\t\t\t\t\t<reference key=\"containingView\" ref=\"1005\"/>\n\t\t\t\t\t\t\t\t<int key=\"scoringType\">3</int>\n\t\t\t\t\t\t\t\t<float key=\"scoringTypeFloat\">9</float>\n\t\t\t\t\t\t\t\t<int key=\"contentType\">3</int>\n\t\t\t\t\t\t\t\t<bool key=\"placeholder\">NO</bool>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t<object class=\"IBNSLayoutConstraint\" id=\"287233369\">\n\t\t\t\t\t\t\t\t<reference key=\"firstItem\" ref=\"1005\"/>\n\t\t\t\t\t\t\t\t<int key=\"firstAttribute\">6</int>\n\t\t\t\t\t\t\t\t<int key=\"relation\">0</int>\n\t\t\t\t\t\t\t\t<reference key=\"secondItem\" ref=\"25351435\"/>\n\t\t\t\t\t\t\t\t<int key=\"secondAttribute\">6</int>\n\t\t\t\t\t\t\t\t<float key=\"multiplier\">1</float>\n\t\t\t\t\t\t\t\t<string key=\"multiplierString\">1</string>\n\t\t\t\t\t\t\t\t<object class=\"IBNSLayoutSymbolicConstant\" key=\"constant\">\n\t\t\t\t\t\t\t\t\t<double key=\"value\">20</double>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<float key=\"priority\">1000</float>\n\t\t\t\t\t\t\t\t<reference key=\"containingView\" ref=\"1005\"/>\n\t\t\t\t\t\t\t\t<int key=\"scoringType\">8</int>\n\t\t\t\t\t\t\t\t<float key=\"scoringTypeFloat\">23</float>\n\t\t\t\t\t\t\t\t<int key=\"contentType\">3</int>\n\t\t\t\t\t\t\t\t<bool key=\"placeholder\">NO</bool>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t<object class=\"IBNSLayoutConstraint\" id=\"739879589\">\n\t\t\t\t\t\t\t\t<reference key=\"firstItem\" ref=\"1013321320\"/>\n\t\t\t\t\t\t\t\t<int key=\"firstAttribute\">5</int>\n\t\t\t\t\t\t\t\t<int key=\"relation\">0</int>\n\t\t\t\t\t\t\t\t<reference key=\"secondItem\" ref=\"1005\"/>\n\t\t\t\t\t\t\t\t<int key=\"secondAttribute\">5</int>\n\t\t\t\t\t\t\t\t<float key=\"multiplier\">1</float>\n\t\t\t\t\t\t\t\t<string key=\"multiplierString\">1</string>\n\t\t\t\t\t\t\t\t<object class=\"IBNSLayoutSymbolicConstant\" key=\"constant\">\n\t\t\t\t\t\t\t\t\t<double key=\"value\">20</double>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<float key=\"priority\">1000</float>\n\t\t\t\t\t\t\t\t<reference key=\"containingView\" ref=\"1005\"/>\n\t\t\t\t\t\t\t\t<int key=\"scoringType\">8</int>\n\t\t\t\t\t\t\t\t<float key=\"scoringTypeFloat\">23</float>\n\t\t\t\t\t\t\t\t<int key=\"contentType\">3</int>\n\t\t\t\t\t\t\t\t<bool key=\"placeholder\">NO</bool>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t<object class=\"IBNSLayoutConstraint\" id=\"651616518\">\n\t\t\t\t\t\t\t\t<reference key=\"firstItem\" ref=\"1013321320\"/>\n\t\t\t\t\t\t\t\t<int key=\"firstAttribute\">3</int>\n\t\t\t\t\t\t\t\t<int key=\"relation\">0</int>\n\t\t\t\t\t\t\t\t<reference key=\"secondItem\" ref=\"1005\"/>\n\t\t\t\t\t\t\t\t<int key=\"secondAttribute\">3</int>\n\t\t\t\t\t\t\t\t<float key=\"multiplier\">1</float>\n\t\t\t\t\t\t\t\t<string key=\"multiplierString\">1</string>\n\t\t\t\t\t\t\t\t<object class=\"IBNSLayoutSymbolicConstant\" key=\"constant\">\n\t\t\t\t\t\t\t\t\t<double key=\"value\">20</double>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<float key=\"priority\">1000</float>\n\t\t\t\t\t\t\t\t<reference key=\"containingView\" ref=\"1005\"/>\n\t\t\t\t\t\t\t\t<int key=\"scoringType\">0</int>\n\t\t\t\t\t\t\t\t<float key=\"scoringTypeFloat\">29</float>\n\t\t\t\t\t\t\t\t<int key=\"contentType\">3</int>\n\t\t\t\t\t\t\t\t<bool key=\"placeholder\">NO</bool>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t<reference ref=\"1013321320\"/>\n\t\t\t\t\t\t\t<reference ref=\"25351435\"/>\n\t\t\t\t\t\t\t<reference ref=\"904615717\"/>\n\t\t\t\t\t\t</array>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"0\"/>\n\t\t\t\t\t\t<string key=\"objectName\">View</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">135</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1013321320\"/>\n\t\t\t\t\t\t<array class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<reference ref=\"633934428\"/>\n\t\t\t\t\t\t</array>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"1005\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">225</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"651616518\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"1005\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">138</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"633934428\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"1013321320\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">245</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"739879589\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"1005\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">246</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"25351435\"/>\n\t\t\t\t\t\t<array class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<reference ref=\"172129374\"/>\n\t\t\t\t\t\t\t<object class=\"IBNSLayoutConstraint\" id=\"897338566\">\n\t\t\t\t\t\t\t\t<reference key=\"firstItem\" ref=\"25351435\"/>\n\t\t\t\t\t\t\t\t<int key=\"firstAttribute\">7</int>\n\t\t\t\t\t\t\t\t<int key=\"relation\">0</int>\n\t\t\t\t\t\t\t\t<nil key=\"secondItem\"/>\n\t\t\t\t\t\t\t\t<int key=\"secondAttribute\">0</int>\n\t\t\t\t\t\t\t\t<float key=\"multiplier\">1</float>\n\t\t\t\t\t\t\t\t<string key=\"multiplierString\">1</string>\n\t\t\t\t\t\t\t\t<object class=\"IBLayoutConstant\" key=\"constant\">\n\t\t\t\t\t\t\t\t\t<double key=\"value\">361</double>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<float key=\"priority\">1000</float>\n\t\t\t\t\t\t\t\t<reference key=\"containingView\" ref=\"25351435\"/>\n\t\t\t\t\t\t\t\t<int key=\"scoringType\">3</int>\n\t\t\t\t\t\t\t\t<float key=\"scoringTypeFloat\">9</float>\n\t\t\t\t\t\t\t\t<int key=\"contentType\">1</int>\n\t\t\t\t\t\t\t\t<bool key=\"placeholder\">NO</bool>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t</array>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"1005\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">247</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"172129374\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"25351435\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">251</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"904615717\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"1005\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">255</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"897338566\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"25351435\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">256</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"287233369\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"1005\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">259</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"500291277\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"1005\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">261</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"441509874\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"1005\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">262</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"765432424\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"1005\"/>\n\t\t\t\t\t</object>\n\t\t\t\t</array>\n\t\t\t</object>\n\t\t\t<dictionary class=\"NSMutableDictionary\" key=\"flattenedProperties\">\n\t\t\t\t<string key=\"-1.IBPluginDependency\">com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t<string key=\"-2.IBPluginDependency\">com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t<string key=\"-3.IBPluginDependency\">com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t<array key=\"1.IBNSViewMetadataConstraints\">\n\t\t\t\t\t<reference ref=\"651616518\"/>\n\t\t\t\t\t<reference ref=\"739879589\"/>\n\t\t\t\t\t<reference ref=\"287233369\"/>\n\t\t\t\t\t<reference ref=\"500291277\"/>\n\t\t\t\t\t<reference ref=\"441509874\"/>\n\t\t\t\t\t<reference ref=\"765432424\"/>\n\t\t\t\t</array>\n\t\t\t\t<reference key=\"1.IBNSViewMetadataGestureRecognizers\" ref=\"0\"/>\n\t\t\t\t<string key=\"1.IBPluginDependency\">com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t<boolean value=\"NO\" key=\"135.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints\"/>\n\t\t\t\t<string key=\"135.IBPluginDependency\">com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t<string key=\"138.IBPluginDependency\">com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t<string key=\"225.IBPluginDependency\">com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t<string key=\"245.IBPluginDependency\">com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t<object class=\"NSMutableDictionary\" key=\"246.IBAttributePlaceholdersKey\">\n\t\t\t\t\t<string key=\"NS.key.0\">ToolTip</string>\n\t\t\t\t\t<object class=\"IBToolTipAttribute\" key=\"NS.object.0\">\n\t\t\t\t\t\t<string key=\"name\">ToolTip</string>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"25351435\"/>\n\t\t\t\t\t\t<string key=\"toolTip\">You can enter a channel URI  in form of \"ma-chan://...\" directly or select a room from the list.</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<array key=\"246.IBNSViewMetadataConstraints\">\n\t\t\t\t\t<reference ref=\"897338566\"/>\n\t\t\t\t</array>\n\t\t\t\t<boolean value=\"NO\" key=\"246.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints\"/>\n\t\t\t\t<string key=\"246.IBPluginDependency\">com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t<string key=\"247.IBPluginDependency\">com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t<boolean value=\"NO\" key=\"251.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints\"/>\n\t\t\t\t<string key=\"251.IBPluginDependency\">com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t<string key=\"255.IBPluginDependency\">com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t<string key=\"256.IBPluginDependency\">com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t<string key=\"259.IBPluginDependency\">com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t<string key=\"261.IBPluginDependency\">com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t<string key=\"262.IBPluginDependency\">com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t</dictionary>\n\t\t\t<dictionary class=\"NSMutableDictionary\" key=\"unlocalizedProperties\"/>\n\t\t\t<nil key=\"activeLocalization\"/>\n\t\t\t<dictionary class=\"NSMutableDictionary\" key=\"localizations\"/>\n\t\t\t<nil key=\"sourceID\"/>\n\t\t\t<int key=\"maxID\">264</int>\n\t\t</object>\n\t\t<object class=\"IBClassDescriber\" key=\"IBDocument.Classes\">\n\t\t\t<array class=\"NSMutableArray\" key=\"referencedPartialClassDescriptions\">\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">DCJoinChatViewController</string>\n\t\t\t\t\t<string key=\"superclassName\">NSObject</string>\n\t\t\t\t\t<object class=\"NSMutableDictionary\" key=\"outlets\">\n\t\t\t\t\t\t<string key=\"NS.key.0\">view</string>\n\t\t\t\t\t\t<string key=\"NS.object.0\">NSView</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"NSMutableDictionary\" key=\"toOneOutletInfosByName\">\n\t\t\t\t\t\t<string key=\"NS.key.0\">view</string>\n\t\t\t\t\t\t<object class=\"IBToOneOutletInfo\" key=\"NS.object.0\">\n\t\t\t\t\t\t\t<string key=\"name\">view</string>\n\t\t\t\t\t\t\t<string key=\"candidateClassName\">NSView</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBProjectSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">../../../../adium/Frameworks/Adium Framework/Source/DCJoinChatViewController.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">DCPurpleSIPEJoinChatViewController</string>\n\t\t\t\t\t<string key=\"superclassName\">DCJoinChatViewController</string>\n\t\t\t\t\t<dictionary class=\"NSMutableDictionary\" key=\"outlets\">\n\t\t\t\t\t\t<string key=\"combo_rooms\">NSComboBox</string>\n\t\t\t\t\t\t<string key=\"progress_fetch\">NSProgressIndicator</string>\n\t\t\t\t\t</dictionary>\n\t\t\t\t\t<dictionary class=\"NSMutableDictionary\" key=\"toOneOutletInfosByName\">\n\t\t\t\t\t\t<object class=\"IBToOneOutletInfo\" key=\"combo_rooms\">\n\t\t\t\t\t\t\t<string key=\"name\">combo_rooms</string>\n\t\t\t\t\t\t\t<string key=\"candidateClassName\">NSComboBox</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"IBToOneOutletInfo\" key=\"progress_fetch\">\n\t\t\t\t\t\t\t<string key=\"name\">progress_fetch</string>\n\t\t\t\t\t\t\t<string key=\"candidateClassName\">NSProgressIndicator</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</dictionary>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBProjectSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">../DCPurpleSIPEJoinChatViewController.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">NSObject</string>\n\t\t\t\t\t<object class=\"NSMutableDictionary\" key=\"actions\">\n\t\t\t\t\t\t<string key=\"NS.key.0\">selectServiceType:</string>\n\t\t\t\t\t\t<string key=\"NS.object.0\">id</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"NSMutableDictionary\" key=\"actionInfosByName\">\n\t\t\t\t\t\t<string key=\"NS.key.0\">selectServiceType:</string>\n\t\t\t\t\t\t<object class=\"IBActionInfo\" key=\"NS.object.0\">\n\t\t\t\t\t\t\t<string key=\"name\">selectServiceType:</string>\n\t\t\t\t\t\t\t<string key=\"candidateClassName\">id</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBProjectSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">../../../../adium/Source/AIServiceMenu.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t</array>\n\t\t\t<array class=\"NSMutableArray\" key=\"referencedPartialClassDescriptionsV3.2+\">\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">DCJoinChatViewController</string>\n\t\t\t\t\t<string key=\"superclassName\">NSObject</string>\n\t\t\t\t\t<object class=\"NSMutableDictionary\" key=\"outlets\">\n\t\t\t\t\t\t<string key=\"NS.key.0\">view</string>\n\t\t\t\t\t\t<string key=\"NS.object.0\">NSView</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"NSMutableDictionary\" key=\"toOneOutletInfosByName\">\n\t\t\t\t\t\t<string key=\"NS.key.0\">view</string>\n\t\t\t\t\t\t<object class=\"IBToOneOutletInfo\" key=\"NS.object.0\">\n\t\t\t\t\t\t\t<string key=\"name\">view</string>\n\t\t\t\t\t\t\t<string key=\"candidateClassName\">NSView</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBFrameworkSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">Adium.framework/Headers/DCJoinChatViewController.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">NSActionCell</string>\n\t\t\t\t\t<string key=\"superclassName\">NSCell</string>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBFrameworkSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">AppKit.framework/Headers/NSActionCell.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">NSApplication</string>\n\t\t\t\t\t<string key=\"superclassName\">NSResponder</string>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBFrameworkSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">AppKit.framework/Headers/NSApplication.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">NSCell</string>\n\t\t\t\t\t<string key=\"superclassName\">NSObject</string>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBFrameworkSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">AppKit.framework/Headers/NSCell.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">NSComboBox</string>\n\t\t\t\t\t<string key=\"superclassName\">NSTextField</string>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBFrameworkSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">AppKit.framework/Headers/NSComboBox.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">NSComboBoxCell</string>\n\t\t\t\t\t<string key=\"superclassName\">NSTextFieldCell</string>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBFrameworkSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">AppKit.framework/Headers/NSComboBoxCell.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">NSControl</string>\n\t\t\t\t\t<string key=\"superclassName\">NSView</string>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBFrameworkSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">AppKit.framework/Headers/NSControl.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">NSFormatter</string>\n\t\t\t\t\t<string key=\"superclassName\">NSObject</string>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBFrameworkSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">Foundation.framework/Headers/NSFormatter.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">NSLayoutConstraint</string>\n\t\t\t\t\t<string key=\"superclassName\">NSObject</string>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBFrameworkSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">AppKit.framework/Headers/NSLayoutConstraint.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">NSMenu</string>\n\t\t\t\t\t<string key=\"superclassName\">NSObject</string>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBFrameworkSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">AppKit.framework/Headers/NSMenu.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">NSObject</string>\n\t\t\t\t\t<object class=\"NSMutableDictionary\" key=\"actions\">\n\t\t\t\t\t\t<string key=\"NS.key.0\">selectServiceType:</string>\n\t\t\t\t\t\t<string key=\"NS.object.0\">id</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"NSMutableDictionary\" key=\"actionInfosByName\">\n\t\t\t\t\t\t<string key=\"NS.key.0\">selectServiceType:</string>\n\t\t\t\t\t\t<object class=\"IBActionInfo\" key=\"NS.object.0\">\n\t\t\t\t\t\t\t<string key=\"name\">selectServiceType:</string>\n\t\t\t\t\t\t\t<string key=\"candidateClassName\">id</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBFrameworkSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">Adium.framework/Headers/AIServiceMenu.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">NSProgressIndicator</string>\n\t\t\t\t\t<string key=\"superclassName\">NSView</string>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBFrameworkSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">AppKit.framework/Headers/NSProgressIndicator.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">NSResponder</string>\n\t\t\t\t\t<string key=\"superclassName\">NSObject</string>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBFrameworkSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">AppKit.framework/Headers/NSResponder.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">NSTextField</string>\n\t\t\t\t\t<string key=\"superclassName\">NSControl</string>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBFrameworkSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">AppKit.framework/Headers/NSTextField.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">NSTextFieldCell</string>\n\t\t\t\t\t<string key=\"superclassName\">NSActionCell</string>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBFrameworkSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">AppKit.framework/Headers/NSTextFieldCell.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">NSView</string>\n\t\t\t\t\t<string key=\"superclassName\">NSResponder</string>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBFrameworkSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">AppKit.framework/Headers/NSView.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t</array>\n\t\t</object>\n\t\t<int key=\"IBDocument.localizationMode\">0</int>\n\t\t<string key=\"IBDocument.TargetRuntimeIdentifier\">IBCocoaFramework</string>\n\t\t<bool key=\"IBDocument.previouslyAttemptedUpgradeToXcode5\">YES</bool>\n\t\t<object class=\"NSMutableDictionary\" key=\"IBDocument.PluginDeclaredDevelopmentDependencies\">\n\t\t\t<string key=\"NS.key.0\">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>\n\t\t\t<integer value=\"4600\" key=\"NS.object.0\"/>\n\t\t</object>\n\t\t<bool key=\"IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion\">YES</bool>\n\t\t<int key=\"IBDocument.defaultPropertyAccessControl\">3</int>\n\t\t<bool key=\"IBDocument.UseAutolayout\">YES</bool>\n\t</data>\n</archive>\n"
  },
  {
    "path": "src/adium/English.lproj/ESSIPEAccountView.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"5053\" systemVersion=\"13C64\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\">\n    <dependencies>\n        <deployment defaultVersion=\"1080\" identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"5053\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"ESSIPEAccountViewController\">\n            <connections>\n                <outlet property=\"checkBox_singleSignOn\" destination=\"225\" id=\"235\"/>\n                <outlet property=\"checkbox_beastDisable\" destination=\"6zD-H5-Yzr\" id=\"7Pa-Pq-39O\"/>\n                <outlet property=\"checkbox_dontPublish\" destination=\"E1F-yb-IqN\" id=\"4vR-SP-5ac\"/>\n                <outlet property=\"checkbox_allowWebPhoto\" destination=\"E1F-yb-IqO\" id=\"4vR-SP-5ad\"/>\n                <outlet property=\"popup_authenticationScheme\" destination=\"65\" id=\"234\"/>\n                <outlet property=\"popup_connectionType\" destination=\"39\" id=\"233\"/>\n                <outlet property=\"textField_accountUID\" destination=\"161\" id=\"252\"/>\n                <outlet property=\"textField_email\" destination=\"118\" id=\"229\"/>\n                <outlet property=\"textField_emailLogin\" destination=\"124\" id=\"230\"/>\n                <outlet property=\"textField_emailPassword\" destination=\"130\" id=\"231\"/>\n                <outlet property=\"textField_emailURL\" destination=\"111\" id=\"228\"/>\n                <outlet property=\"textField_groupchatUser\" destination=\"136\" id=\"232\"/>\n                <outlet property=\"textField_password\" destination=\"163\" id=\"218\"/>\n                <outlet property=\"textField_server\" destination=\"31\" id=\"260\"/>\n                <outlet property=\"textField_userAgent\" destination=\"49\" id=\"227\"/>\n                <outlet property=\"textField_windowsLogin\" destination=\"253\" id=\"259\"/>\n                <outlet property=\"view_options\" destination=\"1\" id=\"216\"/>\n                <outlet property=\"view_setup\" destination=\"157\" id=\"215\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\"/>\n        <customView id=\"1\" userLabel=\"Options\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"398\" height=\"496\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <box autoresizesSubviews=\"NO\" title=\"Connection Settings\" borderType=\"line\" id=\"272\">\n                    <rect key=\"frame\" x=\"5\" y=\"304\" width=\"376\" height=\"172\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <view key=\"contentView\">\n                        <rect key=\"frame\" x=\"1\" y=\"1\" width=\"374\" height=\"156\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <textField autoresizesSubviews=\"NO\" verticalHuggingPriority=\"750\" id=\"4\">\n                                <rect key=\"frame\" x=\"8\" y=\"127\" width=\"81\" height=\"17\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" sendsActionOnEndEditing=\"YES\" title=\"Server[:Port]\" id=\"5\">\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                    <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField verticalHuggingPriority=\"750\" id=\"31\">\n                                <rect key=\"frame\" x=\"175\" y=\"124\" width=\"156\" height=\"22\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" state=\"on\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"32\">\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                    <color key=\"textColor\" name=\"textColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField verticalHuggingPriority=\"750\" id=\"10\">\n                                <rect key=\"frame\" x=\"8\" y=\"98\" width=\"111\" height=\"17\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" sendsActionOnEndEditing=\"YES\" title=\"Connection type:\" id=\"11\">\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                    <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField verticalHuggingPriority=\"750\" id=\"16\">\n                                <rect key=\"frame\" x=\"8\" y=\"36\" width=\"78\" height=\"17\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" sendsActionOnEndEditing=\"YES\" title=\"User Agent:\" id=\"17\">\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                    <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField verticalHuggingPriority=\"750\" id=\"25\">\n                                <rect key=\"frame\" x=\"8\" y=\"68\" width=\"153\" height=\"17\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" sendsActionOnEndEditing=\"YES\" title=\"Authentication scheme:\" id=\"26\">\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                    <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <popUpButton verticalHuggingPriority=\"750\" id=\"39\">\n                                <rect key=\"frame\" x=\"173\" y=\"92\" width=\"161\" height=\"26\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <popUpButtonCell key=\"cell\" type=\"push\" title=\"Auto\" bezelStyle=\"rounded\" alignment=\"left\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"42\" id=\"40\">\n                                    <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"menu\"/>\n                                    <menu key=\"menu\" title=\"OtherViews\" id=\"41\">\n                                        <items>\n                                            <menuItem title=\"Auto\" state=\"on\" id=\"42\"/>\n                                            <menuItem title=\"SSL/TLS\" tag=\"1\" id=\"43\"/>\n                                            <menuItem title=\"TCP\" tag=\"2\" id=\"44\"/>\n                                        </items>\n                                    </menu>\n                                </popUpButtonCell>\n                            </popUpButton>\n                            <textField verticalHuggingPriority=\"750\" id=\"49\">\n                                <rect key=\"frame\" x=\"175\" y=\"33\" width=\"156\" height=\"22\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" state=\"on\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"50\">\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                    <color key=\"textColor\" name=\"textColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <popUpButton verticalHuggingPriority=\"750\" id=\"65\">\n                                <rect key=\"frame\" x=\"173\" y=\"62\" width=\"161\" height=\"26\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <popUpButtonCell key=\"cell\" type=\"push\" title=\"Auto\" bezelStyle=\"rounded\" alignment=\"left\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"REM-Gh-Zed\" id=\"66\">\n                                    <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"menu\"/>\n                                    <menu key=\"menu\" title=\"OtherViews\" id=\"67\">\n                                        <items>\n                                            <menuItem title=\"Auto\" state=\"on\" id=\"REM-Gh-Zed\"/>\n                                            <menuItem title=\"NTLM\" id=\"68\"/>\n                                            <menuItem title=\"Kerberos\" tag=\"1\" id=\"69\"/>\n                                            <menuItem title=\"TLS-DSK\" tag=\"2\" id=\"70\"/>\n                                        </items>\n                                    </menu>\n                                </popUpButtonCell>\n                            </popUpButton>\n                            <button id=\"225\">\n                                <rect key=\"frame\" x=\"8\" y=\"9\" width=\"144\" height=\"18\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <buttonCell key=\"cell\" type=\"check\" title=\"Use Single Sign-On\" bezelStyle=\"regularSquare\" imagePosition=\"left\" state=\"on\" inset=\"2\" id=\"226\">\n                                    <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                </buttonCell>\n                            </button>\n                            <button id=\"6zD-H5-Yzr\">\n                                <rect key=\"frame\" x=\"175\" y=\"9\" width=\"185\" height=\"18\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <buttonCell key=\"cell\" type=\"check\" title=\"Disable BEAST mitigations\" bezelStyle=\"regularSquare\" imagePosition=\"left\" state=\"on\" inset=\"2\" id=\"jdN-I6-JKU\">\n                                    <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                </buttonCell>\n                            </button>\n                        </subviews>\n                    </view>\n                    <color key=\"borderColor\" white=\"0.0\" alpha=\"0.41999999999999998\" colorSpace=\"calibratedWhite\"/>\n                    <color key=\"fillColor\" white=\"0.0\" alpha=\"0.0\" colorSpace=\"calibratedWhite\"/>\n                </box>\n                <box autoresizesSubviews=\"NO\" title=\"Email Settings\" borderType=\"line\" id=\"273\">\n                    <rect key=\"frame\" x=\"5\" y=\"105\" width=\"376\" height=\"158\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <view key=\"contentView\">\n                        <rect key=\"frame\" x=\"1\" y=\"1\" width=\"373\" height=\"142\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n\t\t<subviews>\n\t\t    <textField verticalHuggingPriority=\"750\" id=\"76\">\n                                <rect key=\"frame\" x=\"8\" y=\"113\" width=\"125\" height=\"17\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" sendsActionOnEndEditing=\"YES\" title=\"Email services URL:\" id=\"77\">\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                    <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField verticalHuggingPriority=\"750\" id=\"82\">\n                                <rect key=\"frame\" x=\"8\" y=\"81\" width=\"96\" height=\"17\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" sendsActionOnEndEditing=\"YES\" title=\"Email address:\" id=\"83\">\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                    <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField verticalHuggingPriority=\"750\" id=\"96\">\n                                <rect key=\"frame\" x=\"8\" y=\"49\" width=\"78\" height=\"17\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" sendsActionOnEndEditing=\"YES\" title=\"Email login:\" id=\"97\">\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                    <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField verticalHuggingPriority=\"750\" id=\"100\">\n                                <rect key=\"frame\" x=\"8\" y=\"17\" width=\"107\" height=\"17\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" sendsActionOnEndEditing=\"YES\" title=\"Email password:\" id=\"101\">\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                    <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField verticalHuggingPriority=\"750\" id=\"111\">\n                                <rect key=\"frame\" x=\"175\" y=\"110\" width=\"156\" height=\"22\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" state=\"on\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"112\">\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                    <color key=\"textColor\" name=\"textColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField verticalHuggingPriority=\"750\" id=\"118\">\n                                <rect key=\"frame\" x=\"175\" y=\"78\" width=\"156\" height=\"22\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" state=\"on\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"119\">\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                    <color key=\"textColor\" name=\"textColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField verticalHuggingPriority=\"750\" id=\"124\">\n                                <rect key=\"frame\" x=\"175\" y=\"46\" width=\"156\" height=\"22\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" state=\"on\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"125\">\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                    <color key=\"textColor\" name=\"textColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField verticalHuggingPriority=\"750\" id=\"130\" customClass=\"NSSecureTextField\">\n                                <rect key=\"frame\" x=\"175\" y=\"14\" width=\"156\" height=\"22\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" state=\"on\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"131\">\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                    <color key=\"textColor\" name=\"textColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                        </subviews>\n                    </view>\n                    <color key=\"borderColor\" white=\"0.0\" alpha=\"0.41999999999999998\" colorSpace=\"calibratedWhite\"/>\n                    <color key=\"fillColor\" white=\"0.0\" alpha=\"0.0\" colorSpace=\"calibratedWhite\"/>\n                </box>\n                <textField verticalHuggingPriority=\"750\" id=\"104\">\n                    <rect key=\"frame\" x=\"12\" y=\"281\" width=\"120\" height=\"17\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" sendsActionOnEndEditing=\"YES\" title=\"Group Chat Proxy:\" id=\"105\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField verticalHuggingPriority=\"750\" id=\"136\">\n                    <rect key=\"frame\" x=\"182\" y=\"278\" width=\"156\" height=\"22\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" state=\"on\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"137\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"textColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <box autoresizesSubviews=\"NO\" title=\"Other Options\" borderType=\"line\" id=\"2gf-zd-3kf\">\n                    <rect key=\"frame\" x=\"5\" y=\"16\" width=\"376\" height=\"85\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <view key=\"contentView\">\n                        <rect key=\"frame\" x=\"1\" y=\"1\" width=\"373\" height=\"69\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <button id=\"E1F-yb-IqN\">\n                                <rect key=\"frame\" x=\"8\" y=\"43\" width=\"360\" height=\"18\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <buttonCell key=\"cell\" type=\"check\" title=\"Don't publish my calendar information\" bezelStyle=\"regularSquare\" imagePosition=\"left\" state=\"on\" inset=\"2\" id=\"bvU-tw-rYT\">\n                                    <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                </buttonCell>\n                            </button>\n                            <button id=\"E1F-yb-IqO\">\n                                <rect key=\"frame\" x=\"8\" y=\"15\" width=\"360\" height=\"18\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                <buttonCell key=\"cell\" type=\"check\" title=\"Show profile pictures from web (potentially dangerous)\" bezelStyle=\"regularSquare\" imagePosition=\"left\" state=\"on\" inset=\"2\" id=\"bvU-tw-rYU\">\n                                    <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                </buttonCell>\n                            </button>\n                        </subviews>\n                    </view>\n                    <color key=\"borderColor\" white=\"0.0\" alpha=\"0.41999999999999998\" colorSpace=\"calibratedWhite\"/>\n                    <color key=\"fillColor\" white=\"0.0\" alpha=\"0.0\" colorSpace=\"calibratedWhite\"/>\n                </box>\n            </subviews>\n        </customView>\n        <customView id=\"157\" userLabel=\"Setup\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"360\" height=\"132\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <textField verticalHuggingPriority=\"750\" id=\"158\">\n                    <rect key=\"frame\" x=\"12\" y=\"94\" width=\"71\" height=\"17\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" sendsActionOnEndEditing=\"YES\" title=\"Username:\" id=\"169\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField verticalHuggingPriority=\"750\" id=\"257\">\n                    <rect key=\"frame\" x=\"12\" y=\"64\" width=\"103\" height=\"17\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" sendsActionOnEndEditing=\"YES\" title=\"Windows Login:\" id=\"258\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField verticalHuggingPriority=\"750\" id=\"160\">\n                    <rect key=\"frame\" x=\"12\" y=\"34\" width=\"68\" height=\"17\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" sendsActionOnEndEditing=\"YES\" title=\"Password:\" id=\"167\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField verticalHuggingPriority=\"750\" id=\"161\">\n                    <rect key=\"frame\" x=\"123\" y=\"91\" width=\"213\" height=\"22\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" state=\"on\" borderStyle=\"bezel\" placeholderString=\"user@company.com\" drawsBackground=\"YES\" id=\"166\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"textColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField verticalHuggingPriority=\"750\" id=\"163\">\n                    <rect key=\"frame\" x=\"123\" y=\"31\" width=\"213\" height=\"22\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" state=\"on\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"164\" customClass=\"NSSecureTextFieldCell\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"textColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField verticalHuggingPriority=\"750\" id=\"253\" userLabel=\"windowslogin\">\n                    <rect key=\"frame\" x=\"123\" y=\"61\" width=\"213\" height=\"22\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" state=\"on\" borderStyle=\"bezel\" alignment=\"left\" placeholderString=\"DOMAIN\\username\" drawsBackground=\"YES\" id=\"256\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"textColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n            </subviews>\n        </customView>\n    </objects>\n</document>\n"
  },
  {
    "path": "src/adium/English.lproj/InfoPlist.strings",
    "content": "﻿/* Localized versions of Info.plist keys */\n\n"
  },
  {
    "path": "src/adium/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>English</string>\n\t<key>CFBundleExecutable</key>\n\t<string>${EXECUTABLE_NAME}</string>\n\t<key>CFBundleName</key>\n\t<string>${PRODUCT_NAME}</string>\n\t<key>CFBundleIconFile</key>\n\t<string></string>\n\t<key>CFBundleIdentifier</key>\n\t<string>net.sourceforge.sipe.${PRODUCT_NAME:rfc1034Identifier}</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleSignature</key>\n\t<string>AdIM</string>\n\t<key>AIMinimumAdiumVersionRequirement</key>\n\t<string>1.5</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>PACKAGE_STRING</string>\n\t<key>CFBundleVersion</key>\n\t<string>PACKAGE_VERSION</string>\n\t<key>NSPrincipalClass</key>\n\t<string>ESSIPELibpurpleServicePlugin</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "src/adium/PurpleDefaultsSIPE.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>SIPE:Authentication Scheme</key>\n\t<string>auto</string>\n\t<key>SIPE:Single Sign On</key>\n\t<false/>\n\t<key>SIPE:Dont Publish</key>\n\t<false/>\n\t<key>SIPE:Allow Web Photo</key>\n\t<false/>\n\t<key>SIPE:BEAST Disable</key>\n\t<false/>\n\t<key>SIPE:Connection Type</key>\n\t<string>auto</string>\n\t<key>Connect Host</key>\n\t<string>localhost</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "src/adium/README.Adium",
    "content": "Compiling SIPE plugin for Adium\n===============================\n\nTo compile the Adium plugin you will need Xcode and the source code from\nthe following URLs:\n\n- Adium 1.5+:      http://trac.adium.im/wiki/GettingNewestAdiumSource\n- OpenSSL 0.9.8za: https://www.openssl.org/source/old/0.9.x/openssl-0.9.8za.tar.gz\n- SIPE:            http://sourceforge.net/projects/sipe/files/sipe/\n\n\n1. Get Adium\n------------\n\nNOTE: you only have to do this step once. If you don't change the Adium\n      source code, then you can reuse the results from this step in future\n      SIPEAdiumPlugin builds.\n\nFollow the instructions at their URL above.\n\nThe directory needs to be called \"adium\" and must be located at the same\nlevel as the SIPE source code directory.\n\n\n2. Get OpenSSL\n--------------\n\nNOTE: you only have to do this step once. If you don't change the OpenSSL\n      source code, then you can reuse the results from this step in future\n      SIPEAdiumPlugin builds.\n\nExecute the following commands in the Terminal application to download and\nunpack the source code:\n\n    $ cd my_working_directory\n    $ curl -o openssl-0.9.8za.tar.gz https://www.openssl.org/source/old/0.9.x/openssl-0.9.8za.tar.gz\n    $ tar -xf openssl-0.9.8za.tar.gz\n\nThe directory needs to be called \"openssl-0.9.8za\" and must be located at\nthe same level as the SIPE source code directory.\n\n\n3. Build the SIPEAdiumPlugin Xcode project\n------------------------------------------\n\nIn Xcode go to the menu File -> Open..., browse to the location of your SIPE\nsource tree, go into the src/adium directory, select SIPEAdiumPlugin.xcodeproj\nand press \"Open\".\n\nNOTE: please always make sure that the correct scheme has been selected by\n      selecting the menu Product -> Scheme -> SIPEAdiumPlugin. Otherwise you\n      will get cryptic build failures.\n\nNow you can just select Product -> Build and after a short while you should\nget a SIPEAdiumPlugin binary that you can install into your Adium application. \n\n\n4. Generate & verify the release archive\n----------------------------------------\n\nThe build copies the files into your Adium plugin directory. Use the following\ncommands to generate the release archive:\n\n    $ cd ~/Library/Application\\ Support/Adium\\ 2.0/PlugIns\n    $ zip -r ~/SIPEAdiumPlugin.zip SIPEAdiumPlugin.AdiumLibpurplePlugin/\n\nYou need to have a bash 4 to run the verification script, e.g. on a Linux box\n\n    $ src/adium/check_release.sh ~/SIPEAdiumPlugin.zip\n\n\n5. Build SIPEAdiumPlugin for an older Max OS X release\n------------------------------------------------------\n\nIf your Xcode does not have the SDK for the older Mac OS X release then please\nsee\n\n    https://github.com/devernay/xcodelegacy\n\nhow to extract & install SDKs for\n\n    - OS X 10.9 & 10.10 from the Xcode 6.4 installation package\n    - OS X 10.11 from the Xcode 7.3.1 installation package\n\nInstalling all SDKs in one go seems to break Xcode builds, so please make sure\nto install each SDK separately with\n\n    $ sudo ./XcodeLegacy.sh -osxXXXX install\n\nXcode no longer seems to apply project build settings top-down. To make\nchanges please\n\n    - select the SIPEAdiumPlugin or Adium project\n    - select the \"Build Settings\" tab\n    - change from \"Basic\" to \"All\" (on the left)\n    - change from \"Combined\" to \"Levels\" (in the middle)\n    - find the line with the setting you want to change (use search field)\n    - select that line\n    - change the setting at the right-most(!) place in that line\n    - you will notice that all places to the left change automatically\n\nSettings to change\n\n    SDK to    |  Base SDK  | Implicitly Link Objective-C  | Other\n    build for |            | Runtime Support (Adium only) |\n   -----------|------------|------------------------------|-------------------\n     10.11    | OS X 10.11 |    <No change necessary>     |\n     10.10    | OS X 10.10 |    <No change necessary>     | Adium <= 1.5.10.3\n     10.9     | OS X 10.9  |            No                | Adium <= 1.5.10.3\n\n\n6. Alternative build approach\n-----------------------------\n\nThe default build approach also builds Adium which is actually unnecessary to\nbuild the plugin successfully. All what is needed are the compiled frameworks\nfrom an Adium build. This section describes the modifications in the sections\nabove to build the plugin without Adium.\n\nNOTE: this approach can't run the plugin, hence you won't be able to debug\n      it. To execute the plugin you will need to run Adium by hand, e.g. from\n      your normal Adium installation on the desktop.\n\nSection 1:\n\n    - after getting the Adium source code open Xcode and go to the menu\n      File -> Open...\n    - browse to the location of your Adium source tree, select Adium.xcodeproj\n      and press \"Open\"\n    - optional: go to the menu Product -> Clean, if you want to clean up the\n      artifacts from an earlier build to run a clean build from scratch\n    - go to the menu Product -> Build to run the Adium build\n    - after it is done go to the menu File -> Close Project\n\nAs long as you don't change the Adium source you can re-use the output from\nthis Adium build for all future plugin builds.\n\nSection 3:\n\n    - after opening the project select the Adium sub-project\n    - select \"Delete\" from the context menu\n    - press \"Remove Reference\" in the dialog\n    - go to the menu Product -> Build to run the plugin build\n\nThis build is considerably faster and can help to speed up the development\ncycle.\n\nNOTE: do *NEVER* check-in the modified SIPEAdiumPlugin.xcodeproj directory\n      from this approach. All real changes to the build must be done using\n      the default build approach!\n\nTo revert to the default build approach:\n\n    - go to the menu Product -> Clean to remove the build artifacts of the\n      plugin build\n    - go to the menu File -> Close Project to close the project\n    - execute the following git commands to revert the plugin source tree:\n\n      $ git clean -xfd\n      $ git checkout HEAD -- src/adium/SIPEAdiumPlugin.xcodeproj/\n\nNow you can perform the default build again as described in section 3.\n"
  },
  {
    "path": "src/adium/SIPEAdiumPlugin.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t1C3F91AC12C1F531000AA829 /* libpidgin-sipe.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1C7056D312C1E5820004E43B /* libpidgin-sipe.a */; };\n\t\t1C822BED12F8E87500CC4AEA /* sipe-im.c in Sources */ = {isa = PBXBuildFile; fileRef = 1C822BEB12F8E87500CC4AEA /* sipe-im.c */; };\n\t\t1CD71E3413C5380B0079DE64 /* sipe-ft-tftp.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CD71E3313C5380B0079DE64 /* sipe-ft-tftp.c */; };\n\t\t1CD71E3B13C538340079DE64 /* sipe-group.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CD71E3A13C538340079DE64 /* sipe-group.c */; };\n\t\t1CDEE46112C35DAD00790CAF /* ESSIPEAccountViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CDEE46012C35DAD00790CAF /* ESSIPEAccountViewController.m */; };\n\t\t1CE49FB914A17CF000663393 /* sipe-svc.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CE49FB114A17CF000663393 /* sipe-svc.c */; };\n\t\t1CE49FBA14A17CF000663393 /* sipe-ocs2007.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CE49FB214A17CF000663393 /* sipe-ocs2007.c */; };\n\t\t1CE49FBB14A17CF000663393 /* sipe-ocs2005.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CE49FB314A17CF000663393 /* sipe-ocs2005.c */; };\n\t\t1CE49FEA14A17EF000663393 /* sipe-status.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CE49FE914A17EF000663393 /* sipe-status.c */; };\n\t\t1CE49FF314A17F4D00663393 /* sip-soap.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CE49FF014A17F4D00663393 /* sip-soap.c */; };\n\t\t1CE49FF414A17F4D00663393 /* sipe-notify.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CE49FF114A17F4D00663393 /* sipe-notify.c */; };\n\t\t1CE49FF514A17F4D00663393 /* sipe-webticket.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CE49FF214A17F4D00663393 /* sipe-webticket.c */; };\n\t\t1CE4A00714A17FD100663393 /* sip-sec-digest.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CE4A00114A17FD100663393 /* sip-sec-digest.c */; };\n\t\t1CE4A00814A17FD100663393 /* sip-sec-tls-dsk.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CE4A00014A17FD100663393 /* sip-sec-tls-dsk.c */; };\n\t\t1CE4A00A14A17FD100663393 /* sipe-certificate.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CE4A00214A17FD100663393 /* sipe-certificate.c */; };\n\t\t1CE4A00D14A17FD100663393 /* sipe-tls.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CE4A00514A17FD100663393 /* sipe-tls.c */; };\n\t\t1CE4A01E14A180E100663393 /* purple-search.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CE4A01C14A180E100663393 /* purple-search.c */; };\n\t\t1CE4A01F14A180E100663393 /* purple-status.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CE4A01D14A180E100663393 /* purple-status.c */; };\n\t\t1CF260F912C2DFA00045B6CC /* purple-buddy.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CF260F112C2DFA00045B6CC /* purple-buddy.c */; };\n\t\t1CF260FA12C2DFA00045B6CC /* purple-chat.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CF260F212C2DFA00045B6CC /* purple-chat.c */; };\n\t\t1CF260FB12C2DFA00045B6CC /* purple-ft.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CF260F312C2DFA00045B6CC /* purple-ft.c */; };\n\t\t1CF260FC12C2DFA00045B6CC /* purple-groupchat.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CF260F412C2DFA00045B6CC /* purple-groupchat.c */; };\n\t\t1CF260FD12C2DFA00045B6CC /* purple-im.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CF260F512C2DFA00045B6CC /* purple-im.c */; };\n\t\t1CF260FF12C2DFA00045B6CC /* purple-notify.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CF260F712C2DFA00045B6CC /* purple-notify.c */; };\n\t\t1CF2610012C2DFA00045B6CC /* purple-user.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CF260F812C2DFA00045B6CC /* purple-user.c */; };\n\t\t1CF2611812C2E1AA0045B6CC /* sipe-groupchat.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CF2610C12C2E1AA0045B6CC /* sipe-groupchat.c */; };\n\t\t1CF2611912C2E1AA0045B6CC /* sipe-incoming.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CF2610D12C2E1AA0045B6CC /* sipe-incoming.c */; };\n\t\t1CF2611B12C2E1AA0045B6CC /* sipe-ucs.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CF2610F12C2E1AA0045B6CC /* sipe-ucs.c */; };\n\t\t1CF2611C12C2E1AA0045B6CC /* sipe-subscriptions.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CF2611012C2E1AA0045B6CC /* sipe-subscriptions.c */; };\n\t\t1CF2611D12C2E1AA0045B6CC /* sipe-user.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CF2611112C2E1AA0045B6CC /* sipe-user.c */; };\n\t\t1CF2612C12C2E73F0045B6CC /* ESPurpleSIPEAccount.m in Sources */ = {isa = PBXBuildFile; fileRef = C99F358E109AE68400E79CB2 /* ESPurpleSIPEAccount.m */; };\n\t\t1CF2612D12C2E7420045B6CC /* ESSIPEService.m in Sources */ = {isa = PBXBuildFile; fileRef = C948843C109B2F8100ABFAF7 /* ESSIPEService.m */; };\n\t\t1CF2612E12C2E7430045B6CC /* ESSIPELibpurpleServicePlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = C9488445109B352000ABFAF7 /* ESSIPELibpurpleServicePlugin.m */; };\n\t\t5AAF284A184E4172007481FA /* sipe-cert-crypto-openssl.c in Sources */ = {isa = PBXBuildFile; fileRef = B82FA4181847524B00AE581B /* sipe-cert-crypto-openssl.c */; };\n\t\t5AAF284B184E4172007481FA /* sipe-crypt-openssl.c in Sources */ = {isa = PBXBuildFile; fileRef = B82FA4191847524B00AE581B /* sipe-crypt-openssl.c */; };\n\t\t5AAF284C184E4172007481FA /* sipe-digest-openssl.c in Sources */ = {isa = PBXBuildFile; fileRef = B82FA41A1847524B00AE581B /* sipe-digest-openssl.c */; };\n\t\t5AAF284D184E4172007481FA /* sipe-http-request.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B379591176A2DDF001A02FD /* sipe-http-request.c */; };\n\t\t5AAF284E184E4172007481FA /* sipe-http-transport.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B379592176A2DDF001A02FD /* sipe-http-transport.c */; };\n\t\t5AAF284F184E4172007481FA /* sipe-http.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B379593176A2DDF001A02FD /* sipe-http.c */; };\n\t\t5AAF2850184E4172007481FA /* sip-sec-negotiate.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B78059916DFF8D200B844A6 /* sip-sec-negotiate.c */; };\n\t\t5AAF2851184E4172007481FA /* sip-sec-basic.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B78059D16DFF8D200B844A6 /* sip-sec-basic.c */; };\n\t\t7B50EFAB16DB326100F897D1 /* PurpleDefaultsSIPE.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7B50EFAA16DB326100F897D1 /* PurpleDefaultsSIPE.plist */; };\n\t\t7B78055816DEC73400B844A6 /* ESSIPEAccountView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B78055716DEC73400B844A6 /* ESSIPEAccountView.xib */; };\n\t\t7BBE151C184D4BEA0000FFC9 /* DCPurpleSIPEJoinChatViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BBE151A184D4BEA0000FFC9 /* DCPurpleSIPEJoinChatViewController.h */; };\n\t\t7BBE151D184D4BEA0000FFC9 /* DCPurpleSIPEJoinChatViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BBE151B184D4BEA0000FFC9 /* DCPurpleSIPEJoinChatViewController.m */; };\n\t\t7BBE1529184D4BF50000FFC9 /* DCPurpleSIPEJoinChatView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7BBE1527184D4BF50000FFC9 /* DCPurpleSIPEJoinChatView.xib */; };\n\t\t8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; };\n\t\t8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; };\n\t\tB13FAB5F119D5155001CE037 /* purple-connection.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FAB4F119D5155001CE037 /* purple-connection.c */; };\n\t\tB13FAB61119D5155001CE037 /* purple-debug.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FAB51119D5155001CE037 /* purple-debug.c */; };\n\t\tB13FAB63119D5155001CE037 /* purple-dnsquery.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FAB53119D5155001CE037 /* purple-dnsquery.c */; };\n\t\tB13FAB64119D5155001CE037 /* purple-markup.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FAB54119D5155001CE037 /* purple-markup.c */; };\n\t\tB13FAB66119D5155001CE037 /* purple-mime.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FAB56119D5155001CE037 /* purple-mime.c */; };\n\t\tB13FAB67119D5155001CE037 /* purple-network.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FAB57119D5155001CE037 /* purple-network.c */; };\n\t\tB13FAB68119D5155001CE037 /* purple-plugin.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FAB58119D5155001CE037 /* purple-plugin.c */; };\n\t\tB13FAB6A119D5155001CE037 /* purple-schedule.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FAB5A119D5155001CE037 /* purple-schedule.c */; };\n\t\tB13FAB6B119D5155001CE037 /* purple-setting.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FAB5B119D5155001CE037 /* purple-setting.c */; };\n\t\tB13FAB6C119D5155001CE037 /* purple-transport.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FAB5C119D5155001CE037 /* purple-transport.c */; };\n\t\tB13FABDF119D585A001CE037 /* sip-csta.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABA3119D585A001CE037 /* sip-csta.c */; };\n\t\tB13FABE1119D585A001CE037 /* sip-sec-gssapi.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABA5119D585A001CE037 /* sip-sec-gssapi.c */; };\n\t\tB13FABE5119D585A001CE037 /* sip-sec-ntlm.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABA9119D585A001CE037 /* sip-sec-ntlm.c */; };\n\t\tB13FABE9119D585A001CE037 /* sip-sec.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABAD119D585A001CE037 /* sip-sec.c */; };\n\t\tB13FABEB119D585A001CE037 /* sip-transport.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABAF119D585A001CE037 /* sip-transport.c */; };\n\t\tB13FABED119D585A001CE037 /* sipe-buddy.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABB1119D585A001CE037 /* sipe-buddy.c */; };\n\t\tB13FABEF119D585A001CE037 /* sipe-cal.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABB3119D585A001CE037 /* sipe-cal.c */; };\n\t\tB13FABF1119D585A001CE037 /* sipe-chat.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABB5119D585A001CE037 /* sipe-chat.c */; };\n\t\tB13FABF3119D585A001CE037 /* sipe-conf.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABB7119D585A001CE037 /* sipe-conf.c */; };\n\t\tB13FABF6119D585A001CE037 /* sipe-core.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABBA119D585A001CE037 /* sipe-core.c */; };\n\t\tB13FABF8119D585A001CE037 /* sipe-dialog.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABBC119D585A001CE037 /* sipe-dialog.c */; };\n\t\tB13FABFD119D585A001CE037 /* sipe-ews.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABC1119D585A001CE037 /* sipe-ews.c */; };\n\t\tB13FABFE119D585A001CE037 /* sipe-ews-autodiscover.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABC2119D585A001CE037 /* sipe-ews-autodiscover.c */; };\n\t\tB13FABFF119D585A001CE037 /* sipe-ft.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABC3119D585A001CE037 /* sipe-ft.c */; };\n\t\tB13FAC00119D585A001CE037 /* sipe-lync-autodiscover.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABC4119D585A001CE037 /* sipe-lync-autodiscover.c */; };\n\t\tB13FAC04119D585A001CE037 /* sipe-schedule.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABC8119D585A001CE037 /* sipe-schedule.c */; };\n\t\tB13FAC06119D585A001CE037 /* sipe-session.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABCA119D585A001CE037 /* sipe-session.c */; };\n\t\tB13FAC08119D585A001CE037 /* sipe-sign.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABCC119D585A001CE037 /* sipe-sign.c */; };\n\t\tB13FAC0A119D585A001CE037 /* sipe-utils.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABCE119D585A001CE037 /* sipe-utils.c */; };\n\t\tB13FAC0F119D585A001CE037 /* sipe-xml.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABD3119D585A001CE037 /* sipe-xml.c */; };\n\t\tB13FAC13119D585A001CE037 /* sipmsg.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABD7119D585A001CE037 /* sipmsg.c */; };\n\t\tB13FAC15119D585A001CE037 /* uuid.c in Sources */ = {isa = PBXBuildFile; fileRef = B13FABD9119D585A001CE037 /* uuid.c */; };\n\t\tB89F38821BDEB0D30017B509 /* sipe-ft-lync.c in Sources */ = {isa = PBXBuildFile; fileRef = B89F38811BDEB0D30017B509 /* sipe-ft-lync.c */; };\n\t\tB89F388D1BDEB0F00017B509 /* sipe-mime-common.c in Sources */ = {isa = PBXBuildFile; fileRef = B89F388C1BDEB0F00017B509 /* sipe-mime-common.c */; };\n\t\tB89F388F1BDEB10B0017B509 /* purple-plugin-common.c in Sources */ = {isa = PBXBuildFile; fileRef = B89F388E1BDEB10B0017B509 /* purple-plugin-common.c */; };\n\t\tB8E5616722D21E8E00580386 /* sipe-rtf.l in Sources */ = {isa = PBXBuildFile; fileRef = B8E5616622D21E8E00580386 /* sipe-rtf.l */; };\n\t\tC9FDAE7F109ADC54004EEEAF /* Kerberos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9FDAE7E109ADC54004EEEAF /* Kerberos.framework */; };\n\t\tC9FDAEF6109ADF97004EEEAF /* sipe.png in Resources */ = {isa = PBXBuildFile; fileRef = C9FDAEF4109ADF97004EEEAF /* sipe.png */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXBuildRule section */\n\t\tB8E5616822D21F3A00580386 /* PBXBuildRule */ = {\n\t\t\tisa = PBXBuildRule;\n\t\t\tcompilerSpec = com.apple.compilers.proxy.script;\n\t\t\tfileType = sourcecode.lex;\n\t\t\tisEditable = 1;\n\t\t\tname = \"Project Lex rule\";\n\t\t\toutputFiles = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/${INPUT_FILE_BASE}.c\",\n\t\t\t);\n\t\t\tscript = \"# $(LEX) is actually flex\\ncd ${DERIVED_FILE_DIR} && ${LEX} ${INPUT_FILE_PATH}\";\n\t\t};\n/* End PBXBuildRule section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t7BB8CBC1183AA605004351FF /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 7BB8CBB3183AA600004351FF /* Adium.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 34BD9DA9053146CC000AB133;\n\t\t\tremoteInfo = Adium;\n\t\t};\n\t\t7BB8CBC3183AA605004351FF /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 7BB8CBB3183AA600004351FF /* Adium.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 34BD9DE105314751000AB133;\n\t\t\tremoteInfo = Adium.Framework;\n\t\t};\n\t\t7BB8CBC5183AA605004351FF /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 7BB8CBB3183AA600004351FF /* Adium.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 3485D68009EB416300232CC4;\n\t\t\tremoteInfo = AdiumLibpurple;\n\t\t};\n\t\t7BB8CBC7183AA605004351FF /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 7BB8CBB3183AA600004351FF /* Adium.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 6334FBFC0F9C11DC003C77A9;\n\t\t\tremoteInfo = AIUtilities.framework;\n\t\t};\n\t\t7BB8CBC9183AA605004351FF /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 7BB8CBB3183AA600004351FF /* Adium.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 349C2EFA0867AC97000BF883;\n\t\t\tremoteInfo = AdiumApplescriptRunner;\n\t\t};\n\t\t7BB8CBCB183AA605004351FF /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 7BB8CBB3183AA600004351FF /* Adium.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 312ED3CA0C7E875B00A6BDA9;\n\t\t\tremoteInfo = \"Unit tests\";\n\t\t};\n\t\t7BB8CBCD183AA605004351FF /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 7BB8CBB3183AA600004351FF /* Adium.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 633D4FA40F9D3073004F491E;\n\t\t\tremoteInfo = \"Spotlight Importer\";\n\t\t};\n\t\t7BB8CC2A183AC198004351FF /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 7BB8CBB3183AA600004351FF /* Adium.xcodeproj */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 34BD9CD1053146CC000AB133;\n\t\t\tremoteInfo = Adium;\n\t\t};\n\t\tC92A79F110B25023009B64B9 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 089C1669FE841209C02AAC07 /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = C92A796810B24BAD009B64B9;\n\t\t\tremoteInfo = \"pidgin-sipe\";\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\t7B5DD2EA16DB1DFD00B3D188 /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"\";\n\t\t\tdstSubfolderSpec = 10;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = \"<absolute>\"; };\n\t\t089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = \"<group>\"; };\n\t\t089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = \"<absolute>\"; };\n\t\t1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = \"<absolute>\"; };\n\t\t1C7056D312C1E5820004E43B /* libpidgin-sipe.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = \"libpidgin-sipe.a\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t1C822BEB12F8E87500CC4AEA /* sipe-im.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-im.c\"; sourceTree = \"<group>\"; };\n\t\t1CD71E3313C5380B0079DE64 /* sipe-ft-tftp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-ft-tftp.c\"; sourceTree = \"<group>\"; };\n\t\t1CD71E3A13C538340079DE64 /* sipe-group.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-group.c\"; sourceTree = \"<group>\"; };\n\t\t1CDEE45F12C35DAD00790CAF /* ESSIPEAccountViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ESSIPEAccountViewController.h; sourceTree = \"<group>\"; };\n\t\t1CDEE46012C35DAD00790CAF /* ESSIPEAccountViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ESSIPEAccountViewController.m; sourceTree = \"<group>\"; };\n\t\t1CE49FB114A17CF000663393 /* sipe-svc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-svc.c\"; sourceTree = \"<group>\"; };\n\t\t1CE49FB214A17CF000663393 /* sipe-ocs2007.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-ocs2007.c\"; sourceTree = \"<group>\"; };\n\t\t1CE49FB314A17CF000663393 /* sipe-ocs2005.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-ocs2005.c\"; sourceTree = \"<group>\"; };\n\t\t1CE49FE914A17EF000663393 /* sipe-status.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-status.c\"; sourceTree = \"<group>\"; };\n\t\t1CE49FF014A17F4D00663393 /* sip-soap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sip-soap.c\"; sourceTree = \"<group>\"; };\n\t\t1CE49FF114A17F4D00663393 /* sipe-notify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-notify.c\"; sourceTree = \"<group>\"; };\n\t\t1CE49FF214A17F4D00663393 /* sipe-webticket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-webticket.c\"; sourceTree = \"<group>\"; };\n\t\t1CE4A00014A17FD100663393 /* sip-sec-tls-dsk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sip-sec-tls-dsk.c\"; sourceTree = \"<group>\"; };\n\t\t1CE4A00114A17FD100663393 /* sip-sec-digest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sip-sec-digest.c\"; sourceTree = \"<group>\"; };\n\t\t1CE4A00214A17FD100663393 /* sipe-certificate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-certificate.c\"; sourceTree = \"<group>\"; };\n\t\t1CE4A00514A17FD100663393 /* sipe-tls.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-tls.c\"; sourceTree = \"<group>\"; };\n\t\t1CE4A01C14A180E100663393 /* purple-search.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-search.c\"; sourceTree = \"<group>\"; };\n\t\t1CE4A01D14A180E100663393 /* purple-status.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-status.c\"; sourceTree = \"<group>\"; };\n\t\t1CF260F112C2DFA00045B6CC /* purple-buddy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-buddy.c\"; sourceTree = \"<group>\"; };\n\t\t1CF260F212C2DFA00045B6CC /* purple-chat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-chat.c\"; sourceTree = \"<group>\"; };\n\t\t1CF260F312C2DFA00045B6CC /* purple-ft.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-ft.c\"; sourceTree = \"<group>\"; };\n\t\t1CF260F412C2DFA00045B6CC /* purple-groupchat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-groupchat.c\"; sourceTree = \"<group>\"; };\n\t\t1CF260F512C2DFA00045B6CC /* purple-im.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-im.c\"; sourceTree = \"<group>\"; };\n\t\t1CF260F712C2DFA00045B6CC /* purple-notify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-notify.c\"; sourceTree = \"<group>\"; };\n\t\t1CF260F812C2DFA00045B6CC /* purple-user.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-user.c\"; sourceTree = \"<group>\"; };\n\t\t1CF2610C12C2E1AA0045B6CC /* sipe-groupchat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-groupchat.c\"; sourceTree = \"<group>\"; };\n\t\t1CF2610D12C2E1AA0045B6CC /* sipe-incoming.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-incoming.c\"; sourceTree = \"<group>\"; };\n\t\t1CF2610F12C2E1AA0045B6CC /* sipe-ucs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-ucs.c\"; sourceTree = \"<group>\"; };\n\t\t1CF2611012C2E1AA0045B6CC /* sipe-subscriptions.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-subscriptions.c\"; sourceTree = \"<group>\"; };\n\t\t1CF2611112C2E1AA0045B6CC /* sipe-user.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-user.c\"; sourceTree = \"<group>\"; };\n\t\t32DBCF630370AF2F00C91783 /* SIPEAdiumPlugin_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SIPEAdiumPlugin_Prefix.pch; sourceTree = \"<group>\"; };\n\t\t7B379591176A2DDF001A02FD /* sipe-http-request.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-http-request.c\"; sourceTree = \"<group>\"; };\n\t\t7B379592176A2DDF001A02FD /* sipe-http-transport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-http-transport.c\"; sourceTree = \"<group>\"; };\n\t\t7B379593176A2DDF001A02FD /* sipe-http.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-http.c\"; sourceTree = \"<group>\"; };\n\t\t7B50EFAA16DB326100F897D1 /* PurpleDefaultsSIPE.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = PurpleDefaultsSIPE.plist; sourceTree = \"<group>\"; };\n\t\t7B78055716DEC73400B844A6 /* ESSIPEAccountView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = ESSIPEAccountView.xib; path = English.lproj/ESSIPEAccountView.xib; sourceTree = \"<group>\"; };\n\t\t7B78059916DFF8D200B844A6 /* sip-sec-negotiate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sip-sec-negotiate.c\"; sourceTree = \"<group>\"; };\n\t\t7B78059D16DFF8D200B844A6 /* sip-sec-basic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sip-sec-basic.c\"; sourceTree = \"<group>\"; };\n\t\t7BB8CB91183AA0BD004351FF /* Base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = \"<group>\"; };\n\t\t7BB8CB92183AA0BD004351FF /* Debug-Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = \"Debug-Release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t7BB8CB93183AA0BD004351FF /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = \"<group>\"; };\n\t\t7BB8CB94183AA0BD004351FF /* libpidgin-sipe.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = \"libpidgin-sipe.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t7BB8CB96183AA0BD004351FF /* Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = \"<group>\"; };\n\t\t7BB8CB97183AA0BD004351FF /* SIPEAdiumPlugin.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = SIPEAdiumPlugin.xcconfig; sourceTree = \"<group>\"; };\n\t\t7BB8CBB3183AA600004351FF /* Adium.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = Adium.xcodeproj; path = ../../../adium/Adium.xcodeproj; sourceTree = \"<group>\"; };\n\t\t7BBE151A184D4BEA0000FFC9 /* DCPurpleSIPEJoinChatViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DCPurpleSIPEJoinChatViewController.h; sourceTree = \"<group>\"; };\n\t\t7BBE151B184D4BEA0000FFC9 /* DCPurpleSIPEJoinChatViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DCPurpleSIPEJoinChatViewController.m; sourceTree = \"<group>\"; };\n\t\t7BBE1528184D4BF50000FFC9 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/DCPurpleSIPEJoinChatView.xib; sourceTree = \"<group>\"; };\n\t\t8D5B49B6048680CD000E48DA /* SIPEAdiumPlugin.AdiumLibpurplePlugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SIPEAdiumPlugin.AdiumLibpurplePlugin; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; };\n\t\tB13FAB4F119D5155001CE037 /* purple-connection.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-connection.c\"; sourceTree = \"<group>\"; };\n\t\tB13FAB51119D5155001CE037 /* purple-debug.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-debug.c\"; sourceTree = \"<group>\"; };\n\t\tB13FAB53119D5155001CE037 /* purple-dnsquery.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-dnsquery.c\"; sourceTree = \"<group>\"; };\n\t\tB13FAB54119D5155001CE037 /* purple-markup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-markup.c\"; sourceTree = \"<group>\"; };\n\t\tB13FAB56119D5155001CE037 /* purple-mime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-mime.c\"; sourceTree = \"<group>\"; };\n\t\tB13FAB57119D5155001CE037 /* purple-network.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-network.c\"; sourceTree = \"<group>\"; };\n\t\tB13FAB58119D5155001CE037 /* purple-plugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-plugin.c\"; sourceTree = \"<group>\"; };\n\t\tB13FAB5A119D5155001CE037 /* purple-schedule.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-schedule.c\"; sourceTree = \"<group>\"; };\n\t\tB13FAB5B119D5155001CE037 /* purple-setting.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-setting.c\"; sourceTree = \"<group>\"; };\n\t\tB13FAB5C119D5155001CE037 /* purple-transport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-transport.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABA3119D585A001CE037 /* sip-csta.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sip-csta.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABA5119D585A001CE037 /* sip-sec-gssapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sip-sec-gssapi.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABA9119D585A001CE037 /* sip-sec-ntlm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sip-sec-ntlm.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABAD119D585A001CE037 /* sip-sec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sip-sec.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABAF119D585A001CE037 /* sip-transport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sip-transport.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABB1119D585A001CE037 /* sipe-buddy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-buddy.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABB3119D585A001CE037 /* sipe-cal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-cal.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABB5119D585A001CE037 /* sipe-chat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-chat.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABB7119D585A001CE037 /* sipe-conf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-conf.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABBA119D585A001CE037 /* sipe-core.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-core.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABBC119D585A001CE037 /* sipe-dialog.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-dialog.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABC1119D585A001CE037 /* sipe-ews.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-ews.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABC2119D585A001CE037 /* sipe-ews-autodiscover.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-ews-autodiscover.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABC3119D585A001CE037 /* sipe-ft.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-ft.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABC4119D585A001CE037 /* sipe-lync-autodiscover.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-lync-autodiscover.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABC8119D585A001CE037 /* sipe-schedule.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-schedule.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABCA119D585A001CE037 /* sipe-session.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-session.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABCC119D585A001CE037 /* sipe-sign.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-sign.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABCE119D585A001CE037 /* sipe-utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-utils.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABD3119D585A001CE037 /* sipe-xml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-xml.c\"; sourceTree = \"<group>\"; };\n\t\tB13FABD7119D585A001CE037 /* sipmsg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sipmsg.c; sourceTree = \"<group>\"; };\n\t\tB13FABD9119D585A001CE037 /* uuid.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uuid.c; sourceTree = \"<group>\"; };\n\t\tB82FA4181847524B00AE581B /* sipe-cert-crypto-openssl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-cert-crypto-openssl.c\"; sourceTree = \"<group>\"; };\n\t\tB82FA4191847524B00AE581B /* sipe-crypt-openssl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-crypt-openssl.c\"; sourceTree = \"<group>\"; };\n\t\tB82FA41A1847524B00AE581B /* sipe-digest-openssl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-digest-openssl.c\"; sourceTree = \"<group>\"; };\n\t\tB89F38811BDEB0D30017B509 /* sipe-ft-lync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-ft-lync.c\"; sourceTree = \"<group>\"; };\n\t\tB89F388C1BDEB0F00017B509 /* sipe-mime-common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"sipe-mime-common.c\"; sourceTree = \"<group>\"; };\n\t\tB89F388E1BDEB10B0017B509 /* purple-plugin-common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = \"purple-plugin-common.c\"; sourceTree = \"<group>\"; };\n\t\tB8E5616622D21E8E00580386 /* sipe-rtf.l */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.lex; path = \"sipe-rtf.l\"; sourceTree = \"<group>\"; };\n\t\tC948843B109B2F8100ABFAF7 /* ESSIPEService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ESSIPEService.h; sourceTree = \"<group>\"; };\n\t\tC948843C109B2F8100ABFAF7 /* ESSIPEService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ESSIPEService.m; sourceTree = \"<group>\"; };\n\t\tC9488444109B352000ABFAF7 /* ESSIPELibpurpleServicePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ESSIPELibpurpleServicePlugin.h; sourceTree = \"<group>\"; };\n\t\tC9488445109B352000ABFAF7 /* ESSIPELibpurpleServicePlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ESSIPELibpurpleServicePlugin.m; sourceTree = \"<group>\"; };\n\t\tC99F358D109AE68400E79CB2 /* ESPurpleSIPEAccount.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ESPurpleSIPEAccount.h; sourceTree = \"<group>\"; };\n\t\tC99F358E109AE68400E79CB2 /* ESPurpleSIPEAccount.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ESPurpleSIPEAccount.m; sourceTree = \"<group>\"; };\n\t\tC9FDAE7E109ADC54004EEEAF /* Kerberos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Kerberos.framework; path = System/Library/Frameworks/Kerberos.framework; sourceTree = SDKROOT; };\n\t\tC9FDAEF4109ADF97004EEEAF /* sipe.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = sipe.png; path = ../../pixmaps/48/sipe.png; sourceTree = SOURCE_ROOT; };\n\t\tD2F7E65807B2D6F200F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = \"<absolute>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t8D5B49B3048680CD000E48DA /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */,\n\t\t\t\tC9FDAE7F109ADC54004EEEAF /* Kerberos.framework in Frameworks */,\n\t\t\t\t1C3F91AC12C1F531000AA829 /* libpidgin-sipe.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tC92A796710B24BAD009B64B9 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t089C166AFE841209C02AAC07 /* SIPEAdiumPlugin */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t7BB8CBB3183AA600004351FF /* Adium.xcodeproj */,\n\t\t\t\t08FB77AFFE84173DC02AAC07 /* Classes */,\n\t\t\t\tC92A79B110B24C50009B64B9 /* pidgin-sipe */,\n\t\t\t\t32C88E010371C26100C91783 /* Other Sources */,\n\t\t\t\t089C167CFE841241C02AAC07 /* Resources */,\n\t\t\t\t089C1671FE841209C02AAC07 /* Frameworks and Libraries */,\n\t\t\t\t19C28FB8FE9D52D311CA2CBB /* Products */,\n\t\t\t);\n\t\t\tname = SIPEAdiumPlugin;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t089C1671FE841209C02AAC07 /* Frameworks and Libraries */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t7B1E80001665C79300E0C654 /* Other Libraries */,\n\t\t\t\t1058C7ACFEA557BF11CA2CBB /* Linked Frameworks */,\n\t\t\t\t1058C7AEFEA557BF11CA2CBB /* Other Frameworks */,\n\t\t\t);\n\t\t\tname = \"Frameworks and Libraries\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t089C167CFE841241C02AAC07 /* Resources */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t7BBE1527184D4BF50000FFC9 /* DCPurpleSIPEJoinChatView.xib */,\n\t\t\t\t7B78055716DEC73400B844A6 /* ESSIPEAccountView.xib */,\n\t\t\t\t7B50EFAA16DB326100F897D1 /* PurpleDefaultsSIPE.plist */,\n\t\t\t\tC9FDAEF4109ADF97004EEEAF /* sipe.png */,\n\t\t\t\t8D5B49B7048680CD000E48DA /* Info.plist */,\n\t\t\t\t089C167DFE841241C02AAC07 /* InfoPlist.strings */,\n\t\t\t);\n\t\t\tname = Resources;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t08FB77AFFE84173DC02AAC07 /* Classes */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t7BBE151A184D4BEA0000FFC9 /* DCPurpleSIPEJoinChatViewController.h */,\n\t\t\t\t7BBE151B184D4BEA0000FFC9 /* DCPurpleSIPEJoinChatViewController.m */,\n\t\t\t\tC99F358D109AE68400E79CB2 /* ESPurpleSIPEAccount.h */,\n\t\t\t\tC99F358E109AE68400E79CB2 /* ESPurpleSIPEAccount.m */,\n\t\t\t\tC9488444109B352000ABFAF7 /* ESSIPELibpurpleServicePlugin.h */,\n\t\t\t\tC9488445109B352000ABFAF7 /* ESSIPELibpurpleServicePlugin.m */,\n\t\t\t\tC948843B109B2F8100ABFAF7 /* ESSIPEService.h */,\n\t\t\t\tC948843C109B2F8100ABFAF7 /* ESSIPEService.m */,\n\t\t\t\t1CDEE45F12C35DAD00790CAF /* ESSIPEAccountViewController.h */,\n\t\t\t\t1CDEE46012C35DAD00790CAF /* ESSIPEAccountViewController.m */,\n\t\t\t);\n\t\t\tname = Classes;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t1058C7ACFEA557BF11CA2CBB /* Linked Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */,\n\t\t\t\tC9FDAE7E109ADC54004EEEAF /* Kerberos.framework */,\n\t\t\t);\n\t\t\tname = \"Linked Frameworks\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t1058C7AEFEA557BF11CA2CBB /* Other Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t089C167FFE841241C02AAC07 /* AppKit.framework */,\n\t\t\t\tD2F7E65807B2D6F200F64583 /* CoreData.framework */,\n\t\t\t\t089C1672FE841209C02AAC07 /* Foundation.framework */,\n\t\t\t);\n\t\t\tname = \"Other Frameworks\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t19C28FB8FE9D52D311CA2CBB /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t8D5B49B6048680CD000E48DA /* SIPEAdiumPlugin.AdiumLibpurplePlugin */,\n\t\t\t\t1C7056D312C1E5820004E43B /* libpidgin-sipe.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t32C88E010371C26100C91783 /* Other Sources */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t7BB8CB90183AA07B004351FF /* xcconfigs */,\n\t\t\t\t32DBCF630370AF2F00C91783 /* SIPEAdiumPlugin_Prefix.pch */,\n\t\t\t);\n\t\t\tname = \"Other Sources\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t7B1E80001665C79300E0C654 /* Other Libraries */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t);\n\t\t\tname = \"Other Libraries\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t7BB8CB90183AA07B004351FF /* xcconfigs */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t7BB8CB91183AA0BD004351FF /* Base.xcconfig */,\n\t\t\t\t7BB8CB92183AA0BD004351FF /* Debug-Release.xcconfig */,\n\t\t\t\t7BB8CB93183AA0BD004351FF /* Debug.xcconfig */,\n\t\t\t\t7BB8CB94183AA0BD004351FF /* libpidgin-sipe.xcconfig */,\n\t\t\t\t7BB8CB96183AA0BD004351FF /* Release.xcconfig */,\n\t\t\t\t7BB8CB97183AA0BD004351FF /* SIPEAdiumPlugin.xcconfig */,\n\t\t\t);\n\t\t\tpath = xcconfigs;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t7BB8CBB4183AA600004351FF /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t7BB8CBC2183AA605004351FF /* Adium.app */,\n\t\t\t\t7BB8CBC4183AA605004351FF /* Adium.framework */,\n\t\t\t\t7BB8CBC6183AA605004351FF /* AdiumLibpurple.framework */,\n\t\t\t\t7BB8CBC8183AA605004351FF /* AIUtilities.framework */,\n\t\t\t\t7BB8CBCA183AA605004351FF /* AdiumApplescriptRunner */,\n\t\t\t\t7BB8CBCC183AA605004351FF /* Unit tests.octest */,\n\t\t\t\t7BB8CBCE183AA605004351FF /* AdiumSpotlightImporter.mdimporter */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tB13FAB4D119D5155001CE037 /* purple */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t1CF260F112C2DFA00045B6CC /* purple-buddy.c */,\n\t\t\t\t1CF260F212C2DFA00045B6CC /* purple-chat.c */,\n\t\t\t\tB13FAB4F119D5155001CE037 /* purple-connection.c */,\n\t\t\t\tB13FAB51119D5155001CE037 /* purple-debug.c */,\n\t\t\t\tB13FAB53119D5155001CE037 /* purple-dnsquery.c */,\n\t\t\t\t1CF260F312C2DFA00045B6CC /* purple-ft.c */,\n\t\t\t\t1CF260F412C2DFA00045B6CC /* purple-groupchat.c */,\n\t\t\t\t1CF260F512C2DFA00045B6CC /* purple-im.c */,\n\t\t\t\tB13FAB54119D5155001CE037 /* purple-markup.c */,\n\t\t\t\tB13FAB56119D5155001CE037 /* purple-mime.c */,\n\t\t\t\tB13FAB57119D5155001CE037 /* purple-network.c */,\n\t\t\t\t1CF260F712C2DFA00045B6CC /* purple-notify.c */,\n\t\t\t\tB89F388E1BDEB10B0017B509 /* purple-plugin-common.c */,\n\t\t\t\tB13FAB58119D5155001CE037 /* purple-plugin.c */,\n\t\t\t\tB13FAB5A119D5155001CE037 /* purple-schedule.c */,\n\t\t\t\t1CE4A01C14A180E100663393 /* purple-search.c */,\n\t\t\t\tB13FAB5B119D5155001CE037 /* purple-setting.c */,\n\t\t\t\t1CE4A01D14A180E100663393 /* purple-status.c */,\n\t\t\t\tB13FAB5C119D5155001CE037 /* purple-transport.c */,\n\t\t\t\t1CF260F812C2DFA00045B6CC /* purple-user.c */,\n\t\t\t);\n\t\t\tname = purple;\n\t\t\tpath = ../purple;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\tB13FAB9C119D585A001CE037 /* core */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tB13FABA3119D585A001CE037 /* sip-csta.c */,\n\t\t\t\t7B78059D16DFF8D200B844A6 /* sip-sec-basic.c */,\n\t\t\t\t1CE4A00114A17FD100663393 /* sip-sec-digest.c */,\n\t\t\t\tB13FABA5119D585A001CE037 /* sip-sec-gssapi.c */,\n\t\t\t\t7B78059916DFF8D200B844A6 /* sip-sec-negotiate.c */,\n\t\t\t\tB13FABA9119D585A001CE037 /* sip-sec-ntlm.c */,\n\t\t\t\t1CE4A00014A17FD100663393 /* sip-sec-tls-dsk.c */,\n\t\t\t\tB13FABAD119D585A001CE037 /* sip-sec.c */,\n\t\t\t\t1CE49FF014A17F4D00663393 /* sip-soap.c */,\n\t\t\t\tB13FABAF119D585A001CE037 /* sip-transport.c */,\n\t\t\t\tB13FABB1119D585A001CE037 /* sipe-buddy.c */,\n\t\t\t\tB13FABB3119D585A001CE037 /* sipe-cal.c */,\n\t\t\t\tB82FA4181847524B00AE581B /* sipe-cert-crypto-openssl.c */,\n\t\t\t\t1CE4A00214A17FD100663393 /* sipe-certificate.c */,\n\t\t\t\tB13FABB5119D585A001CE037 /* sipe-chat.c */,\n\t\t\t\tB13FABB7119D585A001CE037 /* sipe-conf.c */,\n\t\t\t\tB13FABBA119D585A001CE037 /* sipe-core.c */,\n\t\t\t\tB82FA4191847524B00AE581B /* sipe-crypt-openssl.c */,\n\t\t\t\tB13FABBC119D585A001CE037 /* sipe-dialog.c */,\n\t\t\t\tB82FA41A1847524B00AE581B /* sipe-digest-openssl.c */,\n\t\t\t\tB13FABC2119D585A001CE037 /* sipe-ews-autodiscover.c */,\n\t\t\t\tB13FABC1119D585A001CE037 /* sipe-ews.c */,\n\t\t\t\tB89F38811BDEB0D30017B509 /* sipe-ft-lync.c */,\n\t\t\t\t1CD71E3313C5380B0079DE64 /* sipe-ft-tftp.c */,\n\t\t\t\tB13FABC3119D585A001CE037 /* sipe-ft.c */,\n\t\t\t\t1CD71E3A13C538340079DE64 /* sipe-group.c */,\n\t\t\t\t1CF2610C12C2E1AA0045B6CC /* sipe-groupchat.c */,\n\t\t\t\t7B379591176A2DDF001A02FD /* sipe-http-request.c */,\n\t\t\t\t7B379592176A2DDF001A02FD /* sipe-http-transport.c */,\n\t\t\t\t7B379593176A2DDF001A02FD /* sipe-http.c */,\n\t\t\t\t1C822BEB12F8E87500CC4AEA /* sipe-im.c */,\n\t\t\t\t1CF2610D12C2E1AA0045B6CC /* sipe-incoming.c */,\n\t\t\t\tB13FABC4119D585A001CE037 /* sipe-lync-autodiscover.c */,\n\t\t\t\tB89F388C1BDEB0F00017B509 /* sipe-mime-common.c */,\n\t\t\t\t1CE49FF114A17F4D00663393 /* sipe-notify.c */,\n\t\t\t\t1CE49FB314A17CF000663393 /* sipe-ocs2005.c */,\n\t\t\t\t1CE49FB214A17CF000663393 /* sipe-ocs2007.c */,\n\t\t\t\tB8E5616622D21E8E00580386 /* sipe-rtf.l */,\n\t\t\t\tB13FABC8119D585A001CE037 /* sipe-schedule.c */,\n\t\t\t\tB13FABCA119D585A001CE037 /* sipe-session.c */,\n\t\t\t\tB13FABCC119D585A001CE037 /* sipe-sign.c */,\n\t\t\t\t1CE49FE914A17EF000663393 /* sipe-status.c */,\n\t\t\t\t1CF2611012C2E1AA0045B6CC /* sipe-subscriptions.c */,\n\t\t\t\t1CE49FB114A17CF000663393 /* sipe-svc.c */,\n\t\t\t\t1CE4A00514A17FD100663393 /* sipe-tls.c */,\n\t\t\t\t1CF2610F12C2E1AA0045B6CC /* sipe-ucs.c */,\n\t\t\t\t1CF2611112C2E1AA0045B6CC /* sipe-user.c */,\n\t\t\t\tB13FABCE119D585A001CE037 /* sipe-utils.c */,\n\t\t\t\t1CE49FF214A17F4D00663393 /* sipe-webticket.c */,\n\t\t\t\tB13FABD3119D585A001CE037 /* sipe-xml.c */,\n\t\t\t\tB13FABD7119D585A001CE037 /* sipmsg.c */,\n\t\t\t\tB13FABD9119D585A001CE037 /* uuid.c */,\n\t\t\t);\n\t\t\tname = core;\n\t\t\tpath = ../core;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\tC92A79B110B24C50009B64B9 /* pidgin-sipe */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tB13FAB9C119D585A001CE037 /* core */,\n\t\t\t\tB13FAB4D119D5155001CE037 /* purple */,\n\t\t\t);\n\t\t\tname = \"pidgin-sipe\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXHeadersBuildPhase section */\n\t\t7B1E80021665E5DA00E0C654 /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t7BBE151C184D4BEA0000FFC9 /* DCPurpleSIPEJoinChatViewController.h in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tC92A796510B24BAD009B64B9 /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXHeadersBuildPhase section */\n\n/* Begin PBXNativeTarget section */\n\t\t8D5B49AC048680CD000E48DA /* SIPEAdiumPlugin */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 1DEB913A08733D840010E9CD /* Build configuration list for PBXNativeTarget \"SIPEAdiumPlugin\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tB8F496C51F96858B00ACE906 /* Run Script to create symlinks to separate Adium build directory (optional) */,\n\t\t\t\t7B1E80021665E5DA00E0C654 /* Headers */,\n\t\t\t\t8D5B49AF048680CD000E48DA /* Resources */,\n\t\t\t\t8D5B49B1048680CD000E48DA /* Sources */,\n\t\t\t\t8D5B49B3048680CD000E48DA /* Frameworks */,\n\t\t\t\t7B5DD2EA16DB1DFD00B3D188 /* CopyFiles */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t\tB8E5616822D21F3A00580386 /* PBXBuildRule */,\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t7BB8CC2B183AC198004351FF /* PBXTargetDependency */,\n\t\t\t\tC92A79F210B25023009B64B9 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = SIPEAdiumPlugin;\n\t\t\tproductInstallPath = \"$(HOME)/Library/Bundles\";\n\t\t\tproductName = SIPEAdiumPlugin;\n\t\t\tproductReference = 8D5B49B6048680CD000E48DA /* SIPEAdiumPlugin.AdiumLibpurplePlugin */;\n\t\t\tproductType = \"com.apple.product-type.bundle\";\n\t\t};\n\t\tC92A796810B24BAD009B64B9 /* pidgin-sipe */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = C92A796C10B24BCD009B64B9 /* Build configuration list for PBXNativeTarget \"pidgin-sipe\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tC92A796510B24BAD009B64B9 /* Headers */,\n\t\t\t\tC92A796610B24BAD009B64B9 /* Sources */,\n\t\t\t\tC92A796710B24BAD009B64B9 /* Frameworks */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = \"pidgin-sipe\";\n\t\t\tproductName = \"pidgin-sipe\";\n\t\t\tproductReference = 1C7056D312C1E5820004E43B /* libpidgin-sipe.a */;\n\t\t\tproductType = \"com.apple.product-type.library.static\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t089C1669FE841209C02AAC07 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0610;\n\t\t\t};\n\t\t\tbuildConfigurationList = 1DEB913E08733D840010E9CD /* Build configuration list for PBXProject \"SIPEAdiumPlugin\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 1;\n\t\t\tknownRegions = (\n\t\t\t\tEnglish,\n\t\t\t\tJapanese,\n\t\t\t\tFrench,\n\t\t\t\tGerman,\n\t\t\t);\n\t\t\tmainGroup = 089C166AFE841209C02AAC07 /* SIPEAdiumPlugin */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectReferences = (\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 7BB8CBB4183AA600004351FF /* Products */;\n\t\t\t\t\tProjectRef = 7BB8CBB3183AA600004351FF /* Adium.xcodeproj */;\n\t\t\t\t},\n\t\t\t);\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t8D5B49AC048680CD000E48DA /* SIPEAdiumPlugin */,\n\t\t\t\tC92A796810B24BAD009B64B9 /* pidgin-sipe */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXReferenceProxy section */\n\t\t7BB8CBC2183AA605004351FF /* Adium.app */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = wrapper.application;\n\t\t\tpath = Adium.app;\n\t\t\tremoteRef = 7BB8CBC1183AA605004351FF /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t7BB8CBC4183AA605004351FF /* Adium.framework */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = wrapper.framework;\n\t\t\tpath = Adium.framework;\n\t\t\tremoteRef = 7BB8CBC3183AA605004351FF /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t7BB8CBC6183AA605004351FF /* AdiumLibpurple.framework */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = wrapper.framework;\n\t\t\tpath = AdiumLibpurple.framework;\n\t\t\tremoteRef = 7BB8CBC5183AA605004351FF /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t7BB8CBC8183AA605004351FF /* AIUtilities.framework */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = wrapper.framework;\n\t\t\tpath = AIUtilities.framework;\n\t\t\tremoteRef = 7BB8CBC7183AA605004351FF /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t7BB8CBCA183AA605004351FF /* AdiumApplescriptRunner */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = \"compiled.mach-o.executable\";\n\t\t\tpath = AdiumApplescriptRunner;\n\t\t\tremoteRef = 7BB8CBC9183AA605004351FF /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t7BB8CBCC183AA605004351FF /* Unit tests.octest */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = wrapper.cfbundle;\n\t\t\tpath = \"Unit tests.octest\";\n\t\t\tremoteRef = 7BB8CBCB183AA605004351FF /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t7BB8CBCE183AA605004351FF /* AdiumSpotlightImporter.mdimporter */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = wrapper.cfbundle;\n\t\t\tpath = AdiumSpotlightImporter.mdimporter;\n\t\t\tremoteRef = 7BB8CBCD183AA605004351FF /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n/* End PBXReferenceProxy section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t8D5B49AF048680CD000E48DA /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */,\n\t\t\t\tC9FDAEF6109ADF97004EEEAF /* sipe.png in Resources */,\n\t\t\t\t7B50EFAB16DB326100F897D1 /* PurpleDefaultsSIPE.plist in Resources */,\n\t\t\t\t7BBE1529184D4BF50000FFC9 /* DCPurpleSIPEJoinChatView.xib in Resources */,\n\t\t\t\t7B78055816DEC73400B844A6 /* ESSIPEAccountView.xib in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\tB8F496C51F96858B00ACE906 /* Run Script to create symlinks to separate Adium build directory (optional) */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Run Script to create symlinks to separate Adium build directory (optional)\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = ./find_adium_build.sh;\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t8D5B49B1048680CD000E48DA /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t1CF2612C12C2E73F0045B6CC /* ESPurpleSIPEAccount.m in Sources */,\n\t\t\t\tB8E5616722D21E8E00580386 /* sipe-rtf.l in Sources */,\n\t\t\t\tB89F388F1BDEB10B0017B509 /* purple-plugin-common.c in Sources */,\n\t\t\t\t1CF2612D12C2E7420045B6CC /* ESSIPEService.m in Sources */,\n\t\t\t\tB89F38821BDEB0D30017B509 /* sipe-ft-lync.c in Sources */,\n\t\t\t\t1CF2612E12C2E7430045B6CC /* ESSIPELibpurpleServicePlugin.m in Sources */,\n\t\t\t\t7BBE151D184D4BEA0000FFC9 /* DCPurpleSIPEJoinChatViewController.m in Sources */,\n\t\t\t\tB89F388D1BDEB0F00017B509 /* sipe-mime-common.c in Sources */,\n\t\t\t\t1CDEE46112C35DAD00790CAF /* ESSIPEAccountViewController.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tC92A796610B24BAD009B64B9 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t5AAF284A184E4172007481FA /* sipe-cert-crypto-openssl.c in Sources */,\n\t\t\t\t5AAF284B184E4172007481FA /* sipe-crypt-openssl.c in Sources */,\n\t\t\t\t5AAF284C184E4172007481FA /* sipe-digest-openssl.c in Sources */,\n\t\t\t\t5AAF284D184E4172007481FA /* sipe-http-request.c in Sources */,\n\t\t\t\t5AAF284E184E4172007481FA /* sipe-http-transport.c in Sources */,\n\t\t\t\t5AAF284F184E4172007481FA /* sipe-http.c in Sources */,\n\t\t\t\t5AAF2850184E4172007481FA /* sip-sec-negotiate.c in Sources */,\n\t\t\t\t5AAF2851184E4172007481FA /* sip-sec-basic.c in Sources */,\n\t\t\t\tB13FAB5F119D5155001CE037 /* purple-connection.c in Sources */,\n\t\t\t\tB13FAB61119D5155001CE037 /* purple-debug.c in Sources */,\n\t\t\t\tB13FAB63119D5155001CE037 /* purple-dnsquery.c in Sources */,\n\t\t\t\tB13FAB64119D5155001CE037 /* purple-markup.c in Sources */,\n\t\t\t\tB13FAB66119D5155001CE037 /* purple-mime.c in Sources */,\n\t\t\t\tB13FAB67119D5155001CE037 /* purple-network.c in Sources */,\n\t\t\t\tB13FAB68119D5155001CE037 /* purple-plugin.c in Sources */,\n\t\t\t\tB13FAB6A119D5155001CE037 /* purple-schedule.c in Sources */,\n\t\t\t\tB13FAB6B119D5155001CE037 /* purple-setting.c in Sources */,\n\t\t\t\tB13FAB6C119D5155001CE037 /* purple-transport.c in Sources */,\n\t\t\t\tB13FABDF119D585A001CE037 /* sip-csta.c in Sources */,\n\t\t\t\tB13FABE1119D585A001CE037 /* sip-sec-gssapi.c in Sources */,\n\t\t\t\tB13FABE5119D585A001CE037 /* sip-sec-ntlm.c in Sources */,\n\t\t\t\tB13FABE9119D585A001CE037 /* sip-sec.c in Sources */,\n\t\t\t\tB13FABEB119D585A001CE037 /* sip-transport.c in Sources */,\n\t\t\t\tB13FABED119D585A001CE037 /* sipe-buddy.c in Sources */,\n\t\t\t\tB13FABEF119D585A001CE037 /* sipe-cal.c in Sources */,\n\t\t\t\tB13FABF1119D585A001CE037 /* sipe-chat.c in Sources */,\n\t\t\t\tB13FABF3119D585A001CE037 /* sipe-conf.c in Sources */,\n\t\t\t\tB13FABF6119D585A001CE037 /* sipe-core.c in Sources */,\n\t\t\t\tB13FABF8119D585A001CE037 /* sipe-dialog.c in Sources */,\n\t\t\t\tB13FABFD119D585A001CE037 /* sipe-ews.c in Sources */,\n\t\t\t\tB13FABFE119D585A001CE037 /* sipe-ews-autodiscover.c in Sources */,\n\t\t\t\tB13FABFF119D585A001CE037 /* sipe-ft.c in Sources */,\n\t\t\t\tB13FAC00119D585A001CE037 /* sipe-lync-autodiscover.c in Sources */,\n\t\t\t\tB13FAC04119D585A001CE037 /* sipe-schedule.c in Sources */,\n\t\t\t\tB13FAC06119D585A001CE037 /* sipe-session.c in Sources */,\n\t\t\t\tB13FAC08119D585A001CE037 /* sipe-sign.c in Sources */,\n\t\t\t\tB13FAC0A119D585A001CE037 /* sipe-utils.c in Sources */,\n\t\t\t\tB13FAC0F119D585A001CE037 /* sipe-xml.c in Sources */,\n\t\t\t\tB13FAC13119D585A001CE037 /* sipmsg.c in Sources */,\n\t\t\t\tB13FAC15119D585A001CE037 /* uuid.c in Sources */,\n\t\t\t\t1CF260F912C2DFA00045B6CC /* purple-buddy.c in Sources */,\n\t\t\t\t1CF260FA12C2DFA00045B6CC /* purple-chat.c in Sources */,\n\t\t\t\t1CF260FB12C2DFA00045B6CC /* purple-ft.c in Sources */,\n\t\t\t\t1CF260FC12C2DFA00045B6CC /* purple-groupchat.c in Sources */,\n\t\t\t\t1CF260FD12C2DFA00045B6CC /* purple-im.c in Sources */,\n\t\t\t\t1CF260FF12C2DFA00045B6CC /* purple-notify.c in Sources */,\n\t\t\t\t1CF2610012C2DFA00045B6CC /* purple-user.c in Sources */,\n\t\t\t\t1CF2611812C2E1AA0045B6CC /* sipe-groupchat.c in Sources */,\n\t\t\t\t1CF2611912C2E1AA0045B6CC /* sipe-incoming.c in Sources */,\n\t\t\t\t1CF2611B12C2E1AA0045B6CC /* sipe-ucs.c in Sources */,\n\t\t\t\t1CF2611C12C2E1AA0045B6CC /* sipe-subscriptions.c in Sources */,\n\t\t\t\t1CF2611D12C2E1AA0045B6CC /* sipe-user.c in Sources */,\n\t\t\t\t1C822BED12F8E87500CC4AEA /* sipe-im.c in Sources */,\n\t\t\t\t1CD71E3413C5380B0079DE64 /* sipe-ft-tftp.c in Sources */,\n\t\t\t\t1CD71E3B13C538340079DE64 /* sipe-group.c in Sources */,\n\t\t\t\t1CE49FB914A17CF000663393 /* sipe-svc.c in Sources */,\n\t\t\t\t1CE49FBA14A17CF000663393 /* sipe-ocs2007.c in Sources */,\n\t\t\t\t1CE49FBB14A17CF000663393 /* sipe-ocs2005.c in Sources */,\n\t\t\t\t1CE49FEA14A17EF000663393 /* sipe-status.c in Sources */,\n\t\t\t\t1CE49FF314A17F4D00663393 /* sip-soap.c in Sources */,\n\t\t\t\t1CE49FF414A17F4D00663393 /* sipe-notify.c in Sources */,\n\t\t\t\t1CE49FF514A17F4D00663393 /* sipe-webticket.c in Sources */,\n\t\t\t\t1CE4A00714A17FD100663393 /* sip-sec-digest.c in Sources */,\n\t\t\t\t1CE4A00814A17FD100663393 /* sip-sec-tls-dsk.c in Sources */,\n\t\t\t\t1CE4A00A14A17FD100663393 /* sipe-certificate.c in Sources */,\n\t\t\t\t1CE4A00D14A17FD100663393 /* sipe-tls.c in Sources */,\n\t\t\t\t1CE4A01E14A180E100663393 /* purple-search.c in Sources */,\n\t\t\t\t1CE4A01F14A180E100663393 /* purple-status.c in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t7BB8CC2B183AC198004351FF /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\tname = Adium;\n\t\t\ttargetProxy = 7BB8CC2A183AC198004351FF /* PBXContainerItemProxy */;\n\t\t};\n\t\tC92A79F210B25023009B64B9 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = C92A796810B24BAD009B64B9 /* pidgin-sipe */;\n\t\t\ttargetProxy = C92A79F110B25023009B64B9 /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin PBXVariantGroup section */\n\t\t089C167DFE841241C02AAC07 /* InfoPlist.strings */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t089C167EFE841241C02AAC07 /* English */,\n\t\t\t);\n\t\t\tname = InfoPlist.strings;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\t7BBE1527184D4BF50000FFC9 /* DCPurpleSIPEJoinChatView.xib */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t7BBE1528184D4BF50000FFC9 /* English */,\n\t\t\t);\n\t\t\tname = DCPurpleSIPEJoinChatView.xib;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t1DEB913B08733D840010E9CD /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7BB8CB97183AA0BD004351FF /* SIPEAdiumPlugin.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1DEB913C08733D840010E9CD /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7BB8CB97183AA0BD004351FF /* SIPEAdiumPlugin.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t1DEB913F08733D840010E9CD /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7BB8CB93183AA0BD004351FF /* Debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1DEB914008733D840010E9CD /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7BB8CB96183AA0BD004351FF /* Release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t7BB8CBFE183AB83D004351FF /* Debug-Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7BB8CB92183AA0BD004351FF /* Debug-Release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t};\n\t\t\tname = \"Debug-Release\";\n\t\t};\n\t\t7BB8CBFF183AB83D004351FF /* Debug-Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7BB8CB97183AA0BD004351FF /* SIPEAdiumPlugin.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t};\n\t\t\tname = \"Debug-Release\";\n\t\t};\n\t\t7BB8CC00183AB83D004351FF /* Debug-Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7BB8CB94183AA0BD004351FF /* libpidgin-sipe.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t};\n\t\t\tname = \"Debug-Release\";\n\t\t};\n\t\tC92A796A10B24BAD009B64B9 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7BB8CB94183AA0BD004351FF /* libpidgin-sipe.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tC92A796B10B24BAD009B64B9 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7BB8CB94183AA0BD004351FF /* libpidgin-sipe.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t1DEB913A08733D840010E9CD /* Build configuration list for PBXNativeTarget \"SIPEAdiumPlugin\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1DEB913B08733D840010E9CD /* Debug */,\n\t\t\t\t1DEB913C08733D840010E9CD /* Release */,\n\t\t\t\t7BB8CBFF183AB83D004351FF /* Debug-Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t1DEB913E08733D840010E9CD /* Build configuration list for PBXProject \"SIPEAdiumPlugin\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1DEB913F08733D840010E9CD /* Debug */,\n\t\t\t\t1DEB914008733D840010E9CD /* Release */,\n\t\t\t\t7BB8CBFE183AB83D004351FF /* Debug-Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tC92A796C10B24BCD009B64B9 /* Build configuration list for PBXNativeTarget \"pidgin-sipe\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tC92A796A10B24BAD009B64B9 /* Debug */,\n\t\t\t\tC92A796B10B24BAD009B64B9 /* Release */,\n\t\t\t\t7BB8CC00183AB83D004351FF /* Debug-Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 089C1669FE841209C02AAC07 /* Project object */;\n}\n"
  },
  {
    "path": "src/adium/SIPEAdiumPlugin.xcodeproj/xcshareddata/xcschemes/SIPEAdiumPlugin.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0610\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"8D5B49AC048680CD000E48DA\"\n               BuildableName = \"SIPEAdiumPlugin.AdiumLibpurplePlugin\"\n               BlueprintName = \"SIPEAdiumPlugin\"\n               ReferencedContainer = \"container:SIPEAdiumPlugin.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      buildConfiguration = \"Debug\">\n      <Testables>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"34BD9CD1053146CC000AB133\"\n            BuildableName = \"Adium.app\"\n            BlueprintName = \"Adium\"\n            ReferencedContainer = \"container:../../../adium/Adium.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </TestAction>\n   <LaunchAction\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      buildConfiguration = \"Debug\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"34BD9CD1053146CC000AB133\"\n            BuildableName = \"Adium.app\"\n            BlueprintName = \"Adium\"\n            ReferencedContainer = \"container:../../../adium/Adium.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      buildConfiguration = \"Release\"\n      debugDocumentVersioning = \"YES\">\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "src/adium/SIPEAdiumPlugin.xcodeproj/xcshareddata/xcschemes/pidgin-sipe.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0610\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"C92A796810B24BAD009B64B9\"\n               BuildableName = \"libpidgin-sipe.a\"\n               BlueprintName = \"pidgin-sipe\"\n               ReferencedContainer = \"container:SIPEAdiumPlugin.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      buildConfiguration = \"Debug\">\n      <Testables>\n      </Testables>\n   </TestAction>\n   <LaunchAction\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      buildConfiguration = \"Debug\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      allowLocationSimulation = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"C92A796810B24BAD009B64B9\"\n            BuildableName = \"libpidgin-sipe.a\"\n            BlueprintName = \"pidgin-sipe\"\n            ReferencedContainer = \"container:SIPEAdiumPlugin.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      buildConfiguration = \"Release\"\n      debugDocumentVersioning = \"YES\">\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "src/adium/SIPEAdiumPlugin_Prefix.pch",
    "content": "//\n// Prefix header for all source files of the 'SIPEAdiumPlugin' target in the 'SIPEAdiumPlugin' project.\n//\n\n#ifdef __OBJC__\n    #import <Cocoa/Cocoa.h>\n#endif\n"
  },
  {
    "path": "src/adium/check_release.sh",
    "content": "#!/bin/bash\n#\n# Compare release contents with golden list to ensure release correctness\n#\nif [[ -z \"$1\" ]]; then\n    echo 1>&2 \"usage: $0 <SIPEAdiumPlugin zip file>\"\n    exit 1\nfi\n\n# examine release archive\necho \"Checking release archive '$1'...\"\nfiles=$(set -o pipefail; unzip -l \"$1\" |\n    grep SIPEAdiumPlugin.AdiumLibpurplePlugin/ |\n    awk '{ print $4, $1 }' |\n    grep -v '/ 0')\nif [[ $? -ne 0 ]]; then\n    echo 1>&2 \"ERROR: can't analyze release archive '$1'!\"\n    exit 1\nfi\n\n# the following files *MUST* be in the release archive\ndeclare -A golden_list\ngolden_list=(\n    [SIPEAdiumPlugin.AdiumLibpurplePlugin/Contents/Info.plist]=1\n    [SIPEAdiumPlugin.AdiumLibpurplePlugin/Contents/MacOS/SIPEAdiumPlugin]=1\n    [SIPEAdiumPlugin.AdiumLibpurplePlugin/Contents/Resources/English.lproj/DCPurpleSIPEJoinChatView.nib]=1\n    [SIPEAdiumPlugin.AdiumLibpurplePlugin/Contents/Resources/English.lproj/InfoPlist.strings]=1\n    [SIPEAdiumPlugin.AdiumLibpurplePlugin/Contents/Resources/ESSIPEAccountView.nib]=1\n    [SIPEAdiumPlugin.AdiumLibpurplePlugin/Contents/Resources/PurpleDefaultsSIPE.plist]=1\n    [SIPEAdiumPlugin.AdiumLibpurplePlugin/Contents/Resources/sipe.png]=1\n)\nnew_files=()\n\n# compare against golden list\n# @TODO: is there a better way to feed in file list?\nwhile read file size; do\n    if [[ -z \"${golden_list[${file}]}\" ]]; then\n        new_files+=( $file )\n    elif [[ \"${size}\" -eq 0 ]]; then\n        echo 1>&2 \"ERROR: file '${file}' is empty!\"\n    else\n        unset golden_list[${file}]\n    fi\ndone <<EOF\n${files[@]}\nEOF\n\n# check for errors\nstatus=0\nif [[ -n \"${new_files[@]}\" ]]; then\n    echo 1>&2 \"Release archive contains superfluous files:\"\n    for file in \"${new_files[@]}\"; do\n        echo -e 1>&2 \"\\t${file}\"\n    done\n    status=1\nfi\nif [[ ${#golden_list[@]} -ne 0 ]]; then\n    echo 1>&2 \"Release archive is missing the following files:\"\n    for file in \"${!golden_list[@]}\"; do\n        echo -e 1>&2 \"\\t${file}\"\n    done\n    status=1\nfi\nif [[ $status -eq 0 ]]; then\n    echo \"Release archive is OK!\"\nelse\n    echo \"Release archive is NOT OK!\"\nfi\nexit $status\n"
  },
  {
    "path": "src/adium/find_adium_build.sh",
    "content": "#!/bin/sh\nset -e\n#set -x\n\n# remove old symlink setup\nrm -rf adium-frameworks\n\n# create empty directory to keep linker happy\nmkdir adium-frameworks\n\n# if Adium is built as sub-project -> skip\nif [[ ( -d \"${BUILT_PRODUCTS_DIR}/Adium.framework\" )          ||\n      ( -d \"${BUILT_PRODUCTS_DIR}/AdiumLibPurple.framework\" ) ||\n      ( -d \"${BUILT_PRODUCTS_DIR}/AIUtilities.framework\" ) ]]; then\n\techo 1>&2 \"Building Adium within SIPEAdiumPlugin - aborting...\"\n\texit 0\nfi\n\n_sipe_build_dir=$(cd \"${BUILT_PRODUCTS_DIR}/../../..\"; pwd -P)\nif [[ ! -d \"${_sipe_build_dir}\" ]]; then\n\techo 1>&2 \"can't detect SIPE build directory from '${BUILT_PRODUCTS_DIR}'\"\n\texit 1\nfi\n\n_build_dir=$(cd \"${_sipe_build_dir}/..\"; pwd -P)\nif [[ ! -d \"${_build_dir}\" ]]; then\n\techo 1>&2 \"can't detect common build directory from '${_sipe_build_dir}'\"\n\texit 1\nfi\n\n_adium_build_dir=( $(find \"${_build_dir}\" -maxdepth 1 -type d -name \"Adium-*\" ) )\nif [[ ${#_adium_build_dir[@]} -ne 1 ]]; then\n\techo 1>&2 \"can't detect Adium build directory from '${_build_dir}'\"\n\texit 1\nfi\n\n# create symlinks to Adium frameworks\n_frameworks_dir=\"${BUILT_PRODUCTS_DIR/#${_sipe_build_dir}/${_adium_build_dir[0]}}\"\n_adium_dirs=(\n\tAdium.framework\n\tAdiumLibPurple.framework\n\tAIUtilities.framework\n)\nln -s ${_adium_dirs[@]/#/${_frameworks_dir}/} adium-frameworks/\n\n# log result\nls -lhtR adium-frameworks\nexit 0\n"
  },
  {
    "path": "src/adium/openssl/libcrypto.0.9.8.tbd",
    "content": "---\narchs:           [ i386, x86_64 ]\nplatform:        macosx\ninstall-name:    /usr/lib/libcrypto.0.9.8.dylib\ncurrent-version: 0.9.8\ncompatibility-version: 0.9.8\nexports:         \n  - archs:           [ i386, x86_64 ]\n    symbols:         [ _ACCESS_DESCRIPTION_free, _ACCESS_DESCRIPTION_it, \n                       _ACCESS_DESCRIPTION_new, _AES_bi_ige_encrypt, _AES_cbc_encrypt, \n                       _AES_cfb128_encrypt, _AES_cfb1_encrypt, _AES_cfb8_encrypt, \n                       _AES_cfbr_encrypt_block, _AES_ctr128_encrypt, _AES_decrypt, \n                       _AES_ecb_encrypt, _AES_encrypt, _AES_ige_encrypt, \n                       _AES_ofb128_encrypt, _AES_options, _AES_set_decrypt_key, \n                       _AES_set_encrypt_key, _AES_unwrap_key, _AES_version, \n                       _AES_wrap_key, _ASN1_ANY_it, _ASN1_BIT_STRING_asn1_meth, \n                       _ASN1_BIT_STRING_free, _ASN1_BIT_STRING_get_bit, \n                       _ASN1_BIT_STRING_it, _ASN1_BIT_STRING_name_print, \n                       _ASN1_BIT_STRING_new, _ASN1_BIT_STRING_num_asc, \n                       _ASN1_BIT_STRING_set, _ASN1_BIT_STRING_set_asc, \n                       _ASN1_BIT_STRING_set_bit, _ASN1_BMPSTRING_free, \n                       _ASN1_BMPSTRING_it, _ASN1_BMPSTRING_new, _ASN1_BOOLEAN_it, \n                       _ASN1_ENUMERATED_free, _ASN1_ENUMERATED_get, _ASN1_ENUMERATED_it, \n                       _ASN1_ENUMERATED_new, _ASN1_ENUMERATED_set, _ASN1_ENUMERATED_to_BN, \n                       _ASN1_FBOOLEAN_it, _ASN1_GENERALIZEDTIME_check, \n                       _ASN1_GENERALIZEDTIME_free, _ASN1_GENERALIZEDTIME_it, \n                       _ASN1_GENERALIZEDTIME_new, _ASN1_GENERALIZEDTIME_print, \n                       _ASN1_GENERALIZEDTIME_set, _ASN1_GENERALIZEDTIME_set_string, \n                       _ASN1_GENERALSTRING_free, _ASN1_GENERALSTRING_it, \n                       _ASN1_GENERALSTRING_new, _ASN1_HEADER_free, _ASN1_HEADER_new, \n                       _ASN1_IA5STRING_asn1_meth, _ASN1_IA5STRING_free, \n                       _ASN1_IA5STRING_it, _ASN1_IA5STRING_new, _ASN1_INTEGER_cmp, \n                       _ASN1_INTEGER_dup, _ASN1_INTEGER_free, _ASN1_INTEGER_get, \n                       _ASN1_INTEGER_it, _ASN1_INTEGER_new, _ASN1_INTEGER_set, \n                       _ASN1_INTEGER_to_BN, _ASN1_NULL_free, _ASN1_NULL_it, \n                       _ASN1_NULL_new, _ASN1_OBJECT_create, _ASN1_OBJECT_free, \n                       _ASN1_OBJECT_it, _ASN1_OBJECT_new, _ASN1_OCTET_STRING_NDEF_it, \n                       _ASN1_OCTET_STRING_cmp, _ASN1_OCTET_STRING_dup, \n                       _ASN1_OCTET_STRING_free, _ASN1_OCTET_STRING_it, \n                       _ASN1_OCTET_STRING_new, _ASN1_OCTET_STRING_set, \n                       _ASN1_PRINTABLESTRING_free, _ASN1_PRINTABLESTRING_it, \n                       _ASN1_PRINTABLESTRING_new, _ASN1_PRINTABLE_free, \n                       _ASN1_PRINTABLE_it, _ASN1_PRINTABLE_new, _ASN1_PRINTABLE_type, \n                       _ASN1_SEQUENCE_it, _ASN1_STRING_TABLE_add, _ASN1_STRING_TABLE_cleanup, \n                       _ASN1_STRING_TABLE_get, _ASN1_STRING_cmp, _ASN1_STRING_data, \n                       _ASN1_STRING_dup, _ASN1_STRING_encode, _ASN1_STRING_free, \n                       _ASN1_STRING_get_default_mask, _ASN1_STRING_length, \n                       _ASN1_STRING_length_set, _ASN1_STRING_new, _ASN1_STRING_print, \n                       _ASN1_STRING_print_ex, _ASN1_STRING_print_ex_fp, \n                       _ASN1_STRING_set, _ASN1_STRING_set0, _ASN1_STRING_set_by_NID, \n                       _ASN1_STRING_set_default_mask, _ASN1_STRING_set_default_mask_asc, \n                       _ASN1_STRING_to_UTF8, _ASN1_STRING_type, _ASN1_STRING_type_new, \n                       _ASN1_T61STRING_free, _ASN1_T61STRING_it, _ASN1_T61STRING_new, \n                       _ASN1_TBOOLEAN_it, _ASN1_TIME_check, _ASN1_TIME_free, \n                       _ASN1_TIME_it, _ASN1_TIME_new, _ASN1_TIME_print, \n                       _ASN1_TIME_set, _ASN1_TIME_to_generalizedtime, _ASN1_TYPE_cmp, \n                       _ASN1_TYPE_free, _ASN1_TYPE_get, _ASN1_TYPE_get_int_octetstring, \n                       _ASN1_TYPE_get_octetstring, _ASN1_TYPE_new, _ASN1_TYPE_set, \n                       _ASN1_TYPE_set1, _ASN1_TYPE_set_int_octetstring, \n                       _ASN1_TYPE_set_octetstring, _ASN1_UNIVERSALSTRING_free, \n                       _ASN1_UNIVERSALSTRING_it, _ASN1_UNIVERSALSTRING_new, \n                       _ASN1_UNIVERSALSTRING_to_string, _ASN1_UTCTIME_check, \n                       _ASN1_UTCTIME_cmp_time_t, _ASN1_UTCTIME_free, _ASN1_UTCTIME_it, \n                       _ASN1_UTCTIME_new, _ASN1_UTCTIME_print, _ASN1_UTCTIME_set, \n                       _ASN1_UTCTIME_set_string, _ASN1_UTF8STRING_free, \n                       _ASN1_UTF8STRING_it, _ASN1_UTF8STRING_new, _ASN1_VISIBLESTRING_free, \n                       _ASN1_VISIBLESTRING_it, _ASN1_VISIBLESTRING_new, \n                       _ASN1_add_oid_module, _ASN1_check_infinite_end, \n                       _ASN1_const_check_infinite_end, _ASN1_d2i_bio, _ASN1_d2i_fp, \n                       _ASN1_digest, _ASN1_dup, _ASN1_generate_nconf, _ASN1_generate_v3, \n                       _ASN1_get_object, _ASN1_i2d_bio, _ASN1_i2d_fp, _ASN1_item_d2i, \n                       _ASN1_item_d2i_bio, _ASN1_item_d2i_fp, _ASN1_item_digest, \n                       _ASN1_item_dup, _ASN1_item_ex_d2i, _ASN1_item_ex_free, \n                       _ASN1_item_ex_i2d, _ASN1_item_ex_new, _ASN1_item_free, \n                       _ASN1_item_i2d, _ASN1_item_i2d_bio, _ASN1_item_i2d_fp, \n                       _ASN1_item_ndef_i2d, _ASN1_item_new, _ASN1_item_pack, \n                       _ASN1_item_sign, _ASN1_item_unpack, _ASN1_item_verify, \n                       _ASN1_mbstring_copy, _ASN1_mbstring_ncopy, _ASN1_object_size, \n                       _ASN1_pack_string, _ASN1_parse, _ASN1_parse_dump, \n                       _ASN1_primitive_free, _ASN1_primitive_new, _ASN1_put_eoc, \n                       _ASN1_put_object, _ASN1_seq_pack, _ASN1_seq_unpack, \n                       _ASN1_sign, _ASN1_tag2bit, _ASN1_tag2str, _ASN1_template_d2i, \n                       _ASN1_template_free, _ASN1_template_i2d, _ASN1_template_new, \n                       _ASN1_unpack_string, _ASN1_verify, _ASN1_version, \n                       _AUTHORITY_INFO_ACCESS_free, _AUTHORITY_INFO_ACCESS_it, \n                       _AUTHORITY_INFO_ACCESS_new, _AUTHORITY_KEYID_free, \n                       _AUTHORITY_KEYID_it, _AUTHORITY_KEYID_new, _BASIC_CONSTRAINTS_free, \n                       _BASIC_CONSTRAINTS_it, _BASIC_CONSTRAINTS_new, _BF_cbc_encrypt, \n                       _BF_cfb64_encrypt, _BF_decrypt, _BF_ecb_encrypt, \n                       _BF_encrypt, _BF_ofb64_encrypt, _BF_options, _BF_set_key, \n                       _BF_version, _BIGNUM_it, _BIO_ACCEPT_free, _BIO_ACCEPT_new, \n                       _BIO_CONNECT_free, _BIO_CONNECT_new, _BIO_accept, \n                       _BIO_callback_ctrl, _BIO_clear_flags, _BIO_copy_next_retry, \n                       _BIO_ctrl, _BIO_ctrl_get_read_request, _BIO_ctrl_get_write_guarantee, \n                       _BIO_ctrl_pending, _BIO_ctrl_reset_read_request, \n                       _BIO_ctrl_wpending, _BIO_debug_callback, _BIO_dgram_non_fatal_error, \n                       _BIO_dump, _BIO_dump_cb, _BIO_dump_fp, _BIO_dump_indent, \n                       _BIO_dump_indent_cb, _BIO_dump_indent_fp, _BIO_dup_chain, \n                       _BIO_f_base64, _BIO_f_buffer, _BIO_f_cipher, _BIO_f_md, \n                       _BIO_f_nbio_test, _BIO_f_null, _BIO_f_reliable, \n                       _BIO_f_zlib, _BIO_fd_non_fatal_error, _BIO_fd_should_retry, \n                       _BIO_find_type, _BIO_free, _BIO_free_all, _BIO_get_accept_socket, \n                       _BIO_get_callback, _BIO_get_callback_arg, _BIO_get_ex_data, \n                       _BIO_get_ex_new_index, _BIO_get_host_ip, _BIO_get_port, \n                       _BIO_get_retry_BIO, _BIO_get_retry_reason, _BIO_gethostbyname, \n                       _BIO_gets, _BIO_indent, _BIO_int_ctrl, _BIO_method_name, \n                       _BIO_method_type, _BIO_new, _BIO_new_accept, _BIO_new_bio_pair, \n                       _BIO_new_connect, _BIO_new_dgram, _BIO_new_fd, _BIO_new_file, \n                       _BIO_new_fp, _BIO_new_mem_buf, _BIO_new_socket, \n                       _BIO_next, _BIO_nread, _BIO_nread0, _BIO_number_read, \n                       _BIO_number_written, _BIO_nwrite, _BIO_nwrite0, \n                       _BIO_pop, _BIO_printf, _BIO_ptr_ctrl, _BIO_push, \n                       _BIO_puts, _BIO_read, _BIO_s_accept, _BIO_s_bio, \n                       _BIO_s_connect, _BIO_s_datagram, _BIO_s_fd, _BIO_s_file, \n                       _BIO_s_log, _BIO_s_mem, _BIO_s_null, _BIO_s_socket, \n                       _BIO_set, _BIO_set_callback, _BIO_set_callback_arg, \n                       _BIO_set_cipher, _BIO_set_ex_data, _BIO_set_flags, \n                       _BIO_set_tcp_ndelay, _BIO_snprintf, _BIO_sock_cleanup, \n                       _BIO_sock_error, _BIO_sock_init, _BIO_sock_non_fatal_error, \n                       _BIO_sock_should_retry, _BIO_socket_ioctl, _BIO_socket_nbio, \n                       _BIO_test_flags, _BIO_vfree, _BIO_vprintf, _BIO_vsnprintf, \n                       _BIO_write, _BN_BLINDING_convert, _BN_BLINDING_convert_ex, \n                       _BN_BLINDING_create_param, _BN_BLINDING_free, _BN_BLINDING_get_flags, \n                       _BN_BLINDING_get_thread_id, _BN_BLINDING_invert, \n                       _BN_BLINDING_invert_ex, _BN_BLINDING_new, _BN_BLINDING_set_flags, \n                       _BN_BLINDING_set_thread_id, _BN_BLINDING_update, \n                       _BN_CTX_end, _BN_CTX_free, _BN_CTX_get, _BN_CTX_init, \n                       _BN_CTX_new, _BN_CTX_start, _BN_GENCB_call, _BN_GF2m_add, \n                       _BN_GF2m_arr2poly, _BN_GF2m_mod, _BN_GF2m_mod_arr, \n                       _BN_GF2m_mod_div, _BN_GF2m_mod_div_arr, _BN_GF2m_mod_exp, \n                       _BN_GF2m_mod_exp_arr, _BN_GF2m_mod_inv, _BN_GF2m_mod_inv_arr, \n                       _BN_GF2m_mod_mul, _BN_GF2m_mod_mul_arr, _BN_GF2m_mod_solve_quad, \n                       _BN_GF2m_mod_solve_quad_arr, _BN_GF2m_mod_sqr, _BN_GF2m_mod_sqr_arr, \n                       _BN_GF2m_mod_sqrt, _BN_GF2m_mod_sqrt_arr, _BN_GF2m_poly2arr, \n                       _BN_MONT_CTX_copy, _BN_MONT_CTX_free, _BN_MONT_CTX_init, \n                       _BN_MONT_CTX_new, _BN_MONT_CTX_set, _BN_MONT_CTX_set_locked, \n                       _BN_RECP_CTX_free, _BN_RECP_CTX_init, _BN_RECP_CTX_new, \n                       _BN_RECP_CTX_set, _BN_X931_derive_prime_ex, _BN_X931_generate_Xpq, \n                       _BN_X931_generate_prime_ex, _BN_add, _BN_add_word, \n                       _BN_bin2bn, _BN_bn2bin, _BN_bn2dec, _BN_bn2hex, \n                       _BN_bn2mpi, _BN_bntest_rand, _BN_clear, _BN_clear_bit, \n                       _BN_clear_free, _BN_cmp, _BN_consttime_swap, _BN_copy, \n                       _BN_dec2bn, _BN_div, _BN_div_recp, _BN_div_word, \n                       _BN_dup, _BN_exp, _BN_free, _BN_from_montgomery, \n                       _BN_gcd, _BN_generate_prime, _BN_generate_prime_ex, \n                       _BN_get0_nist_prime_192, _BN_get0_nist_prime_224, \n                       _BN_get0_nist_prime_256, _BN_get0_nist_prime_384, \n                       _BN_get0_nist_prime_521, _BN_get_params, _BN_get_word, \n                       _BN_hex2bn, _BN_init, _BN_is_bit_set, _BN_is_prime, \n                       _BN_is_prime_ex, _BN_is_prime_fasttest, _BN_is_prime_fasttest_ex, \n                       _BN_kronecker, _BN_lshift, _BN_lshift1, _BN_mask_bits, \n                       _BN_mod_add, _BN_mod_add_quick, _BN_mod_exp, _BN_mod_exp2_mont, \n                       _BN_mod_exp_mont, _BN_mod_exp_mont_consttime, _BN_mod_exp_mont_word, \n                       _BN_mod_exp_recp, _BN_mod_exp_simple, _BN_mod_inverse, \n                       _BN_mod_lshift, _BN_mod_lshift1, _BN_mod_lshift1_quick, \n                       _BN_mod_lshift_quick, _BN_mod_mul, _BN_mod_mul_montgomery, \n                       _BN_mod_mul_reciprocal, _BN_mod_sqr, _BN_mod_sqrt, \n                       _BN_mod_sub, _BN_mod_sub_quick, _BN_mod_word, _BN_mpi2bn, \n                       _BN_mul, _BN_mul_word, _BN_new, _BN_nist_mod_192, \n                       _BN_nist_mod_224, _BN_nist_mod_256, _BN_nist_mod_384, \n                       _BN_nist_mod_521, _BN_nnmod, _BN_num_bits, _BN_num_bits_word, \n                       _BN_options, _BN_print, _BN_print_fp, _BN_pseudo_rand, \n                       _BN_pseudo_rand_range, _BN_rand, _BN_rand_range, \n                       _BN_reciprocal, _BN_rshift, _BN_rshift1, _BN_set_bit, \n                       _BN_set_negative, _BN_set_params, _BN_set_word, \n                       _BN_sqr, _BN_sub, _BN_sub_word, _BN_swap, _BN_to_ASN1_ENUMERATED, \n                       _BN_to_ASN1_INTEGER, _BN_uadd, _BN_ucmp, _BN_usub, \n                       _BN_value_one, _BN_version, _BUF_MEM_free, _BUF_MEM_grow, \n                       _BUF_MEM_grow_clean, _BUF_MEM_new, _BUF_memdup, \n                       _BUF_strdup, _BUF_strlcat, _BUF_strlcpy, _BUF_strndup, \n                       _CAST_S_table0, _CAST_S_table1, _CAST_S_table2, \n                       _CAST_S_table3, _CAST_S_table4, _CAST_S_table5, \n                       _CAST_S_table6, _CAST_S_table7, _CAST_cbc_encrypt, \n                       _CAST_cfb64_encrypt, _CAST_decrypt, _CAST_ecb_encrypt, \n                       _CAST_encrypt, _CAST_ofb64_encrypt, _CAST_set_key, \n                       _CAST_version, _CBIGNUM_it, _CERTIFICATEPOLICIES_free, \n                       _CERTIFICATEPOLICIES_it, _CERTIFICATEPOLICIES_new, \n                       _COMP_CTX_free, _COMP_CTX_new, _COMP_compress_block, \n                       _COMP_expand_block, _COMP_rle, _COMP_zlib, _COMP_zlib_cleanup, \n                       _CONF_def_version, _CONF_dump_bio, _CONF_dump_fp, \n                       _CONF_free, _CONF_get1_default_config_file, _CONF_get_number, \n                       _CONF_get_section, _CONF_get_string, _CONF_imodule_get_flags, \n                       _CONF_imodule_get_module, _CONF_imodule_get_name, \n                       _CONF_imodule_get_usr_data, _CONF_imodule_get_value, \n                       _CONF_imodule_set_flags, _CONF_imodule_set_usr_data, \n                       _CONF_load, _CONF_load_bio, _CONF_load_fp, _CONF_module_add, \n                       _CONF_module_get_usr_data, _CONF_module_set_usr_data, \n                       _CONF_modules_finish, _CONF_modules_free, _CONF_modules_load, \n                       _CONF_modules_load_file, _CONF_modules_unload, _CONF_parse_list, \n                       _CONF_set_default_method, _CONF_set_nconf, _CONF_version, \n                       _CRL_DIST_POINTS_free, _CRL_DIST_POINTS_it, _CRL_DIST_POINTS_new, \n                       _CRYPTO_add_lock, _CRYPTO_cleanup_all_ex_data, _CRYPTO_dbg_free, \n                       _CRYPTO_dbg_get_options, _CRYPTO_dbg_malloc, _CRYPTO_dbg_pop_info, \n                       _CRYPTO_dbg_push_info, _CRYPTO_dbg_realloc, _CRYPTO_dbg_remove_all_info, \n                       _CRYPTO_dbg_set_options, _CRYPTO_destroy_dynlockid, \n                       _CRYPTO_dup_ex_data, _CRYPTO_ex_data_new_class, \n                       _CRYPTO_free, _CRYPTO_free_ex_data, _CRYPTO_free_locked, \n                       _CRYPTO_get_add_lock_callback, _CRYPTO_get_dynlock_create_callback, \n                       _CRYPTO_get_dynlock_destroy_callback, _CRYPTO_get_dynlock_lock_callback, \n                       _CRYPTO_get_dynlock_value, _CRYPTO_get_ex_data, \n                       _CRYPTO_get_ex_data_implementation, _CRYPTO_get_ex_new_index, \n                       _CRYPTO_get_id_callback, _CRYPTO_get_lock_name, \n                       _CRYPTO_get_locked_mem_ex_functions, _CRYPTO_get_locked_mem_functions, \n                       _CRYPTO_get_locking_callback, _CRYPTO_get_mem_debug_functions, \n                       _CRYPTO_get_mem_debug_options, _CRYPTO_get_mem_ex_functions, \n                       _CRYPTO_get_mem_functions, _CRYPTO_get_new_dynlockid, \n                       _CRYPTO_get_new_lockid, _CRYPTO_is_mem_check_on, \n                       _CRYPTO_lock, _CRYPTO_malloc, _CRYPTO_malloc_debug_init, \n                       _CRYPTO_malloc_locked, _CRYPTO_mem_ctrl, _CRYPTO_mem_leaks, \n                       _CRYPTO_mem_leaks_cb, _CRYPTO_mem_leaks_fp, _CRYPTO_memcmp, \n                       _CRYPTO_new_ex_data, _CRYPTO_num_locks, _CRYPTO_pop_info, \n                       _CRYPTO_push_info_, _CRYPTO_realloc, _CRYPTO_realloc_clean, \n                       _CRYPTO_remalloc, _CRYPTO_remove_all_info, _CRYPTO_set_add_lock_callback, \n                       _CRYPTO_set_dynlock_create_callback, _CRYPTO_set_dynlock_destroy_callback, \n                       _CRYPTO_set_dynlock_lock_callback, _CRYPTO_set_ex_data, \n                       _CRYPTO_set_ex_data_implementation, _CRYPTO_set_id_callback, \n                       _CRYPTO_set_locked_mem_ex_functions, _CRYPTO_set_locked_mem_functions, \n                       _CRYPTO_set_locking_callback, _CRYPTO_set_mem_debug_functions, \n                       _CRYPTO_set_mem_debug_options, _CRYPTO_set_mem_ex_functions, \n                       _CRYPTO_set_mem_functions, _CRYPTO_set_mem_info_functions, \n                       _CRYPTO_strdup, _CRYPTO_thread_id, _DES_SPtrans, \n                       _DES_cbc_cksum, _DES_cbc_encrypt, _DES_cfb64_encrypt, \n                       _DES_cfb_encrypt, _DES_check_key_parity, _DES_crypt, \n                       _DES_decrypt3, _DES_ecb3_encrypt, _DES_ecb_encrypt, \n                       _DES_ede3_cbc_encrypt, _DES_ede3_cbcm_encrypt, _DES_ede3_cfb64_encrypt, \n                       _DES_ede3_cfb_encrypt, _DES_ede3_ofb64_encrypt, \n                       _DES_enc_read, _DES_enc_write, _DES_encrypt1, _DES_encrypt2, \n                       _DES_encrypt3, _DES_fcrypt, _DES_is_weak_key, _DES_key_sched, \n                       _DES_ncbc_encrypt, _DES_ofb64_encrypt, _DES_ofb_encrypt, \n                       _DES_options, _DES_pcbc_encrypt, _DES_quad_cksum, \n                       _DES_random_key, _DES_read_2passwords, _DES_read_password, \n                       _DES_set_key, _DES_set_key_checked, _DES_set_key_unchecked, \n                       _DES_set_odd_parity, _DES_string_to_2keys, _DES_string_to_key, \n                       _DES_xcbc_encrypt, _DH_OpenSSL, _DH_check, _DH_check_pub_key, \n                       _DH_compute_key, _DH_free, _DH_generate_key, _DH_generate_parameters, \n                       _DH_generate_parameters_ex, _DH_get_default_method, \n                       _DH_get_ex_data, _DH_get_ex_new_index, _DH_new, \n                       _DH_new_method, _DH_set_default_method, _DH_set_ex_data, \n                       _DH_set_method, _DH_size, _DH_up_ref, _DH_version, \n                       _DHparams_it, _DHparams_print, _DHparams_print_fp, \n                       _DIRECTORYSTRING_free, _DIRECTORYSTRING_it, _DIRECTORYSTRING_new, \n                       _DISPLAYTEXT_free, _DISPLAYTEXT_it, _DISPLAYTEXT_new, \n                       _DIST_POINT_NAME_free, _DIST_POINT_NAME_it, _DIST_POINT_NAME_new, \n                       _DIST_POINT_free, _DIST_POINT_it, _DIST_POINT_new, \n                       _DSAPrivateKey_it, _DSAPublicKey_it, _DSA_OpenSSL, \n                       _DSA_SIG_free, _DSA_SIG_it, _DSA_SIG_new, _DSA_do_sign, \n                       _DSA_do_verify, _DSA_dup_DH, _DSA_free, _DSA_generate_key, \n                       _DSA_generate_parameters, _DSA_generate_parameters_ex, \n                       _DSA_get_default_method, _DSA_get_ex_data, _DSA_get_ex_new_index, \n                       _DSA_new, _DSA_new_method, _DSA_print, _DSA_print_fp, \n                       _DSA_set_default_method, _DSA_set_ex_data, _DSA_set_method, \n                       _DSA_sign, _DSA_sign_setup, _DSA_size, _DSA_up_ref, \n                       _DSA_verify, _DSA_version, _DSAparams_it, _DSAparams_print, \n                       _DSAparams_print_fp, _DSO_METHOD_dl, _DSO_METHOD_dlfcn, \n                       _DSO_METHOD_null, _DSO_METHOD_openssl, _DSO_METHOD_vms, \n                       _DSO_METHOD_win32, _DSO_bind_func, _DSO_bind_var, \n                       _DSO_convert_filename, _DSO_ctrl, _DSO_flags, _DSO_free, \n                       _DSO_get_default_method, _DSO_get_filename, _DSO_get_loaded_filename, \n                       _DSO_get_method, _DSO_load, _DSO_merge, _DSO_new, \n                       _DSO_new_method, _DSO_set_default_method, _DSO_set_filename, \n                       _DSO_set_method, _DSO_set_name_converter, _DSO_up_ref, \n                       _ECDH_OpenSSL, _ECDH_compute_key, _ECDH_get_default_method, \n                       _ECDH_get_ex_data, _ECDH_get_ex_new_index, _ECDH_set_default_method, \n                       _ECDH_set_ex_data, _ECDH_set_method, _ECDH_version, \n                       _ECDSA_OpenSSL, _ECDSA_SIG_free, _ECDSA_SIG_it, \n                       _ECDSA_SIG_new, _ECDSA_do_sign, _ECDSA_do_sign_ex, \n                       _ECDSA_do_verify, _ECDSA_get_default_method, _ECDSA_get_ex_data, \n                       _ECDSA_get_ex_new_index, _ECDSA_set_default_method, \n                       _ECDSA_set_ex_data, _ECDSA_set_method, _ECDSA_sign, \n                       _ECDSA_sign_ex, _ECDSA_sign_setup, _ECDSA_size, \n                       _ECDSA_verify, _ECDSA_version, _ECPARAMETERS_free, \n                       _ECPARAMETERS_it, _ECPARAMETERS_new, _ECPKPARAMETERS_free, \n                       _ECPKPARAMETERS_it, _ECPKPARAMETERS_new, _ECPKParameters_print, \n                       _ECPKParameters_print_fp, _ECParameters_print, _ECParameters_print_fp, \n                       _EC_EX_DATA_clear_free_all_data, _EC_EX_DATA_clear_free_data, \n                       _EC_EX_DATA_free_all_data, _EC_EX_DATA_free_data, \n                       _EC_EX_DATA_get_data, _EC_EX_DATA_set_data, _EC_GF2m_simple_method, \n                       _EC_GFp_mont_method, _EC_GFp_nist_method, _EC_GFp_simple_method, \n                       _EC_GROUP_check, _EC_GROUP_check_discriminant, _EC_GROUP_clear_free, \n                       _EC_GROUP_cmp, _EC_GROUP_copy, _EC_GROUP_dup, _EC_GROUP_free, \n                       _EC_GROUP_get0_generator, _EC_GROUP_get0_seed, _EC_GROUP_get_asn1_flag, \n                       _EC_GROUP_get_basis_type, _EC_GROUP_get_cofactor, \n                       _EC_GROUP_get_curve_GF2m, _EC_GROUP_get_curve_GFp, \n                       _EC_GROUP_get_curve_name, _EC_GROUP_get_degree, \n                       _EC_GROUP_get_order, _EC_GROUP_get_pentanomial_basis, \n                       _EC_GROUP_get_point_conversion_form, _EC_GROUP_get_seed_len, \n                       _EC_GROUP_get_trinomial_basis, _EC_GROUP_have_precompute_mult, \n                       _EC_GROUP_method_of, _EC_GROUP_new, _EC_GROUP_new_by_curve_name, \n                       _EC_GROUP_new_curve_GF2m, _EC_GROUP_new_curve_GFp, \n                       _EC_GROUP_precompute_mult, _EC_GROUP_set_asn1_flag, \n                       _EC_GROUP_set_curve_GF2m, _EC_GROUP_set_curve_GFp, \n                       _EC_GROUP_set_curve_name, _EC_GROUP_set_generator, \n                       _EC_GROUP_set_point_conversion_form, _EC_GROUP_set_seed, \n                       _EC_KEY_check_key, _EC_KEY_copy, _EC_KEY_dup, _EC_KEY_free, \n                       _EC_KEY_generate_key, _EC_KEY_get0_group, _EC_KEY_get0_private_key, \n                       _EC_KEY_get0_public_key, _EC_KEY_get_conv_form, \n                       _EC_KEY_get_enc_flags, _EC_KEY_get_key_method_data, \n                       _EC_KEY_insert_key_method_data, _EC_KEY_new, _EC_KEY_new_by_curve_name, \n                       _EC_KEY_precompute_mult, _EC_KEY_print, _EC_KEY_print_fp, \n                       _EC_KEY_set_asn1_flag, _EC_KEY_set_conv_form, _EC_KEY_set_enc_flags, \n                       _EC_KEY_set_group, _EC_KEY_set_private_key, _EC_KEY_set_public_key, \n                       _EC_KEY_up_ref, _EC_METHOD_get_field_type, _EC_POINT_add, \n                       _EC_POINT_bn2point, _EC_POINT_clear_free, _EC_POINT_cmp, \n                       _EC_POINT_copy, _EC_POINT_dbl, _EC_POINT_dup, _EC_POINT_free, \n                       _EC_POINT_get_Jprojective_coordinates_GFp, _EC_POINT_get_affine_coordinates_GF2m, \n                       _EC_POINT_get_affine_coordinates_GFp, _EC_POINT_hex2point, \n                       _EC_POINT_invert, _EC_POINT_is_at_infinity, _EC_POINT_is_on_curve, \n                       _EC_POINT_make_affine, _EC_POINT_method_of, _EC_POINT_mul, \n                       _EC_POINT_new, _EC_POINT_oct2point, _EC_POINT_point2bn, \n                       _EC_POINT_point2hex, _EC_POINT_point2oct, _EC_POINT_set_Jprojective_coordinates_GFp, \n                       _EC_POINT_set_affine_coordinates_GF2m, _EC_POINT_set_affine_coordinates_GFp, \n                       _EC_POINT_set_compressed_coordinates_GF2m, _EC_POINT_set_compressed_coordinates_GFp, \n                       _EC_POINT_set_to_infinity, _EC_POINTs_make_affine, \n                       _EC_POINTs_mul, _EC_PRIVATEKEY_free, _EC_PRIVATEKEY_it, \n                       _EC_PRIVATEKEY_new, _EC_get_builtin_curves, _EDIPARTYNAME_free, \n                       _EDIPARTYNAME_it, _EDIPARTYNAME_new, _ENGINE_add, \n                       _ENGINE_add_conf_module, _ENGINE_by_id, _ENGINE_cleanup, \n                       _ENGINE_cmd_is_executable, _ENGINE_ctrl, _ENGINE_ctrl_cmd, \n                       _ENGINE_ctrl_cmd_string, _ENGINE_finish, _ENGINE_free, \n                       _ENGINE_get_DH, _ENGINE_get_DSA, _ENGINE_get_ECDH, \n                       _ENGINE_get_ECDSA, _ENGINE_get_RAND, _ENGINE_get_RSA, \n                       _ENGINE_get_STORE, _ENGINE_get_cipher, _ENGINE_get_cipher_engine, \n                       _ENGINE_get_ciphers, _ENGINE_get_cmd_defns, _ENGINE_get_ctrl_function, \n                       _ENGINE_get_default_DH, _ENGINE_get_default_DSA, \n                       _ENGINE_get_default_ECDH, _ENGINE_get_default_ECDSA, \n                       _ENGINE_get_default_RAND, _ENGINE_get_default_RSA, \n                       _ENGINE_get_destroy_function, _ENGINE_get_digest, \n                       _ENGINE_get_digest_engine, _ENGINE_get_digests, \n                       _ENGINE_get_ex_data, _ENGINE_get_ex_new_index, _ENGINE_get_finish_function, \n                       _ENGINE_get_first, _ENGINE_get_flags, _ENGINE_get_id, \n                       _ENGINE_get_init_function, _ENGINE_get_last, _ENGINE_get_load_privkey_function, \n                       _ENGINE_get_load_pubkey_function, _ENGINE_get_name, \n                       _ENGINE_get_next, _ENGINE_get_prev, _ENGINE_get_ssl_client_cert_function, \n                       _ENGINE_get_static_state, _ENGINE_get_table_flags, \n                       _ENGINE_init, _ENGINE_load_builtin_engines, _ENGINE_load_cryptodev, \n                       _ENGINE_load_dynamic, _ENGINE_load_openssl, _ENGINE_load_private_key, \n                       _ENGINE_load_public_key, _ENGINE_load_ssl_client_cert, \n                       _ENGINE_new, _ENGINE_register_DH, _ENGINE_register_DSA, \n                       _ENGINE_register_ECDH, _ENGINE_register_ECDSA, _ENGINE_register_RAND, \n                       _ENGINE_register_RSA, _ENGINE_register_STORE, _ENGINE_register_all_DH, \n                       _ENGINE_register_all_DSA, _ENGINE_register_all_ECDH, \n                       _ENGINE_register_all_ECDSA, _ENGINE_register_all_RAND, \n                       _ENGINE_register_all_RSA, _ENGINE_register_all_STORE, \n                       _ENGINE_register_all_ciphers, _ENGINE_register_all_complete, \n                       _ENGINE_register_all_digests, _ENGINE_register_ciphers, \n                       _ENGINE_register_complete, _ENGINE_register_digests, \n                       _ENGINE_remove, _ENGINE_set_DH, _ENGINE_set_DSA, \n                       _ENGINE_set_ECDH, _ENGINE_set_ECDSA, _ENGINE_set_RAND, \n                       _ENGINE_set_RSA, _ENGINE_set_STORE, _ENGINE_set_ciphers, \n                       _ENGINE_set_cmd_defns, _ENGINE_set_ctrl_function, \n                       _ENGINE_set_default, _ENGINE_set_default_DH, _ENGINE_set_default_DSA, \n                       _ENGINE_set_default_ECDH, _ENGINE_set_default_ECDSA, \n                       _ENGINE_set_default_RAND, _ENGINE_set_default_RSA, \n                       _ENGINE_set_default_ciphers, _ENGINE_set_default_digests, \n                       _ENGINE_set_default_string, _ENGINE_set_destroy_function, \n                       _ENGINE_set_digests, _ENGINE_set_ex_data, _ENGINE_set_finish_function, \n                       _ENGINE_set_flags, _ENGINE_set_id, _ENGINE_set_init_function, \n                       _ENGINE_set_load_privkey_function, _ENGINE_set_load_pubkey_function, \n                       _ENGINE_set_load_ssl_client_cert_function, _ENGINE_set_name, \n                       _ENGINE_set_table_flags, _ENGINE_unregister_DH, \n                       _ENGINE_unregister_DSA, _ENGINE_unregister_ECDH, \n                       _ENGINE_unregister_ECDSA, _ENGINE_unregister_RAND, \n                       _ENGINE_unregister_RSA, _ENGINE_unregister_STORE, \n                       _ENGINE_unregister_ciphers, _ENGINE_unregister_digests, \n                       _ENGINE_up_ref, _ERR_add_error_data, _ERR_clear_error, \n                       _ERR_error_string, _ERR_error_string_n, _ERR_free_strings, \n                       _ERR_func_error_string, _ERR_get_err_state_table, \n                       _ERR_get_error, _ERR_get_error_line, _ERR_get_error_line_data, \n                       _ERR_get_implementation, _ERR_get_next_error_library, \n                       _ERR_get_state, _ERR_get_string_table, _ERR_lib_error_string, \n                       _ERR_load_ASN1_strings, _ERR_load_BIO_strings, _ERR_load_BN_strings, \n                       _ERR_load_BUF_strings, _ERR_load_COMP_strings, _ERR_load_CONF_strings, \n                       _ERR_load_CRYPTO_strings, _ERR_load_DH_strings, \n                       _ERR_load_DSA_strings, _ERR_load_DSO_strings, _ERR_load_ECDH_strings, \n                       _ERR_load_ECDSA_strings, _ERR_load_EC_strings, _ERR_load_ENGINE_strings, \n                       _ERR_load_ERR_strings, _ERR_load_EVP_strings, _ERR_load_OBJ_strings, \n                       _ERR_load_OCSP_strings, _ERR_load_PEM_strings, _ERR_load_PKCS12_strings, \n                       _ERR_load_PKCS7_strings, _ERR_load_RAND_strings, \n                       _ERR_load_RSA_strings, _ERR_load_STORE_strings, \n                       _ERR_load_UI_strings, _ERR_load_X509V3_strings, \n                       _ERR_load_X509_strings, _ERR_load_crypto_strings, \n                       _ERR_load_strings, _ERR_peek_error, _ERR_peek_error_line, \n                       _ERR_peek_error_line_data, _ERR_peek_last_error, \n                       _ERR_peek_last_error_line, _ERR_peek_last_error_line_data, \n                       _ERR_pop_to_mark, _ERR_print_errors, _ERR_print_errors_cb, \n                       _ERR_print_errors_fp, _ERR_put_error, _ERR_reason_error_string, \n                       _ERR_release_err_state_table, _ERR_remove_state, \n                       _ERR_set_error_data, _ERR_set_implementation, _ERR_set_mark, \n                       _ERR_unload_strings, _EVP_BytesToKey, _EVP_CIPHER_CTX_block_size, \n                       _EVP_CIPHER_CTX_cipher, _EVP_CIPHER_CTX_cleanup, \n                       _EVP_CIPHER_CTX_clear_flags, _EVP_CIPHER_CTX_ctrl, \n                       _EVP_CIPHER_CTX_flags, _EVP_CIPHER_CTX_free, _EVP_CIPHER_CTX_get_app_data, \n                       _EVP_CIPHER_CTX_init, _EVP_CIPHER_CTX_iv_length, \n                       _EVP_CIPHER_CTX_key_length, _EVP_CIPHER_CTX_new, \n                       _EVP_CIPHER_CTX_nid, _EVP_CIPHER_CTX_rand_key, _EVP_CIPHER_CTX_set_app_data, \n                       _EVP_CIPHER_CTX_set_flags, _EVP_CIPHER_CTX_set_key_length, \n                       _EVP_CIPHER_CTX_set_padding, _EVP_CIPHER_CTX_test_flags, \n                       _EVP_CIPHER_asn1_to_param, _EVP_CIPHER_block_size, \n                       _EVP_CIPHER_flags, _EVP_CIPHER_get_asn1_iv, _EVP_CIPHER_iv_length, \n                       _EVP_CIPHER_key_length, _EVP_CIPHER_nid, _EVP_CIPHER_param_to_asn1, \n                       _EVP_CIPHER_set_asn1_iv, _EVP_CIPHER_type, _EVP_Cipher, \n                       _EVP_CipherFinal, _EVP_CipherFinal_ex, _EVP_CipherInit, \n                       _EVP_CipherInit_ex, _EVP_CipherUpdate, _EVP_DecodeBlock, \n                       _EVP_DecodeFinal, _EVP_DecodeInit, _EVP_DecodeUpdate, \n                       _EVP_DecryptFinal, _EVP_DecryptFinal_ex, _EVP_DecryptInit, \n                       _EVP_DecryptInit_ex, _EVP_DecryptUpdate, _EVP_Digest, \n                       _EVP_DigestFinal, _EVP_DigestFinal_ex, _EVP_DigestInit, \n                       _EVP_DigestInit_ex, _EVP_DigestUpdate, _EVP_EncodeBlock, \n                       _EVP_EncodeFinal, _EVP_EncodeInit, _EVP_EncodeUpdate, \n                       _EVP_EncryptFinal, _EVP_EncryptFinal_ex, _EVP_EncryptInit, \n                       _EVP_EncryptInit_ex, _EVP_EncryptUpdate, _EVP_MD_CTX_cleanup, \n                       _EVP_MD_CTX_clear_flags, _EVP_MD_CTX_copy, _EVP_MD_CTX_copy_ex, \n                       _EVP_MD_CTX_create, _EVP_MD_CTX_destroy, _EVP_MD_CTX_init, \n                       _EVP_MD_CTX_md, _EVP_MD_CTX_set_flags, _EVP_MD_CTX_test_flags, \n                       _EVP_MD_block_size, _EVP_MD_pkey_type, _EVP_MD_size, \n                       _EVP_MD_type, _EVP_OpenFinal, _EVP_OpenInit, _EVP_PBE_CipherInit, \n                       _EVP_PBE_alg_add, _EVP_PBE_cleanup, _EVP_PKCS82PKEY, \n                       _EVP_PKEY2PKCS8, _EVP_PKEY2PKCS8_broken, _EVP_PKEY_add1_attr, \n                       _EVP_PKEY_add1_attr_by_NID, _EVP_PKEY_add1_attr_by_OBJ, \n                       _EVP_PKEY_add1_attr_by_txt, _EVP_PKEY_assign, _EVP_PKEY_bits, \n                       _EVP_PKEY_cmp, _EVP_PKEY_cmp_parameters, _EVP_PKEY_copy_parameters, \n                       _EVP_PKEY_decrypt, _EVP_PKEY_delete_attr, _EVP_PKEY_encrypt, \n                       _EVP_PKEY_free, _EVP_PKEY_get1_DH, _EVP_PKEY_get1_DSA, \n                       _EVP_PKEY_get1_EC_KEY, _EVP_PKEY_get1_RSA, _EVP_PKEY_get_attr, \n                       _EVP_PKEY_get_attr_by_NID, _EVP_PKEY_get_attr_by_OBJ, \n                       _EVP_PKEY_get_attr_count, _EVP_PKEY_missing_parameters, \n                       _EVP_PKEY_new, _EVP_PKEY_save_parameters, _EVP_PKEY_set1_DH, \n                       _EVP_PKEY_set1_DSA, _EVP_PKEY_set1_EC_KEY, _EVP_PKEY_set1_RSA, \n                       _EVP_PKEY_size, _EVP_PKEY_type, _EVP_SealFinal, \n                       _EVP_SealInit, _EVP_SignFinal, _EVP_VerifyFinal, \n                       _EVP_add_alg_module, _EVP_add_cipher, _EVP_add_digest, \n                       _EVP_aes_128_cbc, _EVP_aes_128_cfb, _EVP_aes_128_cfb1, \n                       _EVP_aes_128_cfb128, _EVP_aes_128_cfb8, _EVP_aes_128_ecb, \n                       _EVP_aes_128_ofb, _EVP_aes_192_cbc, _EVP_aes_192_cfb, \n                       _EVP_aes_192_cfb1, _EVP_aes_192_cfb128, _EVP_aes_192_cfb8, \n                       _EVP_aes_192_ecb, _EVP_aes_192_ofb, _EVP_aes_256_cbc, \n                       _EVP_aes_256_cfb, _EVP_aes_256_cfb1, _EVP_aes_256_cfb128, \n                       _EVP_aes_256_cfb8, _EVP_aes_256_ecb, _EVP_aes_256_ofb, \n                       _EVP_bf_cbc, _EVP_bf_cfb, _EVP_bf_cfb64, _EVP_bf_ecb, \n                       _EVP_bf_ofb, _EVP_cast5_cbc, _EVP_cast5_cfb, _EVP_cast5_cfb64, \n                       _EVP_cast5_ecb, _EVP_cast5_ofb, _EVP_cleanup, _EVP_des_cbc, \n                       _EVP_des_cfb, _EVP_des_cfb1, _EVP_des_cfb64, _EVP_des_cfb8, \n                       _EVP_des_ecb, _EVP_des_ede, _EVP_des_ede3, _EVP_des_ede3_cbc, \n                       _EVP_des_ede3_cfb, _EVP_des_ede3_cfb1, _EVP_des_ede3_cfb64, \n                       _EVP_des_ede3_cfb8, _EVP_des_ede3_ecb, _EVP_des_ede3_ofb, \n                       _EVP_des_ede_cbc, _EVP_des_ede_cfb, _EVP_des_ede_cfb64, \n                       _EVP_des_ede_ecb, _EVP_des_ede_ofb, _EVP_des_ofb, \n                       _EVP_desx_cbc, _EVP_dss, _EVP_dss1, _EVP_ecdsa, \n                       _EVP_enc_null, _EVP_get_cipherbyname, _EVP_get_digestbyname, \n                       _EVP_get_pw_prompt, _EVP_md2, _EVP_md4, _EVP_md5, \n                       _EVP_md_null, _EVP_mdc2, _EVP_rc2_40_cbc, _EVP_rc2_64_cbc, \n                       _EVP_rc2_cbc, _EVP_rc2_cfb, _EVP_rc2_cfb64, _EVP_rc2_ecb, \n                       _EVP_rc2_ofb, _EVP_rc4, _EVP_rc4_40, _EVP_read_pw_string, \n                       _EVP_ripemd160, _EVP_seed_cbc, _EVP_seed_cfb128, \n                       _EVP_seed_ecb, _EVP_seed_ofb, _EVP_set_pw_prompt, \n                       _EVP_sha, _EVP_sha1, _EVP_sha224, _EVP_sha256, _EVP_sha384, \n                       _EVP_sha512, _EVP_version, _EXTENDED_KEY_USAGE_free, \n                       _EXTENDED_KEY_USAGE_it, _EXTENDED_KEY_USAGE_new, \n                       _GENERAL_NAMES_free, _GENERAL_NAMES_it, _GENERAL_NAMES_new, \n                       _GENERAL_NAME_free, _GENERAL_NAME_it, _GENERAL_NAME_new, \n                       _GENERAL_NAME_print, _GENERAL_SUBTREE_free, _GENERAL_SUBTREE_it, \n                       _GENERAL_SUBTREE_new, _HMAC, _HMAC_CTX_cleanup, \n                       _HMAC_CTX_init, _HMAC_CTX_set_flags, _HMAC_Final, \n                       _HMAC_Init, _HMAC_Init_ex, _HMAC_Update, _KRB5_APREQBODY_free, \n                       _KRB5_APREQBODY_it, _KRB5_APREQBODY_new, _KRB5_APREQ_free, \n                       _KRB5_APREQ_it, _KRB5_APREQ_new, _KRB5_AUTHDATA_free, \n                       _KRB5_AUTHDATA_it, _KRB5_AUTHDATA_new, _KRB5_AUTHENTBODY_free, \n                       _KRB5_AUTHENTBODY_it, _KRB5_AUTHENTBODY_new, _KRB5_AUTHENT_free, \n                       _KRB5_AUTHENT_it, _KRB5_AUTHENT_new, _KRB5_CHECKSUM_free, \n                       _KRB5_CHECKSUM_it, _KRB5_CHECKSUM_new, _KRB5_ENCDATA_free, \n                       _KRB5_ENCDATA_it, _KRB5_ENCDATA_new, _KRB5_ENCKEY_free, \n                       _KRB5_ENCKEY_it, _KRB5_ENCKEY_new, _KRB5_PRINCNAME_free, \n                       _KRB5_PRINCNAME_it, _KRB5_PRINCNAME_new, _KRB5_TICKET_free, \n                       _KRB5_TICKET_it, _KRB5_TICKET_new, _KRB5_TKTBODY_free, \n                       _KRB5_TKTBODY_it, _KRB5_TKTBODY_new, _LONG_it, _MD2, \n                       _MD2_Final, _MD2_Init, _MD2_Update, _MD2_options, \n                       _MD2_version, _MD4, _MD4_Final, _MD4_Init, _MD4_Transform, \n                       _MD4_Update, _MD4_version, _MD5, _MD5_Final, _MD5_Init, \n                       _MD5_Transform, _MD5_Update, _MD5_version, _MDC2, \n                       _MDC2_Final, _MDC2_Init, _MDC2_Update, _MGF1, _NAME_CONSTRAINTS_free, \n                       _NAME_CONSTRAINTS_it, _NAME_CONSTRAINTS_new, _NCONF_WIN32, \n                       _NCONF_default, _NCONF_dump_bio, _NCONF_dump_fp, \n                       _NCONF_free, _NCONF_free_data, _NCONF_get_number_e, \n                       _NCONF_get_section, _NCONF_get_string, _NCONF_load, \n                       _NCONF_load_bio, _NCONF_load_fp, _NCONF_new, _NETSCAPE_CERT_SEQUENCE_free, \n                       _NETSCAPE_CERT_SEQUENCE_it, _NETSCAPE_CERT_SEQUENCE_new, \n                       _NETSCAPE_ENCRYPTED_PKEY_free, _NETSCAPE_ENCRYPTED_PKEY_it, \n                       _NETSCAPE_ENCRYPTED_PKEY_new, _NETSCAPE_PKEY_free, \n                       _NETSCAPE_PKEY_it, _NETSCAPE_PKEY_new, _NETSCAPE_SPKAC_free, \n                       _NETSCAPE_SPKAC_it, _NETSCAPE_SPKAC_new, _NETSCAPE_SPKI_b64_decode, \n                       _NETSCAPE_SPKI_b64_encode, _NETSCAPE_SPKI_free, \n                       _NETSCAPE_SPKI_get_pubkey, _NETSCAPE_SPKI_it, _NETSCAPE_SPKI_new, \n                       _NETSCAPE_SPKI_print, _NETSCAPE_SPKI_set_pubkey, \n                       _NETSCAPE_SPKI_sign, _NETSCAPE_SPKI_verify, _NOTICEREF_free, \n                       _NOTICEREF_it, _NOTICEREF_new, _OBJ_NAME_add, _OBJ_NAME_cleanup, \n                       _OBJ_NAME_do_all, _OBJ_NAME_do_all_sorted, _OBJ_NAME_get, \n                       _OBJ_NAME_init, _OBJ_NAME_new_index, _OBJ_NAME_remove, \n                       _OBJ_add_object, _OBJ_bsearch, _OBJ_bsearch_ex, \n                       _OBJ_cleanup, _OBJ_cmp, _OBJ_create, _OBJ_create_objects, \n                       _OBJ_dup, _OBJ_ln2nid, _OBJ_new_nid, _OBJ_nid2ln, \n                       _OBJ_nid2obj, _OBJ_nid2sn, _OBJ_obj2nid, _OBJ_obj2txt, \n                       _OBJ_sn2nid, _OBJ_txt2nid, _OBJ_txt2obj, _OCSP_BASICRESP_add1_ext_i2d, \n                       _OCSP_BASICRESP_add_ext, _OCSP_BASICRESP_delete_ext, \n                       _OCSP_BASICRESP_free, _OCSP_BASICRESP_get1_ext_d2i, \n                       _OCSP_BASICRESP_get_ext, _OCSP_BASICRESP_get_ext_by_NID, \n                       _OCSP_BASICRESP_get_ext_by_OBJ, _OCSP_BASICRESP_get_ext_by_critical, \n                       _OCSP_BASICRESP_get_ext_count, _OCSP_BASICRESP_it, \n                       _OCSP_BASICRESP_new, _OCSP_CERTID_free, _OCSP_CERTID_it, \n                       _OCSP_CERTID_new, _OCSP_CERTSTATUS_free, _OCSP_CERTSTATUS_it, \n                       _OCSP_CERTSTATUS_new, _OCSP_CRLID_free, _OCSP_CRLID_it, \n                       _OCSP_CRLID_new, _OCSP_ONEREQ_add1_ext_i2d, _OCSP_ONEREQ_add_ext, \n                       _OCSP_ONEREQ_delete_ext, _OCSP_ONEREQ_free, _OCSP_ONEREQ_get1_ext_d2i, \n                       _OCSP_ONEREQ_get_ext, _OCSP_ONEREQ_get_ext_by_NID, \n                       _OCSP_ONEREQ_get_ext_by_OBJ, _OCSP_ONEREQ_get_ext_by_critical, \n                       _OCSP_ONEREQ_get_ext_count, _OCSP_ONEREQ_it, _OCSP_ONEREQ_new, \n                       _OCSP_REQINFO_free, _OCSP_REQINFO_it, _OCSP_REQINFO_new, \n                       _OCSP_REQUEST_add1_ext_i2d, _OCSP_REQUEST_add_ext, \n                       _OCSP_REQUEST_delete_ext, _OCSP_REQUEST_free, _OCSP_REQUEST_get1_ext_d2i, \n                       _OCSP_REQUEST_get_ext, _OCSP_REQUEST_get_ext_by_NID, \n                       _OCSP_REQUEST_get_ext_by_OBJ, _OCSP_REQUEST_get_ext_by_critical, \n                       _OCSP_REQUEST_get_ext_count, _OCSP_REQUEST_it, _OCSP_REQUEST_new, \n                       _OCSP_REQUEST_print, _OCSP_REQ_CTX_free, _OCSP_RESPBYTES_free, \n                       _OCSP_RESPBYTES_it, _OCSP_RESPBYTES_new, _OCSP_RESPDATA_free, \n                       _OCSP_RESPDATA_it, _OCSP_RESPDATA_new, _OCSP_RESPID_free, \n                       _OCSP_RESPID_it, _OCSP_RESPID_new, _OCSP_RESPONSE_free, \n                       _OCSP_RESPONSE_it, _OCSP_RESPONSE_new, _OCSP_RESPONSE_print, \n                       _OCSP_REVOKEDINFO_free, _OCSP_REVOKEDINFO_it, _OCSP_REVOKEDINFO_new, \n                       _OCSP_SERVICELOC_free, _OCSP_SERVICELOC_it, _OCSP_SERVICELOC_new, \n                       _OCSP_SIGNATURE_free, _OCSP_SIGNATURE_it, _OCSP_SIGNATURE_new, \n                       _OCSP_SINGLERESP_add1_ext_i2d, _OCSP_SINGLERESP_add_ext, \n                       _OCSP_SINGLERESP_delete_ext, _OCSP_SINGLERESP_free, \n                       _OCSP_SINGLERESP_get1_ext_d2i, _OCSP_SINGLERESP_get_ext, \n                       _OCSP_SINGLERESP_get_ext_by_NID, _OCSP_SINGLERESP_get_ext_by_OBJ, \n                       _OCSP_SINGLERESP_get_ext_by_critical, _OCSP_SINGLERESP_get_ext_count, \n                       _OCSP_SINGLERESP_it, _OCSP_SINGLERESP_new, _OCSP_accept_responses_new, \n                       _OCSP_archive_cutoff_new, _OCSP_basic_add1_cert, \n                       _OCSP_basic_add1_nonce, _OCSP_basic_add1_status, \n                       _OCSP_basic_sign, _OCSP_basic_verify, _OCSP_cert_id_new, \n                       _OCSP_cert_status_str, _OCSP_cert_to_id, _OCSP_check_nonce, \n                       _OCSP_check_validity, _OCSP_copy_nonce, _OCSP_crlID_new, \n                       _OCSP_crl_reason_str, _OCSP_id_cmp, _OCSP_id_get0_info, \n                       _OCSP_id_issuer_cmp, _OCSP_onereq_get0_id, _OCSP_parse_url, \n                       _OCSP_request_add0_id, _OCSP_request_add1_cert, \n                       _OCSP_request_add1_nonce, _OCSP_request_is_signed, \n                       _OCSP_request_onereq_count, _OCSP_request_onereq_get0, \n                       _OCSP_request_set1_name, _OCSP_request_sign, _OCSP_request_verify, \n                       _OCSP_resp_count, _OCSP_resp_find, _OCSP_resp_find_status, \n                       _OCSP_resp_get0, _OCSP_response_create, _OCSP_response_get1_basic, \n                       _OCSP_response_status, _OCSP_response_status_str, \n                       _OCSP_sendreq_bio, _OCSP_sendreq_nbio, _OCSP_sendreq_new, \n                       _OCSP_single_get0_status, _OCSP_url_svcloc_new, \n                       _OPENSSL_DIR_end, _OPENSSL_DIR_read, _OPENSSL_NONPIC_relocated, \n                       _OPENSSL_add_all_algorithms_conf, _OPENSSL_add_all_algorithms_noconf, \n                       _OPENSSL_cleanse, _OPENSSL_config, _OPENSSL_cpuid_setup, \n                       _OPENSSL_gmtime, _OPENSSL_ia32cap_P, _OPENSSL_ia32cap_loc, \n                       _OPENSSL_init, _OPENSSL_isservice, _OPENSSL_issetugid, \n                       _OPENSSL_load_builtin_modules, _OPENSSL_memcmp, \n                       _OPENSSL_no_config, _OPENSSL_showfatal, _OPENSSL_stderr, \n                       _OPENSSL_strcasecmp, _OPENSSL_strncasecmp, _OSSL_DES_version, \n                       _OSSL_libdes_version, _OTHERNAME_free, _OTHERNAME_it, \n                       _OTHERNAME_new, _OpenSSLDie, _OpenSSL_add_all_ciphers, \n                       _OpenSSL_add_all_digests, _PBE2PARAM_free, _PBE2PARAM_it, \n                       _PBE2PARAM_new, _PBEPARAM_free, _PBEPARAM_it, _PBEPARAM_new, \n                       _PBKDF2PARAM_free, _PBKDF2PARAM_it, _PBKDF2PARAM_new, \n                       _PEM_ASN1_read, _PEM_ASN1_read_bio, _PEM_ASN1_write, \n                       _PEM_ASN1_write_bio, _PEM_SealFinal, _PEM_SealInit, \n                       _PEM_SealUpdate, _PEM_SignFinal, _PEM_SignInit, \n                       _PEM_SignUpdate, _PEM_X509_INFO_read, _PEM_X509_INFO_read_bio, \n                       _PEM_X509_INFO_write_bio, _PEM_bytes_read_bio, _PEM_def_callback, \n                       _PEM_dek_info, _PEM_do_header, _PEM_get_EVP_CIPHER_INFO, \n                       _PEM_proc_type, _PEM_read, _PEM_read_DHparams, _PEM_read_DSAPrivateKey, \n                       _PEM_read_DSA_PUBKEY, _PEM_read_DSAparams, _PEM_read_ECPKParameters, \n                       _PEM_read_ECPrivateKey, _PEM_read_EC_PUBKEY, _PEM_read_NETSCAPE_CERT_SEQUENCE, \n                       _PEM_read_PKCS7, _PEM_read_PKCS8, _PEM_read_PKCS8_PRIV_KEY_INFO, \n                       _PEM_read_PUBKEY, _PEM_read_PrivateKey, _PEM_read_RSAPrivateKey, \n                       _PEM_read_RSAPublicKey, _PEM_read_RSA_PUBKEY, _PEM_read_X509, \n                       _PEM_read_X509_AUX, _PEM_read_X509_CERT_PAIR, _PEM_read_X509_CRL, \n                       _PEM_read_X509_REQ, _PEM_read_bio, _PEM_read_bio_DHparams, \n                       _PEM_read_bio_DSAPrivateKey, _PEM_read_bio_DSA_PUBKEY, \n                       _PEM_read_bio_DSAparams, _PEM_read_bio_ECPKParameters, \n                       _PEM_read_bio_ECPrivateKey, _PEM_read_bio_EC_PUBKEY, \n                       _PEM_read_bio_NETSCAPE_CERT_SEQUENCE, _PEM_read_bio_PKCS7, \n                       _PEM_read_bio_PKCS8, _PEM_read_bio_PKCS8_PRIV_KEY_INFO, \n                       _PEM_read_bio_PUBKEY, _PEM_read_bio_PrivateKey, \n                       _PEM_read_bio_RSAPrivateKey, _PEM_read_bio_RSAPublicKey, \n                       _PEM_read_bio_RSA_PUBKEY, _PEM_read_bio_X509, _PEM_read_bio_X509_AUX, \n                       _PEM_read_bio_X509_CERT_PAIR, _PEM_read_bio_X509_CRL, \n                       _PEM_read_bio_X509_REQ, _PEM_version, _PEM_write, \n                       _PEM_write_DHparams, _PEM_write_DSAPrivateKey, _PEM_write_DSA_PUBKEY, \n                       _PEM_write_DSAparams, _PEM_write_ECPKParameters, \n                       _PEM_write_ECPrivateKey, _PEM_write_EC_PUBKEY, _PEM_write_NETSCAPE_CERT_SEQUENCE, \n                       _PEM_write_PKCS7, _PEM_write_PKCS8, _PEM_write_PKCS8PrivateKey, \n                       _PEM_write_PKCS8PrivateKey_nid, _PEM_write_PKCS8_PRIV_KEY_INFO, \n                       _PEM_write_PUBKEY, _PEM_write_PrivateKey, _PEM_write_RSAPrivateKey, \n                       _PEM_write_RSAPublicKey, _PEM_write_RSA_PUBKEY, \n                       _PEM_write_X509, _PEM_write_X509_AUX, _PEM_write_X509_CERT_PAIR, \n                       _PEM_write_X509_CRL, _PEM_write_X509_REQ, _PEM_write_X509_REQ_NEW, \n                       _PEM_write_bio, _PEM_write_bio_DHparams, _PEM_write_bio_DSAPrivateKey, \n                       _PEM_write_bio_DSA_PUBKEY, _PEM_write_bio_DSAparams, \n                       _PEM_write_bio_ECPKParameters, _PEM_write_bio_ECPrivateKey, \n                       _PEM_write_bio_EC_PUBKEY, _PEM_write_bio_NETSCAPE_CERT_SEQUENCE, \n                       _PEM_write_bio_PKCS7, _PEM_write_bio_PKCS8, _PEM_write_bio_PKCS8PrivateKey, \n                       _PEM_write_bio_PKCS8PrivateKey_nid, _PEM_write_bio_PKCS8_PRIV_KEY_INFO, \n                       _PEM_write_bio_PUBKEY, _PEM_write_bio_PrivateKey, \n                       _PEM_write_bio_RSAPrivateKey, _PEM_write_bio_RSAPublicKey, \n                       _PEM_write_bio_RSA_PUBKEY, _PEM_write_bio_X509, \n                       _PEM_write_bio_X509_AUX, _PEM_write_bio_X509_CERT_PAIR, \n                       _PEM_write_bio_X509_CRL, _PEM_write_bio_X509_REQ, \n                       _PEM_write_bio_X509_REQ_NEW, _PKCS12_AUTHSAFES_it, \n                       _PKCS12_BAGS_free, _PKCS12_BAGS_it, _PKCS12_BAGS_new, \n                       _PKCS12_MAC_DATA_free, _PKCS12_MAC_DATA_it, _PKCS12_MAC_DATA_new, \n                       _PKCS12_MAKE_KEYBAG, _PKCS12_MAKE_SHKEYBAG, _PKCS12_PBE_add, \n                       _PKCS12_PBE_keyivgen, _PKCS12_SAFEBAGS_it, _PKCS12_SAFEBAG_free, \n                       _PKCS12_SAFEBAG_it, _PKCS12_SAFEBAG_new, _PKCS12_add_CSPName_asc, \n                       _PKCS12_add_cert, _PKCS12_add_friendlyname_asc, \n                       _PKCS12_add_friendlyname_uni, _PKCS12_add_key, _PKCS12_add_localkeyid, \n                       _PKCS12_add_safe, _PKCS12_add_safes, _PKCS12_certbag2x509, \n                       _PKCS12_certbag2x509crl, _PKCS12_create, _PKCS12_decrypt_skey, \n                       _PKCS12_free, _PKCS12_gen_mac, _PKCS12_get_attr_gen, \n                       _PKCS12_get_friendlyname, _PKCS12_init, _PKCS12_it, \n                       _PKCS12_item_decrypt_d2i, _PKCS12_item_i2d_encrypt, \n                       _PKCS12_item_pack_safebag, _PKCS12_key_gen_asc, \n                       _PKCS12_key_gen_uni, _PKCS12_new, _PKCS12_newpass, \n                       _PKCS12_pack_authsafes, _PKCS12_pack_p7data, _PKCS12_pack_p7encdata, \n                       _PKCS12_parse, _PKCS12_pbe_crypt, _PKCS12_set_mac, \n                       _PKCS12_setup_mac, _PKCS12_unpack_authsafes, _PKCS12_unpack_p7data, \n                       _PKCS12_unpack_p7encdata, _PKCS12_verify_mac, _PKCS12_x5092certbag, \n                       _PKCS12_x509crl2certbag, _PKCS1_MGF1, _PKCS5_PBE_add, \n                       _PKCS5_PBE_keyivgen, _PKCS5_PBKDF2_HMAC_SHA1, _PKCS5_pbe2_set, \n                       _PKCS5_pbe_set, _PKCS5_v2_PBE_keyivgen, _PKCS7_ATTR_SIGN_it, \n                       _PKCS7_ATTR_VERIFY_it, _PKCS7_DIGEST_free, _PKCS7_DIGEST_it, \n                       _PKCS7_DIGEST_new, _PKCS7_ENCRYPT_free, _PKCS7_ENCRYPT_it, \n                       _PKCS7_ENCRYPT_new, _PKCS7_ENC_CONTENT_free, _PKCS7_ENC_CONTENT_it, \n                       _PKCS7_ENC_CONTENT_new, _PKCS7_ENVELOPE_free, _PKCS7_ENVELOPE_it, \n                       _PKCS7_ENVELOPE_new, _PKCS7_ISSUER_AND_SERIAL_digest, \n                       _PKCS7_ISSUER_AND_SERIAL_free, _PKCS7_ISSUER_AND_SERIAL_it, \n                       _PKCS7_ISSUER_AND_SERIAL_new, _PKCS7_RECIP_INFO_free, \n                       _PKCS7_RECIP_INFO_it, _PKCS7_RECIP_INFO_new, _PKCS7_RECIP_INFO_set, \n                       _PKCS7_SIGNED_free, _PKCS7_SIGNED_it, _PKCS7_SIGNED_new, \n                       _PKCS7_SIGNER_INFO_free, _PKCS7_SIGNER_INFO_it, \n                       _PKCS7_SIGNER_INFO_new, _PKCS7_SIGNER_INFO_set, \n                       _PKCS7_SIGN_ENVELOPE_free, _PKCS7_SIGN_ENVELOPE_it, \n                       _PKCS7_SIGN_ENVELOPE_new, _PKCS7_add_attrib_smimecap, \n                       _PKCS7_add_attribute, _PKCS7_add_certificate, _PKCS7_add_crl, \n                       _PKCS7_add_recipient, _PKCS7_add_recipient_info, \n                       _PKCS7_add_signature, _PKCS7_add_signed_attribute, \n                       _PKCS7_add_signer, _PKCS7_cert_from_signer_info, \n                       _PKCS7_content_new, _PKCS7_ctrl, _PKCS7_dataDecode, \n                       _PKCS7_dataFinal, _PKCS7_dataInit, _PKCS7_dataVerify, \n                       _PKCS7_decrypt, _PKCS7_digest_from_attributes, _PKCS7_dup, \n                       _PKCS7_encrypt, _PKCS7_free, _PKCS7_get0_signers, \n                       _PKCS7_get_attribute, _PKCS7_get_issuer_and_serial, \n                       _PKCS7_get_signed_attribute, _PKCS7_get_signer_info, \n                       _PKCS7_get_smimecap, _PKCS7_it, _PKCS7_new, _PKCS7_set0_type_other, \n                       _PKCS7_set_attributes, _PKCS7_set_cipher, _PKCS7_set_content, \n                       _PKCS7_set_digest, _PKCS7_set_signed_attributes, \n                       _PKCS7_set_type, _PKCS7_sign, _PKCS7_signatureVerify, \n                       _PKCS7_simple_smimecap, _PKCS7_verify, _PKCS8_PRIV_KEY_INFO_free, \n                       _PKCS8_PRIV_KEY_INFO_it, _PKCS8_PRIV_KEY_INFO_new, \n                       _PKCS8_add_keyusage, _PKCS8_decrypt, _PKCS8_encrypt, \n                       _PKCS8_set_broken, _PKEY_USAGE_PERIOD_free, _PKEY_USAGE_PERIOD_it, \n                       _PKEY_USAGE_PERIOD_new, _POLICYINFO_free, _POLICYINFO_it, \n                       _POLICYINFO_new, _POLICYQUALINFO_free, _POLICYQUALINFO_it, \n                       _POLICYQUALINFO_new, _POLICY_CONSTRAINTS_free, _POLICY_CONSTRAINTS_it, \n                       _POLICY_CONSTRAINTS_new, _POLICY_MAPPINGS_it, _POLICY_MAPPING_free, \n                       _POLICY_MAPPING_it, _POLICY_MAPPING_new, _PROXY_CERT_INFO_EXTENSION_free, \n                       _PROXY_CERT_INFO_EXTENSION_it, _PROXY_CERT_INFO_EXTENSION_new, \n                       _PROXY_POLICY_free, _PROXY_POLICY_it, _PROXY_POLICY_new, \n                       _RAND_SSLeay, _RAND_add, _RAND_bytes, _RAND_cleanup, \n                       _RAND_egd, _RAND_egd_bytes, _RAND_file_name, _RAND_get_rand_method, \n                       _RAND_load_file, _RAND_poll, _RAND_pseudo_bytes, \n                       _RAND_query_egd_bytes, _RAND_seed, _RAND_set_rand_engine, \n                       _RAND_set_rand_method, _RAND_status, _RAND_version, \n                       _RAND_write_file, _RC2_cbc_encrypt, _RC2_cfb64_encrypt, \n                       _RC2_decrypt, _RC2_ecb_encrypt, _RC2_encrypt, _RC2_ofb64_encrypt, \n                       _RC2_set_key, _RC2_version, _RC4, _RC4_options, \n                       _RC4_set_key, _RC4_version, _RIPEMD160, _RIPEMD160_Final, \n                       _RIPEMD160_Init, _RIPEMD160_Transform, _RIPEMD160_Update, \n                       _RMD160_version, _RSAPrivateKey_asn1_meth, _RSAPrivateKey_dup, \n                       _RSAPrivateKey_it, _RSAPublicKey_dup, _RSAPublicKey_it, \n                       _RSA_PKCS1_SSLeay, _RSA_X931_derive_ex, _RSA_X931_generate_key_ex, \n                       _RSA_X931_hash_id, _RSA_blinding_off, _RSA_blinding_on, \n                       _RSA_check_key, _RSA_flags, _RSA_free, _RSA_generate_key, \n                       _RSA_generate_key_ex, _RSA_get_default_method, _RSA_get_ex_data, \n                       _RSA_get_ex_new_index, _RSA_get_method, _RSA_memory_lock, \n                       _RSA_new, _RSA_new_method, _RSA_null_method, _RSA_padding_add_PKCS1_OAEP, \n                       _RSA_padding_add_PKCS1_PSS, _RSA_padding_add_PKCS1_type_1, \n                       _RSA_padding_add_PKCS1_type_2, _RSA_padding_add_SSLv23, \n                       _RSA_padding_add_X931, _RSA_padding_add_none, _RSA_padding_check_PKCS1_OAEP, \n                       _RSA_padding_check_PKCS1_type_1, _RSA_padding_check_PKCS1_type_2, \n                       _RSA_padding_check_SSLv23, _RSA_padding_check_X931, \n                       _RSA_padding_check_none, _RSA_print, _RSA_print_fp, \n                       _RSA_private_decrypt, _RSA_private_encrypt, _RSA_public_decrypt, \n                       _RSA_public_encrypt, _RSA_set_default_method, _RSA_set_ex_data, \n                       _RSA_set_method, _RSA_setup_blinding, _RSA_sign, \n                       _RSA_sign_ASN1_OCTET_STRING, _RSA_size, _RSA_up_ref, \n                       _RSA_verify, _RSA_verify_ASN1_OCTET_STRING, _RSA_verify_PKCS1_PSS, \n                       _RSA_version, _SEED_cbc_encrypt, _SEED_cfb128_encrypt, \n                       _SEED_decrypt, _SEED_ecb_encrypt, _SEED_encrypt, \n                       _SEED_ofb128_encrypt, _SEED_set_key, _SHA, _SHA1, \n                       _SHA1_Final, _SHA1_Init, _SHA1_Transform, _SHA1_Update, \n                       _SHA1_version, _SHA224, _SHA224_Final, _SHA224_Init, \n                       _SHA224_Update, _SHA256, _SHA256_Final, _SHA256_Init, \n                       _SHA256_Transform, _SHA256_Update, _SHA256_version, \n                       _SHA384, _SHA384_Final, _SHA384_Init, _SHA384_Update, \n                       _SHA512, _SHA512_Final, _SHA512_Init, _SHA512_Transform, \n                       _SHA512_Update, _SHA512_version, _SHA_Final, _SHA_Init, \n                       _SHA_Transform, _SHA_Update, _SHA_version, _SMIME_crlf_copy, \n                       _SMIME_read_ASN1, _SMIME_read_PKCS7, _SMIME_text, \n                       _SMIME_write_PKCS7, _SSLeay, _SSLeay_version, _STACK_version, \n                       _STORE_ATTR_INFO_compare, _STORE_ATTR_INFO_free, \n                       _STORE_ATTR_INFO_get0_cstr, _STORE_ATTR_INFO_get0_dn, \n                       _STORE_ATTR_INFO_get0_number, _STORE_ATTR_INFO_get0_sha1str, \n                       _STORE_ATTR_INFO_in, _STORE_ATTR_INFO_in_ex, _STORE_ATTR_INFO_in_range, \n                       _STORE_ATTR_INFO_modify_cstr, _STORE_ATTR_INFO_modify_dn, \n                       _STORE_ATTR_INFO_modify_number, _STORE_ATTR_INFO_modify_sha1str, \n                       _STORE_ATTR_INFO_new, _STORE_ATTR_INFO_set_cstr, \n                       _STORE_ATTR_INFO_set_dn, _STORE_ATTR_INFO_set_number, \n                       _STORE_ATTR_INFO_set_sha1str, _STORE_Memory, _STORE_OBJECT_free, \n                       _STORE_OBJECT_new, _STORE_attr_sizes, _STORE_create_method, \n                       _STORE_ctrl, _STORE_delete_arbitrary, _STORE_delete_certificate, \n                       _STORE_delete_crl, _STORE_delete_number, _STORE_delete_private_key, \n                       _STORE_delete_public_key, _STORE_destroy_method, \n                       _STORE_free, _STORE_generate_crl, _STORE_generate_key, \n                       _STORE_get_arbitrary, _STORE_get_certificate, _STORE_get_crl, \n                       _STORE_get_ex_data, _STORE_get_ex_new_index, _STORE_get_method, \n                       _STORE_get_number, _STORE_get_private_key, _STORE_get_public_key, \n                       _STORE_list_certificate_end, _STORE_list_certificate_endp, \n                       _STORE_list_certificate_next, _STORE_list_certificate_start, \n                       _STORE_list_crl_end, _STORE_list_crl_endp, _STORE_list_crl_next, \n                       _STORE_list_crl_start, _STORE_list_private_key_end, \n                       _STORE_list_private_key_endp, _STORE_list_private_key_next, \n                       _STORE_list_private_key_start, _STORE_list_public_key_end, \n                       _STORE_list_public_key_endp, _STORE_list_public_key_next, \n                       _STORE_list_public_key_start, _STORE_method_get_cleanup_function, \n                       _STORE_method_get_ctrl_function, _STORE_method_get_delete_function, \n                       _STORE_method_get_generate_function, _STORE_method_get_get_function, \n                       _STORE_method_get_initialise_function, _STORE_method_get_list_end_function, \n                       _STORE_method_get_list_next_function, _STORE_method_get_list_start_function, \n                       _STORE_method_get_lock_store_function, _STORE_method_get_modify_function, \n                       _STORE_method_get_revoke_function, _STORE_method_get_store_function, \n                       _STORE_method_get_unlock_store_function, _STORE_method_get_update_store_function, \n                       _STORE_method_set_cleanup_function, _STORE_method_set_ctrl_function, \n                       _STORE_method_set_delete_function, _STORE_method_set_generate_function, \n                       _STORE_method_set_get_function, _STORE_method_set_initialise_function, \n                       _STORE_method_set_list_end_function, _STORE_method_set_list_next_function, \n                       _STORE_method_set_list_start_function, _STORE_method_set_lock_store_function, \n                       _STORE_method_set_modify_function, _STORE_method_set_revoke_function, \n                       _STORE_method_set_store_function, _STORE_method_set_unlock_store_function, \n                       _STORE_method_set_update_store_function, _STORE_modify_arbitrary, \n                       _STORE_modify_certificate, _STORE_modify_crl, _STORE_modify_number, \n                       _STORE_modify_private_key, _STORE_modify_public_key, \n                       _STORE_new_engine, _STORE_new_method, _STORE_object_type_string, \n                       _STORE_param_sizes, _STORE_parse_attrs_end, _STORE_parse_attrs_endp, \n                       _STORE_parse_attrs_next, _STORE_parse_attrs_start, \n                       _STORE_revoke_certificate, _STORE_revoke_private_key, \n                       _STORE_revoke_public_key, _STORE_set_ex_data, _STORE_set_method, \n                       _STORE_store_arbitrary, _STORE_store_certificate, \n                       _STORE_store_crl, _STORE_store_number, _STORE_store_private_key, \n                       _STORE_store_public_key, _SXNETID_free, _SXNETID_it, \n                       _SXNETID_new, _SXNET_add_id_INTEGER, _SXNET_add_id_asc, \n                       _SXNET_add_id_ulong, _SXNET_free, _SXNET_get_id_INTEGER, \n                       _SXNET_get_id_asc, _SXNET_get_id_ulong, _SXNET_it, \n                       _SXNET_new, _TXT_DB_create_index, _TXT_DB_free, \n                       _TXT_DB_get_by_index, _TXT_DB_insert, _TXT_DB_read, \n                       _TXT_DB_version, _TXT_DB_write, _UI_OpenSSL, _UI_UTIL_read_pw, \n                       _UI_UTIL_read_pw_string, _UI_add_error_string, _UI_add_info_string, \n                       _UI_add_input_boolean, _UI_add_input_string, _UI_add_user_data, \n                       _UI_add_verify_string, _UI_construct_prompt, _UI_create_method, \n                       _UI_ctrl, _UI_destroy_method, _UI_dup_error_string, \n                       _UI_dup_info_string, _UI_dup_input_boolean, _UI_dup_input_string, \n                       _UI_dup_verify_string, _UI_free, _UI_get0_action_string, \n                       _UI_get0_output_string, _UI_get0_result, _UI_get0_result_string, \n                       _UI_get0_test_string, _UI_get0_user_data, _UI_get_default_method, \n                       _UI_get_ex_data, _UI_get_ex_new_index, _UI_get_input_flags, \n                       _UI_get_method, _UI_get_result_maxsize, _UI_get_result_minsize, \n                       _UI_get_string_type, _UI_method_get_closer, _UI_method_get_flusher, \n                       _UI_method_get_opener, _UI_method_get_reader, _UI_method_get_writer, \n                       _UI_method_set_closer, _UI_method_set_flusher, _UI_method_set_opener, \n                       _UI_method_set_reader, _UI_method_set_writer, _UI_new, \n                       _UI_new_method, _UI_process, _UI_set_default_method, \n                       _UI_set_ex_data, _UI_set_method, _UI_set_result, \n                       _USERNOTICE_free, _USERNOTICE_it, _USERNOTICE_new, \n                       _UTF8_getc, _UTF8_putc, _X509V3_EXT_CRL_add_conf, \n                       _X509V3_EXT_CRL_add_nconf, _X509V3_EXT_REQ_add_conf, \n                       _X509V3_EXT_REQ_add_nconf, _X509V3_EXT_add, _X509V3_EXT_add_alias, \n                       _X509V3_EXT_add_conf, _X509V3_EXT_add_list, _X509V3_EXT_add_nconf, \n                       _X509V3_EXT_add_nconf_sk, _X509V3_EXT_cleanup, _X509V3_EXT_conf, \n                       _X509V3_EXT_conf_nid, _X509V3_EXT_d2i, _X509V3_EXT_get, \n                       _X509V3_EXT_get_nid, _X509V3_EXT_i2d, _X509V3_EXT_nconf, \n                       _X509V3_EXT_nconf_nid, _X509V3_EXT_print, _X509V3_EXT_print_fp, \n                       _X509V3_EXT_val_prn, _X509V3_NAME_from_section, \n                       _X509V3_add1_i2d, _X509V3_add_standard_extensions, \n                       _X509V3_add_value, _X509V3_add_value_bool, _X509V3_add_value_bool_nf, \n                       _X509V3_add_value_int, _X509V3_add_value_uchar, \n                       _X509V3_conf_free, _X509V3_extensions_print, _X509V3_get_d2i, \n                       _X509V3_get_section, _X509V3_get_string, _X509V3_get_value_bool, \n                       _X509V3_get_value_int, _X509V3_parse_list, _X509V3_section_free, \n                       _X509V3_set_conf_lhash, _X509V3_set_ctx, _X509V3_set_nconf, \n                       _X509V3_string_free, _X509_ALGORS_it, _X509_ALGOR_cmp, \n                       _X509_ALGOR_dup, _X509_ALGOR_free, _X509_ALGOR_get0, \n                       _X509_ALGOR_it, _X509_ALGOR_new, _X509_ALGOR_set0, \n                       _X509_ATTRIBUTE_SET_it, _X509_ATTRIBUTE_count, _X509_ATTRIBUTE_create, \n                       _X509_ATTRIBUTE_create_by_NID, _X509_ATTRIBUTE_create_by_OBJ, \n                       _X509_ATTRIBUTE_create_by_txt, _X509_ATTRIBUTE_dup, \n                       _X509_ATTRIBUTE_free, _X509_ATTRIBUTE_get0_data, \n                       _X509_ATTRIBUTE_get0_object, _X509_ATTRIBUTE_get0_type, \n                       _X509_ATTRIBUTE_it, _X509_ATTRIBUTE_new, _X509_ATTRIBUTE_set1_data, \n                       _X509_ATTRIBUTE_set1_object, _X509_CERT_AUX_free, \n                       _X509_CERT_AUX_it, _X509_CERT_AUX_new, _X509_CERT_AUX_print, \n                       _X509_CERT_PAIR_free, _X509_CERT_PAIR_it, _X509_CERT_PAIR_new, \n                       _X509_CINF_free, _X509_CINF_it, _X509_CINF_new, \n                       _X509_CRL_INFO_free, _X509_CRL_INFO_it, _X509_CRL_INFO_new, \n                       _X509_CRL_add0_revoked, _X509_CRL_add1_ext_i2d, \n                       _X509_CRL_add_ext, _X509_CRL_cmp, _X509_CRL_delete_ext, \n                       _X509_CRL_digest, _X509_CRL_dup, _X509_CRL_free, \n                       _X509_CRL_get_ext, _X509_CRL_get_ext_by_NID, _X509_CRL_get_ext_by_OBJ, \n                       _X509_CRL_get_ext_by_critical, _X509_CRL_get_ext_count, \n                       _X509_CRL_get_ext_d2i, _X509_CRL_it, _X509_CRL_new, \n                       _X509_CRL_print, _X509_CRL_print_fp, _X509_CRL_set_issuer_name, \n                       _X509_CRL_set_lastUpdate, _X509_CRL_set_nextUpdate, \n                       _X509_CRL_set_version, _X509_CRL_sign, _X509_CRL_sort, \n                       _X509_CRL_verify, _X509_EXTENSIONS_it, _X509_EXTENSION_create_by_NID, \n                       _X509_EXTENSION_create_by_OBJ, _X509_EXTENSION_dup, \n                       _X509_EXTENSION_free, _X509_EXTENSION_get_critical, \n                       _X509_EXTENSION_get_data, _X509_EXTENSION_get_object, \n                       _X509_EXTENSION_it, _X509_EXTENSION_new, _X509_EXTENSION_set_critical, \n                       _X509_EXTENSION_set_data, _X509_EXTENSION_set_object, \n                       _X509_INFO_free, _X509_INFO_new, _X509_LOOKUP_by_alias, \n                       _X509_LOOKUP_by_fingerprint, _X509_LOOKUP_by_issuer_serial, \n                       _X509_LOOKUP_by_subject, _X509_LOOKUP_ctrl, _X509_LOOKUP_file, \n                       _X509_LOOKUP_free, _X509_LOOKUP_hash_dir, _X509_LOOKUP_init, \n                       _X509_LOOKUP_new, _X509_LOOKUP_shutdown, _X509_NAME_ENTRIES_it, \n                       _X509_NAME_ENTRY_create_by_NID, _X509_NAME_ENTRY_create_by_OBJ, \n                       _X509_NAME_ENTRY_create_by_txt, _X509_NAME_ENTRY_dup, \n                       _X509_NAME_ENTRY_free, _X509_NAME_ENTRY_get_data, \n                       _X509_NAME_ENTRY_get_object, _X509_NAME_ENTRY_it, \n                       _X509_NAME_ENTRY_new, _X509_NAME_ENTRY_set_data, \n                       _X509_NAME_ENTRY_set_object, _X509_NAME_INTERNAL_it, \n                       _X509_NAME_add_entry, _X509_NAME_add_entry_by_NID, \n                       _X509_NAME_add_entry_by_OBJ, _X509_NAME_add_entry_by_txt, \n                       _X509_NAME_cmp, _X509_NAME_delete_entry, _X509_NAME_digest, \n                       _X509_NAME_dup, _X509_NAME_entry_count, _X509_NAME_free, \n                       _X509_NAME_get_entry, _X509_NAME_get_index_by_NID, \n                       _X509_NAME_get_index_by_OBJ, _X509_NAME_get_text_by_NID, \n                       _X509_NAME_get_text_by_OBJ, _X509_NAME_hash, _X509_NAME_it, \n                       _X509_NAME_new, _X509_NAME_oneline, _X509_NAME_print, \n                       _X509_NAME_print_ex, _X509_NAME_print_ex_fp, _X509_NAME_set, \n                       _X509_OBJECT_free_contents, _X509_OBJECT_idx_by_subject, \n                       _X509_OBJECT_retrieve_by_subject, _X509_OBJECT_retrieve_match, \n                       _X509_OBJECT_up_ref_count, _X509_PKEY_free, _X509_PKEY_new, \n                       _X509_POLICY_NODE_print, _X509_PUBKEY_free, _X509_PUBKEY_get, \n                       _X509_PUBKEY_it, _X509_PUBKEY_new, _X509_PUBKEY_set, \n                       _X509_PURPOSE_add, _X509_PURPOSE_cleanup, _X509_PURPOSE_get0, \n                       _X509_PURPOSE_get0_name, _X509_PURPOSE_get0_sname, \n                       _X509_PURPOSE_get_by_id, _X509_PURPOSE_get_by_sname, \n                       _X509_PURPOSE_get_count, _X509_PURPOSE_get_id, _X509_PURPOSE_get_trust, \n                       _X509_PURPOSE_set, _X509_REQ_INFO_free, _X509_REQ_INFO_it, \n                       _X509_REQ_INFO_new, _X509_REQ_add1_attr, _X509_REQ_add1_attr_by_NID, \n                       _X509_REQ_add1_attr_by_OBJ, _X509_REQ_add1_attr_by_txt, \n                       _X509_REQ_add_extensions, _X509_REQ_add_extensions_nid, \n                       _X509_REQ_check_private_key, _X509_REQ_delete_attr, \n                       _X509_REQ_digest, _X509_REQ_dup, _X509_REQ_extension_nid, \n                       _X509_REQ_free, _X509_REQ_get1_email, _X509_REQ_get_attr, \n                       _X509_REQ_get_attr_by_NID, _X509_REQ_get_attr_by_OBJ, \n                       _X509_REQ_get_attr_count, _X509_REQ_get_extension_nids, \n                       _X509_REQ_get_extensions, _X509_REQ_get_pubkey, \n                       _X509_REQ_it, _X509_REQ_new, _X509_REQ_print, _X509_REQ_print_ex, \n                       _X509_REQ_print_fp, _X509_REQ_set_extension_nids, \n                       _X509_REQ_set_pubkey, _X509_REQ_set_subject_name, \n                       _X509_REQ_set_version, _X509_REQ_sign, _X509_REQ_to_X509, \n                       _X509_REQ_verify, _X509_REVOKED_add1_ext_i2d, _X509_REVOKED_add_ext, \n                       _X509_REVOKED_delete_ext, _X509_REVOKED_free, _X509_REVOKED_get_ext, \n                       _X509_REVOKED_get_ext_by_NID, _X509_REVOKED_get_ext_by_OBJ, \n                       _X509_REVOKED_get_ext_by_critical, _X509_REVOKED_get_ext_count, \n                       _X509_REVOKED_get_ext_d2i, _X509_REVOKED_it, _X509_REVOKED_new, \n                       _X509_REVOKED_set_revocationDate, _X509_REVOKED_set_serialNumber, \n                       _X509_SIG_free, _X509_SIG_it, _X509_SIG_new, _X509_STORE_CTX_cleanup, \n                       _X509_STORE_CTX_free, _X509_STORE_CTX_get0_param, \n                       _X509_STORE_CTX_get0_policy_tree, _X509_STORE_CTX_get1_chain, \n                       _X509_STORE_CTX_get1_issuer, _X509_STORE_CTX_get_chain, \n                       _X509_STORE_CTX_get_current_cert, _X509_STORE_CTX_get_error, \n                       _X509_STORE_CTX_get_error_depth, _X509_STORE_CTX_get_ex_data, \n                       _X509_STORE_CTX_get_ex_new_index, _X509_STORE_CTX_get_explicit_policy, \n                       _X509_STORE_CTX_init, _X509_STORE_CTX_new, _X509_STORE_CTX_purpose_inherit, \n                       _X509_STORE_CTX_set0_crls, _X509_STORE_CTX_set0_param, \n                       _X509_STORE_CTX_set_cert, _X509_STORE_CTX_set_chain, \n                       _X509_STORE_CTX_set_default, _X509_STORE_CTX_set_depth, \n                       _X509_STORE_CTX_set_error, _X509_STORE_CTX_set_ex_data, \n                       _X509_STORE_CTX_set_flags, _X509_STORE_CTX_set_purpose, \n                       _X509_STORE_CTX_set_time, _X509_STORE_CTX_set_trust, \n                       _X509_STORE_CTX_set_verify_cb, _X509_STORE_CTX_trusted_stack, \n                       _X509_STORE_add_cert, _X509_STORE_add_crl, _X509_STORE_add_lookup, \n                       _X509_STORE_free, _X509_STORE_get_by_subject, _X509_STORE_load_locations, \n                       _X509_STORE_new, _X509_STORE_set1_param, _X509_STORE_set_default_paths, \n                       _X509_STORE_set_depth, _X509_STORE_set_flags, _X509_STORE_set_purpose, \n                       _X509_STORE_set_trust, _X509_TEA_is_enabled, _X509_TEA_set_state, \n                       _X509_TRUST_add, _X509_TRUST_cleanup, _X509_TRUST_get0, \n                       _X509_TRUST_get0_name, _X509_TRUST_get_by_id, _X509_TRUST_get_count, \n                       _X509_TRUST_get_flags, _X509_TRUST_get_trust, _X509_TRUST_set, \n                       _X509_TRUST_set_default, _X509_VAL_free, _X509_VAL_it, \n                       _X509_VAL_new, _X509_VERIFY_PARAM_add0_policy, _X509_VERIFY_PARAM_add0_table, \n                       _X509_VERIFY_PARAM_clear_flags, _X509_VERIFY_PARAM_free, \n                       _X509_VERIFY_PARAM_get_depth, _X509_VERIFY_PARAM_get_flags, \n                       _X509_VERIFY_PARAM_inherit, _X509_VERIFY_PARAM_lookup, \n                       _X509_VERIFY_PARAM_new, _X509_VERIFY_PARAM_set1, \n                       _X509_VERIFY_PARAM_set1_name, _X509_VERIFY_PARAM_set1_policies, \n                       _X509_VERIFY_PARAM_set_depth, _X509_VERIFY_PARAM_set_flags, \n                       _X509_VERIFY_PARAM_set_purpose, _X509_VERIFY_PARAM_set_time, \n                       _X509_VERIFY_PARAM_set_trust, _X509_VERIFY_PARAM_table_cleanup, \n                       _X509_add1_ext_i2d, _X509_add1_reject_object, _X509_add1_trust_object, \n                       _X509_add_ext, _X509_alias_get0, _X509_alias_set1, \n                       _X509_asn1_meth, _X509_certificate_type, _X509_check_ca, \n                       _X509_check_issued, _X509_check_private_key, _X509_check_purpose, \n                       _X509_check_trust, _X509_cmp, _X509_cmp_current_time, \n                       _X509_cmp_time, _X509_delete_ext, _X509_digest, \n                       _X509_dup, _X509_email_free, _X509_find_by_issuer_and_serial, \n                       _X509_find_by_subject, _X509_free, _X509_get0_pubkey_bitstr, \n                       _X509_get1_email, _X509_get1_ocsp, _X509_get_default_cert_area, \n                       _X509_get_default_cert_dir, _X509_get_default_cert_dir_env, \n                       _X509_get_default_cert_file, _X509_get_default_cert_file_env, \n                       _X509_get_default_private_dir, _X509_get_ex_data, \n                       _X509_get_ex_new_index, _X509_get_ext, _X509_get_ext_by_NID, \n                       _X509_get_ext_by_OBJ, _X509_get_ext_by_critical, \n                       _X509_get_ext_count, _X509_get_ext_d2i, _X509_get_issuer_name, \n                       _X509_get_pubkey, _X509_get_pubkey_parameters, _X509_get_serialNumber, \n                       _X509_get_subject_name, _X509_gmtime_adj, _X509_issuer_and_serial_cmp, \n                       _X509_issuer_and_serial_hash, _X509_issuer_name_cmp, \n                       _X509_issuer_name_hash, _X509_it, _X509_keyid_get0, \n                       _X509_keyid_set1, _X509_load_cert_crl_file, _X509_load_cert_file, \n                       _X509_load_crl_file, _X509_new, _X509_ocspid_print, \n                       _X509_policy_check, _X509_policy_level_get0_node, \n                       _X509_policy_level_node_count, _X509_policy_node_get0_parent, \n                       _X509_policy_node_get0_policy, _X509_policy_node_get0_qualifiers, \n                       _X509_policy_tree_free, _X509_policy_tree_get0_level, \n                       _X509_policy_tree_get0_policies, _X509_policy_tree_get0_user_policies, \n                       _X509_policy_tree_level_count, _X509_print, _X509_print_ex, \n                       _X509_print_ex_fp, _X509_print_fp, _X509_pubkey_digest, \n                       _X509_reject_clear, _X509_set_ex_data, _X509_set_issuer_name, \n                       _X509_set_notAfter, _X509_set_notBefore, _X509_set_pubkey, \n                       _X509_set_serialNumber, _X509_set_subject_name, \n                       _X509_set_version, _X509_sign, _X509_signature_print, \n                       _X509_subject_name_cmp, _X509_subject_name_hash, \n                       _X509_supported_extension, _X509_time_adj, _X509_to_X509_REQ, \n                       _X509_trust_clear, _X509_verify, _X509_verify_cert, \n                       _X509_verify_cert_error_string, _X509_verify_cert_orig, \n                       _X509_version, _X509at_add1_attr, _X509at_add1_attr_by_NID, \n                       _X509at_add1_attr_by_OBJ, _X509at_add1_attr_by_txt, \n                       _X509at_delete_attr, _X509at_get0_data_by_OBJ, _X509at_get_attr, \n                       _X509at_get_attr_by_NID, _X509at_get_attr_by_OBJ, \n                       _X509at_get_attr_count, _X509v3_add_ext, _X509v3_delete_ext, \n                       _X509v3_get_ext, _X509v3_get_ext_by_NID, _X509v3_get_ext_by_OBJ, \n                       _X509v3_get_ext_by_critical, _X509v3_get_ext_count, \n                       _X9_62_CHARACTERISTIC_TWO_free, _X9_62_CHARACTERISTIC_TWO_it, \n                       _X9_62_CHARACTERISTIC_TWO_new, _X9_62_CURVE_it, \n                       _X9_62_FIELDID_it, _X9_62_PENTANOMIAL_free, _X9_62_PENTANOMIAL_it, \n                       _X9_62_PENTANOMIAL_new, _ZLONG_it, __CONF_add_string, \n                       __CONF_free_data, __CONF_get_section, __CONF_get_section_values, \n                       __CONF_get_string, __CONF_new_data, __CONF_new_section, \n                       __des_crypt, __ossl_096_des_random_seed, __ossl_old_crypt, \n                       __ossl_old_des_cbc_cksum, __ossl_old_des_cbc_encrypt, \n                       __ossl_old_des_cfb64_encrypt, __ossl_old_des_cfb_encrypt, \n                       __ossl_old_des_crypt, __ossl_old_des_decrypt3, __ossl_old_des_ecb3_encrypt, \n                       __ossl_old_des_ecb_encrypt, __ossl_old_des_ede3_cbc_encrypt, \n                       __ossl_old_des_ede3_cfb64_encrypt, __ossl_old_des_ede3_ofb64_encrypt, \n                       __ossl_old_des_enc_read, __ossl_old_des_enc_write, \n                       __ossl_old_des_encrypt, __ossl_old_des_encrypt2, \n                       __ossl_old_des_encrypt3, __ossl_old_des_fcrypt, \n                       __ossl_old_des_is_weak_key, __ossl_old_des_key_sched, \n                       __ossl_old_des_ncbc_encrypt, __ossl_old_des_ofb64_encrypt, \n                       __ossl_old_des_ofb_encrypt, __ossl_old_des_options, \n                       __ossl_old_des_pcbc_encrypt, __ossl_old_des_quad_cksum, \n                       __ossl_old_des_random_key, __ossl_old_des_random_seed, \n                       __ossl_old_des_read_2passwords, __ossl_old_des_read_password, \n                       __ossl_old_des_read_pw, __ossl_old_des_read_pw_string, \n                       __ossl_old_des_set_key, __ossl_old_des_set_odd_parity, \n                       __ossl_old_des_string_to_2keys, __ossl_old_des_string_to_key, \n                       __ossl_old_des_xcbc_encrypt, __shadow_DES_check_key, \n                       __shadow_DES_rw_mode, _a2d_ASN1_OBJECT, _a2i_ASN1_ENUMERATED, \n                       _a2i_ASN1_INTEGER, _a2i_ASN1_STRING, _a2i_IPADDRESS, \n                       _a2i_IPADDRESS_NC, _a2i_ipadd, _asc2uni, _asn1_Finish, \n                       _asn1_GetSequence, _asn1_add_error, _asn1_const_Finish, \n                       _asn1_do_adb, _asn1_do_lock, _asn1_enc_free, _asn1_enc_init, \n                       _asn1_enc_restore, _asn1_enc_save, _asn1_ex_c2i, \n                       _asn1_ex_i2c, _asn1_get_choice_selector, _asn1_get_field_ptr, \n                       _asn1_primitive_clear, _asn1_set_choice_selector, \n                       _bn_add_part_words, _bn_add_words, _bn_cmp_part_words, \n                       _bn_cmp_words, _bn_div_words, _bn_dup_expand, _bn_expand2, \n                       _bn_mul_add_words, _bn_mul_comba4, _bn_mul_comba8, \n                       _bn_mul_high, _bn_mul_low_normal, _bn_mul_low_recursive, \n                       _bn_mul_normal, _bn_mul_part_recursive, _bn_mul_recursive, \n                       _bn_mul_words, _bn_sqr_comba4, _bn_sqr_comba8, _bn_sqr_normal, \n                       _bn_sqr_recursive, _bn_sqr_words, _bn_sub_part_words, \n                       _bn_sub_words, _c2i_ASN1_BIT_STRING, _c2i_ASN1_INTEGER, \n                       _c2i_ASN1_OBJECT, _cleanse_ctr, _d2i_ACCESS_DESCRIPTION, \n                       _d2i_ASN1_BIT_STRING, _d2i_ASN1_BMPSTRING, _d2i_ASN1_BOOLEAN, \n                       _d2i_ASN1_ENUMERATED, _d2i_ASN1_GENERALIZEDTIME, \n                       _d2i_ASN1_GENERALSTRING, _d2i_ASN1_HEADER, _d2i_ASN1_IA5STRING, \n                       _d2i_ASN1_INTEGER, _d2i_ASN1_NULL, _d2i_ASN1_OBJECT, \n                       _d2i_ASN1_OCTET_STRING, _d2i_ASN1_PRINTABLE, _d2i_ASN1_PRINTABLESTRING, \n                       _d2i_ASN1_SET, _d2i_ASN1_T61STRING, _d2i_ASN1_TIME, \n                       _d2i_ASN1_TYPE, _d2i_ASN1_UINTEGER, _d2i_ASN1_UNIVERSALSTRING, \n                       _d2i_ASN1_UTCTIME, _d2i_ASN1_UTF8STRING, _d2i_ASN1_VISIBLESTRING, \n                       _d2i_ASN1_bytes, _d2i_ASN1_type_bytes, _d2i_AUTHORITY_INFO_ACCESS, \n                       _d2i_AUTHORITY_KEYID, _d2i_AutoPrivateKey, _d2i_BASIC_CONSTRAINTS, \n                       _d2i_CERTIFICATEPOLICIES, _d2i_CRL_DIST_POINTS, \n                       _d2i_DHparams, _d2i_DIRECTORYSTRING, _d2i_DISPLAYTEXT, \n                       _d2i_DIST_POINT, _d2i_DIST_POINT_NAME, _d2i_DSAPrivateKey, \n                       _d2i_DSAPrivateKey_bio, _d2i_DSAPrivateKey_fp, _d2i_DSAPublicKey, \n                       _d2i_DSA_PUBKEY, _d2i_DSA_PUBKEY_bio, _d2i_DSA_PUBKEY_fp, \n                       _d2i_DSA_SIG, _d2i_DSAparams, _d2i_ECDSA_SIG, _d2i_ECPKPARAMETERS, \n                       _d2i_ECPKParameters, _d2i_ECParameters, _d2i_ECPrivateKey, \n                       _d2i_ECPrivateKey_bio, _d2i_ECPrivateKey_fp, _d2i_EC_PRIVATEKEY, \n                       _d2i_EC_PUBKEY, _d2i_EC_PUBKEY_bio, _d2i_EC_PUBKEY_fp, \n                       _d2i_EDIPARTYNAME, _d2i_EXTENDED_KEY_USAGE, _d2i_GENERAL_NAME, \n                       _d2i_GENERAL_NAMES, _d2i_KRB5_APREQ, _d2i_KRB5_APREQBODY, \n                       _d2i_KRB5_AUTHDATA, _d2i_KRB5_AUTHENT, _d2i_KRB5_AUTHENTBODY, \n                       _d2i_KRB5_CHECKSUM, _d2i_KRB5_ENCDATA, _d2i_KRB5_ENCKEY, \n                       _d2i_KRB5_PRINCNAME, _d2i_KRB5_TICKET, _d2i_KRB5_TKTBODY, \n                       _d2i_NETSCAPE_CERT_SEQUENCE, _d2i_NETSCAPE_ENCRYPTED_PKEY, \n                       _d2i_NETSCAPE_PKEY, _d2i_NETSCAPE_SPKAC, _d2i_NETSCAPE_SPKI, \n                       _d2i_NOTICEREF, _d2i_Netscape_RSA, _d2i_OCSP_BASICRESP, \n                       _d2i_OCSP_CERTID, _d2i_OCSP_CERTSTATUS, _d2i_OCSP_CRLID, \n                       _d2i_OCSP_ONEREQ, _d2i_OCSP_REQINFO, _d2i_OCSP_REQUEST, \n                       _d2i_OCSP_RESPBYTES, _d2i_OCSP_RESPDATA, _d2i_OCSP_RESPID, \n                       _d2i_OCSP_RESPONSE, _d2i_OCSP_REVOKEDINFO, _d2i_OCSP_SERVICELOC, \n                       _d2i_OCSP_SIGNATURE, _d2i_OCSP_SINGLERESP, _d2i_OTHERNAME, \n                       _d2i_PBE2PARAM, _d2i_PBEPARAM, _d2i_PBKDF2PARAM, \n                       _d2i_PKCS12, _d2i_PKCS12_BAGS, _d2i_PKCS12_MAC_DATA, \n                       _d2i_PKCS12_SAFEBAG, _d2i_PKCS12_bio, _d2i_PKCS12_fp, \n                       _d2i_PKCS7, _d2i_PKCS7_DIGEST, _d2i_PKCS7_ENCRYPT, \n                       _d2i_PKCS7_ENC_CONTENT, _d2i_PKCS7_ENVELOPE, _d2i_PKCS7_ISSUER_AND_SERIAL, \n                       _d2i_PKCS7_RECIP_INFO, _d2i_PKCS7_SIGNED, _d2i_PKCS7_SIGNER_INFO, \n                       _d2i_PKCS7_SIGN_ENVELOPE, _d2i_PKCS7_bio, _d2i_PKCS7_fp, \n                       _d2i_PKCS8PrivateKey_bio, _d2i_PKCS8PrivateKey_fp, \n                       _d2i_PKCS8_PRIV_KEY_INFO, _d2i_PKCS8_PRIV_KEY_INFO_bio, \n                       _d2i_PKCS8_PRIV_KEY_INFO_fp, _d2i_PKCS8_bio, _d2i_PKCS8_fp, \n                       _d2i_PKEY_USAGE_PERIOD, _d2i_POLICYINFO, _d2i_POLICYQUALINFO, \n                       _d2i_PROXY_CERT_INFO_EXTENSION, _d2i_PROXY_POLICY, \n                       _d2i_PUBKEY, _d2i_PUBKEY_bio, _d2i_PUBKEY_fp, _d2i_PrivateKey, \n                       _d2i_PrivateKey_bio, _d2i_PrivateKey_fp, _d2i_PublicKey, \n                       _d2i_RSAPrivateKey, _d2i_RSAPrivateKey_bio, _d2i_RSAPrivateKey_fp, \n                       _d2i_RSAPublicKey, _d2i_RSAPublicKey_bio, _d2i_RSAPublicKey_fp, \n                       _d2i_RSA_NET, _d2i_RSA_PUBKEY, _d2i_RSA_PUBKEY_bio, \n                       _d2i_RSA_PUBKEY_fp, _d2i_SXNET, _d2i_SXNETID, _d2i_USERNOTICE, \n                       _d2i_X509, _d2i_X509_ALGOR, _d2i_X509_ALGORS, _d2i_X509_ATTRIBUTE, \n                       _d2i_X509_AUX, _d2i_X509_CERT_AUX, _d2i_X509_CERT_PAIR, \n                       _d2i_X509_CINF, _d2i_X509_CRL, _d2i_X509_CRL_INFO, \n                       _d2i_X509_CRL_bio, _d2i_X509_CRL_fp, _d2i_X509_EXTENSION, \n                       _d2i_X509_EXTENSIONS, _d2i_X509_NAME, _d2i_X509_NAME_ENTRY, \n                       _d2i_X509_PKEY, _d2i_X509_PUBKEY, _d2i_X509_REQ, \n                       _d2i_X509_REQ_INFO, _d2i_X509_REQ_bio, _d2i_X509_REQ_fp, \n                       _d2i_X509_REVOKED, _d2i_X509_SIG, _d2i_X509_VAL, \n                       _d2i_X509_bio, _d2i_X509_fp, _dsa_pub_internal_it, \n                       _ec_GF2m_have_precompute_mult, _ec_GF2m_precompute_mult, \n                       _ec_GF2m_simple_add, _ec_GF2m_simple_cmp, _ec_GF2m_simple_dbl, \n                       _ec_GF2m_simple_field_div, _ec_GF2m_simple_field_mul, \n                       _ec_GF2m_simple_field_sqr, _ec_GF2m_simple_group_check_discriminant, \n                       _ec_GF2m_simple_group_clear_finish, _ec_GF2m_simple_group_copy, \n                       _ec_GF2m_simple_group_finish, _ec_GF2m_simple_group_get_curve, \n                       _ec_GF2m_simple_group_get_degree, _ec_GF2m_simple_group_init, \n                       _ec_GF2m_simple_group_set_curve, _ec_GF2m_simple_invert, \n                       _ec_GF2m_simple_is_at_infinity, _ec_GF2m_simple_is_on_curve, \n                       _ec_GF2m_simple_make_affine, _ec_GF2m_simple_mul, \n                       _ec_GF2m_simple_oct2point, _ec_GF2m_simple_point2oct, \n                       _ec_GF2m_simple_point_clear_finish, _ec_GF2m_simple_point_copy, \n                       _ec_GF2m_simple_point_finish, _ec_GF2m_simple_point_get_affine_coordinates, \n                       _ec_GF2m_simple_point_init, _ec_GF2m_simple_point_set_affine_coordinates, \n                       _ec_GF2m_simple_point_set_to_infinity, _ec_GF2m_simple_points_make_affine, \n                       _ec_GF2m_simple_set_compressed_coordinates, _ec_GFp_mont_field_decode, \n                       _ec_GFp_mont_field_encode, _ec_GFp_mont_field_mul, \n                       _ec_GFp_mont_field_set_to_one, _ec_GFp_mont_field_sqr, \n                       _ec_GFp_mont_group_clear_finish, _ec_GFp_mont_group_copy, \n                       _ec_GFp_mont_group_finish, _ec_GFp_mont_group_init, \n                       _ec_GFp_mont_group_set_curve, _ec_GFp_nist_field_mul, \n                       _ec_GFp_nist_field_sqr, _ec_GFp_nist_group_copy, \n                       _ec_GFp_nist_group_set_curve, _ec_GFp_simple_add, \n                       _ec_GFp_simple_cmp, _ec_GFp_simple_dbl, _ec_GFp_simple_field_mul, \n                       _ec_GFp_simple_field_sqr, _ec_GFp_simple_get_Jprojective_coordinates_GFp, \n                       _ec_GFp_simple_group_check_discriminant, _ec_GFp_simple_group_clear_finish, \n                       _ec_GFp_simple_group_copy, _ec_GFp_simple_group_finish, \n                       _ec_GFp_simple_group_get_curve, _ec_GFp_simple_group_get_degree, \n                       _ec_GFp_simple_group_init, _ec_GFp_simple_group_set_curve, \n                       _ec_GFp_simple_invert, _ec_GFp_simple_is_at_infinity, \n                       _ec_GFp_simple_is_on_curve, _ec_GFp_simple_make_affine, \n                       _ec_GFp_simple_oct2point, _ec_GFp_simple_point2oct, \n                       _ec_GFp_simple_point_clear_finish, _ec_GFp_simple_point_copy, \n                       _ec_GFp_simple_point_finish, _ec_GFp_simple_point_get_affine_coordinates, \n                       _ec_GFp_simple_point_init, _ec_GFp_simple_point_set_affine_coordinates, \n                       _ec_GFp_simple_point_set_to_infinity, _ec_GFp_simple_points_make_affine, \n                       _ec_GFp_simple_set_Jprojective_coordinates_GFp, \n                       _ec_GFp_simple_set_compressed_coordinates, _ec_wNAF_have_precompute_mult, \n                       _ec_wNAF_mul, _ec_wNAF_precompute_mult, _ecdh_check, \n                       _ecdsa_check, _engine_cleanup_add_first, _engine_cleanup_add_last, \n                       _engine_free_util, _engine_set_all_null, _engine_table_cleanup, \n                       _engine_table_register, _engine_table_select, _engine_table_unregister, \n                       _engine_unlocked_finish, _engine_unlocked_init, \n                       _fcrypt_body, _get_rfc2409_prime_1024, _get_rfc2409_prime_768, \n                       _get_rfc3526_prime_1536, _get_rfc3526_prime_2048, \n                       _get_rfc3526_prime_3072, _get_rfc3526_prime_4096, \n                       _get_rfc3526_prime_6144, _get_rfc3526_prime_8192, \n                       _hex_to_string, _i2a_ACCESS_DESCRIPTION, _i2a_ASN1_ENUMERATED, \n                       _i2a_ASN1_INTEGER, _i2a_ASN1_OBJECT, _i2a_ASN1_STRING, \n                       _i2c_ASN1_BIT_STRING, _i2c_ASN1_INTEGER, _i2d_ACCESS_DESCRIPTION, \n                       _i2d_ASN1_BIT_STRING, _i2d_ASN1_BMPSTRING, _i2d_ASN1_BOOLEAN, \n                       _i2d_ASN1_ENUMERATED, _i2d_ASN1_GENERALIZEDTIME, \n                       _i2d_ASN1_GENERALSTRING, _i2d_ASN1_HEADER, _i2d_ASN1_IA5STRING, \n                       _i2d_ASN1_INTEGER, _i2d_ASN1_NULL, _i2d_ASN1_OBJECT, \n                       _i2d_ASN1_OCTET_STRING, _i2d_ASN1_PRINTABLE, _i2d_ASN1_PRINTABLESTRING, \n                       _i2d_ASN1_SET, _i2d_ASN1_T61STRING, _i2d_ASN1_TIME, \n                       _i2d_ASN1_TYPE, _i2d_ASN1_UNIVERSALSTRING, _i2d_ASN1_UTCTIME, \n                       _i2d_ASN1_UTF8STRING, _i2d_ASN1_VISIBLESTRING, _i2d_ASN1_bytes, \n                       _i2d_AUTHORITY_INFO_ACCESS, _i2d_AUTHORITY_KEYID, \n                       _i2d_BASIC_CONSTRAINTS, _i2d_CERTIFICATEPOLICIES, \n                       _i2d_CRL_DIST_POINTS, _i2d_DHparams, _i2d_DIRECTORYSTRING, \n                       _i2d_DISPLAYTEXT, _i2d_DIST_POINT, _i2d_DIST_POINT_NAME, \n                       _i2d_DSAPrivateKey, _i2d_DSAPrivateKey_bio, _i2d_DSAPrivateKey_fp, \n                       _i2d_DSAPublicKey, _i2d_DSA_PUBKEY, _i2d_DSA_PUBKEY_bio, \n                       _i2d_DSA_PUBKEY_fp, _i2d_DSA_SIG, _i2d_DSAparams, \n                       _i2d_ECDSA_SIG, _i2d_ECPKPARAMETERS, _i2d_ECPKParameters, \n                       _i2d_ECParameters, _i2d_ECPrivateKey, _i2d_ECPrivateKey_bio, \n                       _i2d_ECPrivateKey_fp, _i2d_EC_PRIVATEKEY, _i2d_EC_PUBKEY, \n                       _i2d_EC_PUBKEY_bio, _i2d_EC_PUBKEY_fp, _i2d_EDIPARTYNAME, \n                       _i2d_EXTENDED_KEY_USAGE, _i2d_GENERAL_NAME, _i2d_GENERAL_NAMES, \n                       _i2d_KRB5_APREQ, _i2d_KRB5_APREQBODY, _i2d_KRB5_AUTHDATA, \n                       _i2d_KRB5_AUTHENT, _i2d_KRB5_AUTHENTBODY, _i2d_KRB5_CHECKSUM, \n                       _i2d_KRB5_ENCDATA, _i2d_KRB5_ENCKEY, _i2d_KRB5_PRINCNAME, \n                       _i2d_KRB5_TICKET, _i2d_KRB5_TKTBODY, _i2d_NETSCAPE_CERT_SEQUENCE, \n                       _i2d_NETSCAPE_ENCRYPTED_PKEY, _i2d_NETSCAPE_PKEY, \n                       _i2d_NETSCAPE_SPKAC, _i2d_NETSCAPE_SPKI, _i2d_NOTICEREF, \n                       _i2d_Netscape_RSA, _i2d_OCSP_BASICRESP, _i2d_OCSP_CERTID, \n                       _i2d_OCSP_CERTSTATUS, _i2d_OCSP_CRLID, _i2d_OCSP_ONEREQ, \n                       _i2d_OCSP_REQINFO, _i2d_OCSP_REQUEST, _i2d_OCSP_RESPBYTES, \n                       _i2d_OCSP_RESPDATA, _i2d_OCSP_RESPID, _i2d_OCSP_RESPONSE, \n                       _i2d_OCSP_REVOKEDINFO, _i2d_OCSP_SERVICELOC, _i2d_OCSP_SIGNATURE, \n                       _i2d_OCSP_SINGLERESP, _i2d_OTHERNAME, _i2d_PBE2PARAM, \n                       _i2d_PBEPARAM, _i2d_PBKDF2PARAM, _i2d_PKCS12, _i2d_PKCS12_BAGS, \n                       _i2d_PKCS12_MAC_DATA, _i2d_PKCS12_SAFEBAG, _i2d_PKCS12_bio, \n                       _i2d_PKCS12_fp, _i2d_PKCS7, _i2d_PKCS7_DIGEST, _i2d_PKCS7_ENCRYPT, \n                       _i2d_PKCS7_ENC_CONTENT, _i2d_PKCS7_ENVELOPE, _i2d_PKCS7_ISSUER_AND_SERIAL, \n                       _i2d_PKCS7_NDEF, _i2d_PKCS7_RECIP_INFO, _i2d_PKCS7_SIGNED, \n                       _i2d_PKCS7_SIGNER_INFO, _i2d_PKCS7_SIGN_ENVELOPE, \n                       _i2d_PKCS7_bio, _i2d_PKCS7_fp, _i2d_PKCS8PrivateKeyInfo_bio, \n                       _i2d_PKCS8PrivateKeyInfo_fp, _i2d_PKCS8PrivateKey_bio, \n                       _i2d_PKCS8PrivateKey_fp, _i2d_PKCS8PrivateKey_nid_bio, \n                       _i2d_PKCS8PrivateKey_nid_fp, _i2d_PKCS8_PRIV_KEY_INFO, \n                       _i2d_PKCS8_PRIV_KEY_INFO_bio, _i2d_PKCS8_PRIV_KEY_INFO_fp, \n                       _i2d_PKCS8_bio, _i2d_PKCS8_fp, _i2d_PKEY_USAGE_PERIOD, \n                       _i2d_POLICYINFO, _i2d_POLICYQUALINFO, _i2d_PROXY_CERT_INFO_EXTENSION, \n                       _i2d_PROXY_POLICY, _i2d_PUBKEY, _i2d_PUBKEY_bio, \n                       _i2d_PUBKEY_fp, _i2d_PrivateKey, _i2d_PrivateKey_bio, \n                       _i2d_PrivateKey_fp, _i2d_PublicKey, _i2d_RSAPrivateKey, \n                       _i2d_RSAPrivateKey_bio, _i2d_RSAPrivateKey_fp, _i2d_RSAPublicKey, \n                       _i2d_RSAPublicKey_bio, _i2d_RSAPublicKey_fp, _i2d_RSA_NET, \n                       _i2d_RSA_PUBKEY, _i2d_RSA_PUBKEY_bio, _i2d_RSA_PUBKEY_fp, \n                       _i2d_SXNET, _i2d_SXNETID, _i2d_USERNOTICE, _i2d_X509, \n                       _i2d_X509_ALGOR, _i2d_X509_ALGORS, _i2d_X509_ATTRIBUTE, \n                       _i2d_X509_AUX, _i2d_X509_CERT_AUX, _i2d_X509_CERT_PAIR, \n                       _i2d_X509_CINF, _i2d_X509_CRL, _i2d_X509_CRL_INFO, \n                       _i2d_X509_CRL_bio, _i2d_X509_CRL_fp, _i2d_X509_EXTENSION, \n                       _i2d_X509_EXTENSIONS, _i2d_X509_NAME, _i2d_X509_NAME_ENTRY, \n                       _i2d_X509_PKEY, _i2d_X509_PUBKEY, _i2d_X509_REQ, \n                       _i2d_X509_REQ_INFO, _i2d_X509_REQ_bio, _i2d_X509_REQ_fp, \n                       _i2d_X509_REVOKED, _i2d_X509_SIG, _i2d_X509_VAL, \n                       _i2d_X509_bio, _i2d_X509_fp, _i2o_ECPublicKey, _i2s_ASN1_ENUMERATED, \n                       _i2s_ASN1_ENUMERATED_TABLE, _i2s_ASN1_INTEGER, _i2s_ASN1_OCTET_STRING, \n                       _i2t_ASN1_OBJECT, _i2v_ASN1_BIT_STRING, _i2v_GENERAL_NAME, \n                       _i2v_GENERAL_NAMES, _int_CRYPTO_set_do_dynlock_callback, \n                       _int_smime_write_ASN1, _level_add_node, _level_find_node, \n                       _lh_delete, _lh_doall, _lh_doall_arg, _lh_free, \n                       _lh_insert, _lh_new, _lh_node_stats, _lh_node_stats_bio, \n                       _lh_node_usage_stats, _lh_node_usage_stats_bio, \n                       _lh_num_items, _lh_retrieve, _lh_stats, _lh_stats_bio, \n                       _lh_strhash, _lh_version, _md4_block_data_order, \n                       _md5_block_data_order, _ms_time_cmp, _ms_time_diff, \n                       _ms_time_free, _ms_time_get, _ms_time_new, _name_cmp, \n                       _o2i_ECPublicKey, _pitem_free, _pitem_new, _policy_cache_find_data, \n                       _policy_cache_free, _policy_cache_set, _policy_cache_set_mapping, \n                       _policy_data_free, _policy_data_new, _policy_node_cmp_new, \n                       _policy_node_free, _pqueue_find, _pqueue_free, _pqueue_insert, \n                       _pqueue_iterator, _pqueue_new, _pqueue_next, _pqueue_peek, \n                       _pqueue_pop, _pqueue_print, _pqueue_size, _rand_ssleay_meth, \n                       _ripemd160_block_data_order, _s2i_ASN1_INTEGER, \n                       _s2i_ASN1_OCTET_STRING, _sk_delete, _sk_delete_ptr, \n                       _sk_dup, _sk_find, _sk_find_ex, _sk_free, _sk_insert, \n                       _sk_is_sorted, _sk_new, _sk_new_null, _sk_num, _sk_pop, \n                       _sk_pop_free, _sk_push, _sk_set, _sk_set_cmp_func, \n                       _sk_shift, _sk_sort, _sk_unshift, _sk_value, _sk_zero, \n                       _string_to_hex, _tree_find_sk, _uni2asc, _v2i_ASN1_BIT_STRING, \n                       _v2i_GENERAL_NAME, _v2i_GENERAL_NAMES, _v2i_GENERAL_NAME_ex, \n                       _v3_akey_id, _v3_alt, _v3_bcons, _v3_cpols, _v3_crl_hold, \n                       _v3_crl_invdate, _v3_crl_num, _v3_crl_reason, _v3_crld, \n                       _v3_delta_crl, _v3_ext_ku, _v3_info, _v3_inhibit_anyp, \n                       _v3_key_usage, _v3_name_constraints, _v3_ns_ia5_list, \n                       _v3_nscert, _v3_ocsp_accresp, _v3_ocsp_acutoff, \n                       _v3_ocsp_crlid, _v3_ocsp_nocheck, _v3_ocsp_nonce, \n                       _v3_ocsp_serviceloc, _v3_pci, _v3_pkey_usage_period, \n                       _v3_policy_constraints, _v3_policy_mappings, _v3_sinfo, \n                       _v3_skey_id, _v3_sxnet, _x509_dir_lookup, _x509_file_lookup, \n                       _x509_name_ff ]\n...\n"
  },
  {
    "path": "src/adium/openssl/opensslconf.h",
    "content": "/* opensslconf.h */\n/* WARNING: Generated automatically from opensslconf.h.in by Configure. */\n\n/* OpenSSL was configured with the following options: */\n#ifndef OPENSSL_SYSNAME_MACOSX\n# define OPENSSL_SYSNAME_MACOSX\n#endif\n#ifndef OPENSSL_DOING_MAKEDEPEND\n\n\n#ifndef OPENSSL_NO_CAMELLIA\n# define OPENSSL_NO_CAMELLIA\n#endif\n#ifndef OPENSSL_NO_CAPIENG\n# define OPENSSL_NO_CAPIENG\n#endif\n#ifndef OPENSSL_NO_CMS\n# define OPENSSL_NO_CMS\n#endif\n#ifndef OPENSSL_NO_GMP\n# define OPENSSL_NO_GMP\n#endif\n#ifndef OPENSSL_NO_IDEA\n# define OPENSSL_NO_IDEA\n#endif\n#ifndef OPENSSL_NO_JPAKE\n# define OPENSSL_NO_JPAKE\n#endif\n#ifndef OPENSSL_NO_KRB5\n# define OPENSSL_NO_KRB5\n#endif\n#ifndef OPENSSL_NO_RFC3779\n# define OPENSSL_NO_RFC3779\n#endif\n\n#endif /* OPENSSL_DOING_MAKEDEPEND */\n\n#ifndef OPENSSL_THREADS\n# define OPENSSL_THREADS\n#endif\n#ifndef OPENSSL_NO_HW\n# define OPENSSL_NO_HW\n#endif\n#ifndef OPENSSL_NO_STATIC_ENGINE\n# define OPENSSL_NO_STATIC_ENGINE\n#endif\n\n/* The OPENSSL_NO_* macros are also defined as NO_* if the application\n   asks for it.  This is a transient feature that is provided for those\n   who haven't had the time to do the appropriate changes in their\n   applications.  */\n#ifdef OPENSSL_ALGORITHM_DEFINES\n# if defined(OPENSSL_NO_CAMELLIA) && !defined(NO_CAMELLIA)\n#  define NO_CAMELLIA\n# endif\n# if defined(OPENSSL_NO_CAPIENG) && !defined(NO_CAPIENG)\n#  define NO_CAPIENG\n# endif\n# if defined(OPENSSL_NO_CMS) && !defined(NO_CMS)\n#  define NO_CMS\n# endif\n# if defined(OPENSSL_NO_GMP) && !defined(NO_GMP)\n#  define NO_GMP\n# endif\n# if defined(OPENSSL_NO_IDEA) && !defined(NO_IDEA)\n#  define NO_IDEA\n# endif\n# if defined(OPENSSL_NO_JPAKE) && !defined(NO_JPAKE)\n#  define NO_JPAKE\n# endif\n# if defined(OPENSSL_NO_KRB5) && !defined(NO_KRB5)\n#  define NO_KRB5\n# endif\n# if defined(OPENSSL_NO_RFC3779) && !defined(NO_RFC3779)\n#  define NO_RFC3779\n# endif\n#endif\n\n/* crypto/opensslconf.h.in */\n\n#ifdef OPENSSL_DOING_MAKEDEPEND\n\n/* Include any symbols here that have to be explicitly set to enable a feature\n * that should be visible to makedepend.\n *\n * [Our \"make depend\" doesn't actually look at this, we use actual build settings\n * instead; we want to make it easy to remove subdirectories with disabled algorithms.]\n */\n\n#ifndef OPENSSL_FIPS\n#define OPENSSL_FIPS\n#endif\n\n#endif\n\n/* Generate 80386 code? */\n#undef I386_ONLY\n\n#if !(defined(VMS) || defined(__VMS)) /* VMS uses logical names instead */\n#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR)\n#define ENGINESDIR \"/usr/lib/openssl/engines\"\n#define OPENSSLDIR \"/System/Library/OpenSSL\"\n#endif\n#endif\n\n#undef OPENSSL_UNISTD\n#define OPENSSL_UNISTD <unistd.h>\n\n#undef OPENSSL_EXPORT_VAR_AS_FUNCTION\n\n#if defined(HEADER_IDEA_H) && !defined(IDEA_INT)\n#define IDEA_INT unsigned int\n#endif\n\n#if defined(HEADER_MD2_H) && !defined(MD2_INT)\n#define MD2_INT unsigned int\n#endif\n\n#if defined(HEADER_RC2_H) && !defined(RC2_INT)\n/* I need to put in a mod for the alpha - eay */\n#define RC2_INT unsigned int\n#endif\n\n#if defined(HEADER_RC4_H)\n#if !defined(RC4_INT)\n/* using int types make the structure larger but make the code faster\n * on most boxes I have tested - up to %20 faster. */\n/*\n * I don't know what does \"most\" mean, but declaring \"int\" is a must on:\n * - Intel P6 because partial register stalls are very expensive;\n * - elder Alpha because it lacks byte load/store instructions;\n */\n#define RC4_INT unsigned char\n#endif\n#if !defined(RC4_CHUNK)\n/*\n * This enables code handling data aligned at natural CPU word\n * boundary. See crypto/rc4/rc4_enc.c for further details.\n */\n#define RC4_CHUNK unsigned long\n#endif\n#endif\n\n#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG)\n/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a\n * %20 speed up (longs are 8 bytes, int's are 4). */\n#ifndef DES_LONG\n#ifdef __LP64__\n#define DES_LONG unsigned int\n#else\n#define DES_LONG unsigned long\n#endif\n#endif\n#endif\n\n#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H)\n#define CONFIG_HEADER_BN_H\n#ifdef __LP64__\n#undef BN_LLONG\n#else\n#define BN_LLONG\n#endif\n\n/* Should we define BN_DIV2W here? */\n\n/* Only one for the following should be defined */\n/* The prime number generation stuff may not work when\n * EIGHT_BIT but I don't care since I've only used this mode\n * for debuging the bignum libraries */\n#ifdef __LP64__\n#define SIXTY_FOUR_BIT_LONG\n#else\n#undef SIXTY_FOUR_BIT_LONG\n#endif\n#undef SIXTY_FOUR_BIT\n#ifdef __LP64__\n#undef THIRTY_TWO_BIT\n#else\n#define THIRTY_TWO_BIT\n#endif\n#undef SIXTEEN_BIT\n#undef EIGHT_BIT\n#endif\n\n#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H)\n#define CONFIG_HEADER_RC4_LOCL_H\n/* if this is defined data[i] is used instead of *data, this is a %20\n * speedup on x86 */\n#undef RC4_INDEX\n#endif\n\n#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H)\n#define CONFIG_HEADER_BF_LOCL_H\n#ifdef __LP64__\n#undef BF_PTR\n#else\n#define BF_PTR\n#endif\n#endif /* HEADER_BF_LOCL_H */\n\n#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H)\n#define CONFIG_HEADER_DES_LOCL_H\n#ifndef DES_DEFAULT_OPTIONS\n/* the following is tweaked from a config script, that is why it is a\n * protected undef/define */\n#ifndef DES_PTR\n#undef DES_PTR\n#endif\n\n/* This helps C compiler generate the correct code for multiple functional\n * units.  It reduces register dependancies at the expense of 2 more\n * registers */\n#ifndef DES_RISC1\n#undef DES_RISC1\n#endif\n\n#ifndef DES_RISC2\n#undef DES_RISC2\n#endif\n\n#if defined(DES_RISC1) && defined(DES_RISC2)\nYOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!!\n#endif\n\n/* Unroll the inner loop, this sometimes helps, sometimes hinders.\n * Very mucy CPU dependant */\n#ifndef DES_UNROLL\n#define DES_UNROLL\n#endif\n\n/* These default values were supplied by\n * Peter Gutman <pgut001@cs.auckland.ac.nz>\n * They are only used if nothing else has been defined */\n#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL)\n/* Special defines which change the way the code is built depending on the\n   CPU and OS.  For SGI machines you can use _MIPS_SZLONG (32 or 64) to find\n   even newer MIPS CPU's, but at the moment one size fits all for\n   optimization options.  Older Sparc's work better with only UNROLL, but\n   there's no way to tell at compile time what it is you're running on */\n \n#if defined( sun )\t\t/* Newer Sparc's */\n#  define DES_PTR\n#  define DES_RISC1\n#  define DES_UNROLL\n#elif defined( __ultrix )\t/* Older MIPS */\n#  define DES_PTR\n#  define DES_RISC2\n#  define DES_UNROLL\n#elif defined( __osf1__ )\t/* Alpha */\n#  define DES_PTR\n#  define DES_RISC2\n#elif defined ( _AIX )\t\t/* RS6000 */\n  /* Unknown */\n#elif defined( __hpux )\t\t/* HP-PA */\n  /* Unknown */\n#elif defined( __aux )\t\t/* 68K */\n  /* Unknown */\n#elif defined( __dgux )\t\t/* 88K (but P6 in latest boxes) */\n#  define DES_UNROLL\n#elif defined( __sgi )\t\t/* Newer MIPS */\n#  define DES_PTR\n#  define DES_RISC2\n#  define DES_UNROLL\n#elif defined(i386) || defined(__i386__)\t/* x86 boxes, should be gcc */\n#  define DES_PTR\n#  define DES_RISC1\n#  define DES_UNROLL\n#endif /* Systems-specific speed defines */\n#endif\n\n#endif /* DES_DEFAULT_OPTIONS */\n#endif /* HEADER_DES_LOCL_H */\n"
  },
  {
    "path": "src/adium/xcconfigs/Base.xcconfig",
    "content": "//\n//  Base.xcconfig\n//  SIPEAdiumPlugin\n//\n//  Created by Lamb, Michael on 11/13/13.\n//\n//\n\nINFOPLIST_PREPROCESSOR_DEFINITIONS = ${GCC_PREPROCESSOR_DEFINITIONS}\nINFOPLIST_PREPROCESS = YES\n\nMACOSX_DEPLOYMENT_TARGET = 10.8\n\nHEADER_SEARCH_PATHS = \"../../../adium/Frameworks/libglib.framework/Headers\" \"../../../adium/Frameworks/libpurple.framework/Headers\" \"../../../adium/Frameworks/libintl.framework/Headers\" ../purple ../api /usr/include/libxml2 . ../../../openssl-0.9.8za/include\n\n// Hack to work around how xcconfig pre-processor handles double-slash as a comment (even in a quoted string!!) :(\nSLASH=/\nSIPE_TRANSLATIONS_URL=\\\"https:${SLASH}/www.transifex.com/stefanb/pidgin-sipe/\\\"\nPACKAGE_BUGREPORT=\\\"https:${SLASH}/sourceforge.net/p/sipe/bugs/\\\"\nPACKAGE_URL=\\\"http:${SLASH}/sipe.sourceforge.net/\\\"\n\n// No need to change version number in the xcodeproj file every release, just here.\nPACKAGE_VERSION=1.25.0\nPACKAGE_STRING=\\\"pidgin-sipe\\ ${PACKAGE_VERSION}\\\"\n\nGCC_PREPROCESSOR_DEFINITIONS = SIPE_TRANSLATIONS_URL=${SIPE_TRANSLATIONS_URL} LOCALEDIR=\\\"translations\\\" PURPLE_STATIC_PRPL=1 HAVE_BIND_TEXTDOMAIN_CODESET=1 ENABLE_NLS=1 ADIUM=1 PACKAGE_NAME=\\\"pidgin-sipe\\\" PACKAGE_TARNAME=\\\"pidgin-sipe\\\" PACKAGE_BUGREPORT=${PACKAGE_BUGREPORT} PACKAGE_VERSION=\\\"${PACKAGE_VERSION}\\\" PACKAGE_STRING=${PACKAGE_STRING} PACKAGE_URL=${PACKAGE_URL} STDC_HEADERS=1 HAVE_SYS_TYPES_H=1 HAVE_SYS_STAT_H=1 HAVE_STDLIB_H=1 HAVE_STRING_H=1 HAVE_MEMORY_H=1 HAVE_STRINGS_H=1 HAVE_INTTYPES_H=1 HAVE_STDINT_H=1 HAVE_UNISTD_H=1 HAVE_DLFCN_H=1 LT_OBJDIR=\\\".libs/\\\" STDC_HEADERS=1 HAVE_LOCALE_H=1 HAVE_LC_MESSAGES=1 HAVE_DLFCN_H=1 HAVE_DCGETTEXT=1 HAVE_GETTEXT=1 HAVE_LOCALE_H=1 HAVE_GSSAPI_GSSAPI_H=1 HAVE_LANGINFO_CODESET=1\n\nARCHS = $(ARCHS_STANDARD_64_BIT)\nSTRINGS_FILE_OUTPUT_ENCODING = UTF-16\nGCC_MODEL_TUNING = G5\nGCC_C_LANGUAGE_STANDARD = gnu99\nGCC_WARN_ABOUT_RETURN_TYPE = YES\nGCC_WARN_UNUSED_VARIABLE = YES\nGCC_PRECOMPILE_PREFIX_HEADER = YES\nDEBUG_INFORMATION_FORMAT = dwarf-with-dsym\n\n\n\n\n"
  },
  {
    "path": "src/adium/xcconfigs/Debug-Release.xcconfig",
    "content": "//\n//  Debug-Release.xcconfig\n//  SIPEAdiumPlugin\n//\n//  Created by Lamb, Michael on 11/13/13.\n//\n//\n#include \"Base.xcconfig\"\n//:configuration = Debug-Release\n"
  },
  {
    "path": "src/adium/xcconfigs/Debug.xcconfig",
    "content": "//\n//  Debug.xcconfig\n//  SIPEAdiumPlugin\n//\n//  Created by Lamb, Michael on 11/13/13.\n//\n//\n#include \"Base.xcconfig\"\n//:configuration = Debug\nONLY_ACTIVE_ARCH = YES\nCOPY_PHASE_STRIP = NO\nGCC_DYNAMIC_NO_PIC = NO\nGCC_OPTIMIZATION_LEVEL = 0\n"
  },
  {
    "path": "src/adium/xcconfigs/Release.xcconfig",
    "content": "//\n//  Release.xcconfig\n//  SIPEAdiumPlugin\n//\n//  Created by Lamb, Michael on 11/13/13.\n//\n//\n#include \"Base.xcconfig\"\n//:configuration = Release\nDEBUG_INFORMATION_FORMAT = dwarf-with-dsym\nCOPY_PHASE_STRIP = YES\nGCC_MODEL_TUNING = G5\nZERO_LINK = NO\n"
  },
  {
    "path": "src/adium/xcconfigs/SIPEAdiumPlugin.xcconfig",
    "content": "//\n//  SIPEAdiumPlugin.xcconfig\n//  SIPEAdiumPlugin\n//\n//  Created by Lamb, Michael on 11/13/13.\n//\n//\nPRODUCT_NAME = SIPEAdiumPlugin\nOTHER_LDFLAGS = -lxml2 -Lopenssl -lcrypto.0.9.8 -undefined dynamic_lookup\nLD_RUNPATH_SEARCH_PATHS = @loader_path/../Frameworks\nINFOPLIST_FILE = Info.plist\nWRAPPER_EXTENSION = AdiumLibpurplePlugin\nGCC_PREFIX_HEADER = SIPEAdiumPlugin_Prefix.pch\nDEPLOYMENT_LOCATION = YES\nDEPLOYMENT_POSTPROCESSING = YES\nDSTROOT =\nINSTALL_PATH = $(HOME)/Library/Application Support/Adium 2.0/PlugIns/\nFRAMEWORK_SEARCH_PATHS = \"$(BUILT_PRODUCTS_DIR)\" ./adium-frameworks ../../../adium/Frameworks\nUSER_HEADER_SEARCH_PATHS = \"$(BUILT_PRODUCTS_DIR)/Adium.framework/Headers\" ./adium-frameworks/Adium.framework/Headers ../../../adium/Source\n"
  },
  {
    "path": "src/adium/xcconfigs/libpidgin-sipe.xcconfig",
    "content": "//\n//  libpidgin-sipe.xcconfig\n//  SIPEAdiumPlugin\n//\n//  Created by Lamb, Michael on 11/13/13.\n//\n//\nPRODUCT_NAME = pidgin-sipe\n\n\n\n"
  },
  {
    "path": "src/api/Makefile.am",
    "content": "MAINTAINERCLEANFILES = \\\n\tMakefile.in\n\nEXTRA_DIST = \\\n\tsipe-backend.h \\\n\tsipe-common.h \\\n\tsipe-core.h \\\n\tsipe-mime.h \\\n\tsipe-nls.h\n"
  },
  {
    "path": "src/api/sipe-backend.h",
    "content": "/**\n * @file sipe-backend.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/**\n *\n * SIPE Core -> Backend API - functions called by SIPE core code\n *\n ***************** !!! IMPORTANT NOTE FOR BACKEND CODERS !!! *****************\n *\n *            The SIPE core assumes atomicity and is *NOT* thread-safe.\n *\n * It *does not* protect any of its data structures or code paths with locks!\n *\n * In no circumstances it must be possible that a sipe_core_xxx() function can\n * be entered through another thread while the first thread has entered the\n * backend specific code through a sipe_backend_xxx() function.\n *\n ***************** !!! IMPORTANT NOTE FOR BACKEND CODERS !!! *****************\n */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Forward declarations */\nstruct sipe_backend_chat_session;\nstruct sipe_chat_session;\nstruct sipe_core_public;\nstruct sipe_transport_connection;\nstruct sipe_file_transfer;\nstruct sipe_media_call;\nstruct sipe_media;\n\n/** MISC. STUFF **************************************************************/\n/**\n * Get the version of the backend suitable for e.g. UserAgent\n *\n * @return backend version string. Will be g_free()'d.by the core.\n */\ngchar *sipe_backend_version(void);\n\n/** DEBUGGING ****************************************************************/\n\ntypedef enum {\n\tSIPE_LOG_LEVEL_INFO,\n\tSIPE_LOG_LEVEL_WARNING,\n\tSIPE_LOG_LEVEL_ERROR,\n\tSIPE_DEBUG_LEVEL_INFO,\n\tSIPE_DEBUG_LEVEL_WARNING,\n\tSIPE_DEBUG_LEVEL_ERROR,\n}  sipe_debug_level;\n#define SIPE_DEBUG_LEVEL_LOWEST SIPE_DEBUG_LEVEL_INFO\n\n/**\n * Output debug information without formatting\n *\n * Shouldn't be used directly. Instead use SIPE_DEBUG_xxx() macros\n *\n * @param level  debug level\n * @param msg    debug message \"\\n\" will be automatically appended.\n */\nvoid sipe_backend_debug_literal(sipe_debug_level level,\n\t\t\t\tconst gchar *msg);\n\n/**\n * Output debug information\n *\n * Shouldn't be used directly. Instead use SIPE_DEBUG_xxx() macros\n *\n * @param level  debug level\n * @param format format string. \"\\n\" will be automatically appended.\n */\nvoid sipe_backend_debug(sipe_debug_level level,\n\t\t\tconst gchar *format,\n\t\t\t...) G_GNUC_PRINTF(2, 3);\n\n/* Convenience macros */\n#define SIPE_LOG_INFO(fmt, ...)          sipe_backend_debug(SIPE_LOG_LEVEL_INFO,    fmt, __VA_ARGS__)\n#define SIPE_LOG_INFO_NOFORMAT(msg)      sipe_backend_debug_literal(SIPE_LOG_LEVEL_INFO,    msg)\n#define SIPE_LOG_WARNING(fmt, ...)       sipe_backend_debug(SIPE_LOG_LEVEL_WARNING, fmt, __VA_ARGS__)\n#define SIPE_LOG_WARNING_NOFORMAT(msg)   sipe_backend_debug_literal(SIPE_LOG_LEVEL_WARNING, msg)\n#define SIPE_LOG_ERROR(fmt, ...)         sipe_backend_debug(SIPE_LOG_LEVEL_ERROR,   fmt, __VA_ARGS__)\n#define SIPE_LOG_ERROR_NOFORMAT(msg)     sipe_backend_debug_literal(SIPE_LOG_LEVEL_ERROR,   msg)\n#define SIPE_DEBUG_INFO(fmt, ...)        sipe_backend_debug(SIPE_DEBUG_LEVEL_INFO,    fmt, __VA_ARGS__)\n#define SIPE_DEBUG_INFO_NOFORMAT(msg)    sipe_backend_debug_literal(SIPE_DEBUG_LEVEL_INFO,    msg)\n#define SIPE_DEBUG_WARNING(fmt, ...)     sipe_backend_debug(SIPE_DEBUG_LEVEL_WARNING, fmt, __VA_ARGS__)\n#define SIPE_DEBUG_WARNING_NOFORMAT(msg) sipe_backend_debug_literal(SIPE_DEBUG_LEVEL_WARNING, msg)\n#define SIPE_DEBUG_ERROR(fmt, ...)       sipe_backend_debug(SIPE_DEBUG_LEVEL_ERROR,   fmt, __VA_ARGS__)\n#define SIPE_DEBUG_ERROR_NOFORMAT(msg)   sipe_backend_debug_literal(SIPE_DEBUG_LEVEL_ERROR,   msg)\n\n/**\n * Check backend debugging status\n *\n * @return TRUE if debugging is enabled\n */\ngboolean sipe_backend_debug_enabled(void);\n\n/** CHAT *********************************************************************/\n\nvoid sipe_backend_chat_session_destroy(struct sipe_backend_chat_session *session);\nvoid sipe_backend_chat_add(struct sipe_backend_chat_session *backend_session,\n\t\t\t   const gchar *uri,\n\t\t\t   gboolean is_new);\nvoid sipe_backend_chat_close(struct sipe_backend_chat_session *backend_session);\n\n/**\n * Joined a new chat\n */\nstruct sipe_backend_chat_session *sipe_backend_chat_create(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t   struct sipe_chat_session *session,\n\t\t\t\t\t\t\t   const gchar *title,\n\t\t\t\t\t\t\t   const gchar *nick);\ngboolean sipe_backend_chat_find(struct sipe_backend_chat_session *backend_session,\n\t\t\t\tconst gchar *uri);\ngboolean sipe_backend_chat_is_operator(struct sipe_backend_chat_session *backend_session,\n\t\t\t\t       const gchar *uri);\nvoid sipe_backend_chat_message(struct sipe_core_public *sipe_public,\n\t\t\t       struct sipe_backend_chat_session *backend_session,\n\t\t\t       const gchar *from,\n\t\t\t       time_t when,\n\t\t\t       const gchar *html);\nvoid sipe_backend_chat_operator(struct sipe_backend_chat_session *backend_session,\n\t\t\t\tconst gchar *uri);\n\n/**\n * Rejoin an existing chat window after connection re-establishment\n */\nvoid sipe_backend_chat_rejoin(struct sipe_core_public *sipe_public,\n\t\t\t      struct sipe_backend_chat_session *backend_session,\n\t\t\t      const gchar *nick,\n\t\t\t      const gchar *title);\n\n/**\n * Core has completed connection re-establishment.\n * Should call sipe_core_chat_rejoin() for existing chats.\n */\nvoid sipe_backend_chat_rejoin_all(struct sipe_core_public *sipe_public);\nvoid sipe_backend_chat_remove(struct sipe_backend_chat_session *backend_session,\n\t\t\t      const gchar *uri);\n\n/**\n * Move chat window to the front. Will be called when\n * a user tries to join an already joined chat again.\n */\nvoid sipe_backend_chat_show(struct sipe_backend_chat_session *backend_session);\nvoid sipe_backend_chat_topic(struct sipe_backend_chat_session *backend_session,\n\t\t\t     const gchar *topic);\n\n/** CONNECTION ***************************************************************/\n\nvoid sipe_backend_connection_completed(struct sipe_core_public *sipe_public);\n\ntypedef enum {\n  SIPE_CONNECTION_ERROR_NETWORK = 0,\n  SIPE_CONNECTION_ERROR_INVALID_USERNAME,\n  SIPE_CONNECTION_ERROR_INVALID_SETTINGS,\n  SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,\n  SIPE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,\n  SIPE_CONNECTION_ERROR_LAST\n} sipe_connection_error;\nvoid sipe_backend_connection_error(struct sipe_core_public *sipe_public,\n\t\t\t\t   sipe_connection_error error,\n\t\t\t\t   const gchar *msg);\n\ngboolean sipe_backend_connection_is_disconnecting(struct sipe_core_public *sipe_public);\ngboolean sipe_backend_connection_is_valid(struct sipe_core_public *sipe_public);\n\n/** DNS QUERY ****************************************************************/\n\ntypedef void (*sipe_dns_resolved_cb)(gpointer data, const gchar *hostname, guint port);\n\nstruct sipe_dns_query *sipe_backend_dns_query_srv(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t  const gchar *protocol,\n\t\t\t\t\t\t  const gchar *transport,\n\t\t\t\t\t\t  const gchar *domain,\n\t\t\t\t\t\t  sipe_dns_resolved_cb callback,\n\t\t\t\t\t\t  gpointer data);\n\nstruct sipe_dns_query *sipe_backend_dns_query_a(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\tconst gchar *hostname,\n\t\t\t\t\t\tguint port,\n\t\t\t\t\t\tsipe_dns_resolved_cb callback,\n\t\t\t\t\t\tgpointer data);\n\nvoid sipe_backend_dns_query_cancel(struct sipe_dns_query *query);\n\n/** FILE TRANSFER ************************************************************/\n\nstruct sipe_backend_fd;\n\nvoid sipe_backend_ft_error(struct sipe_file_transfer *ft,\n\t\t\t   const gchar *errmsg);\nconst gchar *sipe_backend_ft_get_error(struct sipe_file_transfer *ft);\nvoid sipe_backend_ft_deallocate(struct sipe_file_transfer *ft);\n\n/**\n * Try to read up to @c size bytes from file transfer connection\n *\n * @param ft   file transfer data.\n * @param data buffer to read data into.\n * @param size buffer size in bytes.\n *\n * @return number of bytes read or negative on failure.\n *         EAGAIN should return 0 bytes read.\n */\ngssize sipe_backend_ft_read(struct sipe_file_transfer *ft,\n\t\t\t    guchar *data,\n\t\t\t    gsize size);\n\n/**\n * Try to write up to @c size bytes to file transfer connection\n *\n * @param ft   file transfer data.\n * @param data data to write\n * @param size buffer size in bytes.\n *\n * @return number of bytes read or negative on failure.\n *         EAGAIN should return 0 bytes written.\n */\ngssize sipe_backend_ft_write(struct sipe_file_transfer *ft,\n\t\t\t     const guchar *data,\n\t\t\t     gsize size);\n\nvoid sipe_backend_ft_set_completed(struct sipe_file_transfer *ft);\n\nvoid sipe_backend_ft_cancel_local(struct sipe_file_transfer *ft);\nvoid sipe_backend_ft_cancel_remote(struct sipe_file_transfer *ft);\n\nvoid sipe_backend_ft_incoming(struct sipe_core_public *sipe_public,\n\t\t\t      struct sipe_file_transfer *ft,\n\t\t\t      const gchar *who,\n\t\t\t      const gchar *file_name,\n\t\t\t      gsize file_size);\n/**\n * Allocates and initializes backend file transfer structure for sending a file.\n *\n * @param sipe_public (in) the handle representing the protocol instance\n * @param ft (in) sipe core file transfer structure\n * @param who (in) SIP URI of the file recipient\n * @param file_name (in) filesystem path of the file being sent\n */\nvoid sipe_backend_ft_outgoing(struct sipe_core_public *sipe_public,\n\t\t\t      struct sipe_file_transfer *ft,\n\t\t\t      const gchar *who,\n\t\t\t      const gchar *file_name);\n/**\n * Begins file transfer with remote peer.\n *\n * You can provide either opened file descriptor to use for read/write operations\n * or ip address and port where the backend should connect.\n *\n * @param ft   file transfer data\n * @param fd   opaque file descriptor pointer or NULL if ip and port are used\n * @param ip   ip address to connect of NULL when file descriptor is used\n * @param port port to connect or 0 when file descriptor is used\n */\nvoid sipe_backend_ft_start(struct sipe_file_transfer *ft,\n\t\t\t   struct sipe_backend_fd *fd,\n\t\t\t   const char* ip, unsigned port);\n\n/**\n * Check whether file transfer is incoming or outgoing\n *\n * @param ft file transfer data\n * @return @c TRUE if @c ft is incoming, otherwise @c FALSE\n */\ngboolean sipe_backend_ft_is_incoming(struct sipe_file_transfer *ft);\n\n/** GROUP CHAT ***************************************************************/\n\n#define SIPE_GROUPCHAT_ROOM_FILEPOST 0x00000001\n#define SIPE_GROUPCHAT_ROOM_INVITE   0x00000002\n#define SIPE_GROUPCHAT_ROOM_LOGGED   0x00000004\n#define SIPE_GROUPCHAT_ROOM_PRIVATE  0x00000008\n\n/**\n * Add a room found through room query\n *\n * @param uri         room URI\n * @param name        human readable name for room\n * @param description room description\n * @param users       number of users in the room\n * @param flags       SIPE_GROUPCHAT_ROOM_* flags\n */\nvoid sipe_backend_groupchat_room_add(struct sipe_core_public *sipe_public,\n\t\t\t\t     const gchar *uri,\n\t\t\t\t     const gchar *name,\n\t\t\t\t     const gchar *description,\n\t\t\t\t     guint users,\n\t\t\t\t     guint32 flags);\n\n/**\n * Terminate room query\n */\nvoid sipe_backend_groupchat_room_terminate(struct sipe_core_public *sipe_public);\n\n/** IM ***********************************************************************/\n\nvoid sipe_backend_im_message(struct sipe_core_public *sipe_public,\n\t\t\t     const gchar *from,\n\t\t\t     const gchar *html);\nvoid sipe_backend_im_topic(struct sipe_core_public *sipe_public,\n\t\t\t   const gchar *with,\n\t\t\t   const gchar *topic);\n\n/** MARKUP *******************************************************************/\n\ngchar *sipe_backend_markup_css_property(const gchar *style,\n\t\t\t\t\tconst gchar *option);\ngchar *sipe_backend_markup_strip_html(const gchar *html);\n\n/** MEDIA ********************************************************************/\n\ntypedef enum {\n\t/* This client is the one who invites other participant to the call. */\n\tSIPE_MEDIA_CALL_INITIATOR = 1,\n\t/* Don't show any user interface elements for the call. */\n\tSIPE_MEDIA_CALL_NO_UI = 2\n} SipeMediaCallFlags;\n\ntypedef enum {\n\tSIPE_ICE_NO_ICE,\n\tSIPE_ICE_DRAFT_6,\n\tSIPE_ICE_RFC_5245\n} SipeIceVersion;\n\ntypedef enum {\n\tSIPE_CANDIDATE_TYPE_ANY,\n\tSIPE_CANDIDATE_TYPE_HOST,\n\tSIPE_CANDIDATE_TYPE_RELAY,\n\tSIPE_CANDIDATE_TYPE_SRFLX,\n\tSIPE_CANDIDATE_TYPE_PRFLX\n} SipeCandidateType;\n\ntypedef enum {\n\tSIPE_COMPONENT_NONE = 0,\n\tSIPE_COMPONENT_RTP  = 1,\n\tSIPE_COMPONENT_RTCP = 2\n} SipeComponentType;\n\ntypedef enum {\n\tSIPE_MEDIA_AUDIO,\n\tSIPE_MEDIA_VIDEO,\n\tSIPE_MEDIA_APPLICATION\n} SipeMediaType;\n\ntypedef enum {\n\tSIPE_NETWORK_PROTOCOL_UDP,\n\tSIPE_NETWORK_PROTOCOL_TCP_ACTIVE,\n\tSIPE_NETWORK_PROTOCOL_TCP_PASSIVE,\n\tSIPE_NETWORK_PROTOCOL_TCP_SO,\n} SipeNetworkProtocol;\n\ntypedef enum {\n\tSIPE_ENCRYPTION_POLICY_REJECTED,\n\tSIPE_ENCRYPTION_POLICY_OPTIONAL,\n\tSIPE_ENCRYPTION_POLICY_REQUIRED,\n\tSIPE_ENCRYPTION_POLICY_OBEY_SERVER\n} SipeEncryptionPolicy;\n\nstruct sipe_media_call;\nstruct sipe_backend_media;\nstruct sipe_backend_codec;\nstruct sipe_backend_candidate;\nstruct sipe_backend_media_stream;\nstruct sipe_backend_media_relays;\n\nstruct ssrc_range {\n\tguint32 begin;\n\tguint32 end;\n};\n\nstruct sipe_media_stream {\n\tstruct sipe_backend_media_stream *backend_private;\n\n\tstruct sipe_media_call *call;\n\tgchar *id;\n\tstruct ssrc_range *ssrc_range;\n\tguint32 media_source_id;\n\n\tvoid (*candidate_pairs_established_cb)(struct sipe_media_stream *);\n\tvoid (*read_cb)(struct sipe_media_stream *);\n\tvoid (*writable_cb)(struct sipe_media_stream *);\n\tvoid (*mute_cb)(struct sipe_media_stream *, gboolean is_muted);\n};\n\nstruct sipe_media_call {\n\tstruct sipe_backend_media *backend_private;\n\n\tgchar *with;\n\n\tvoid (*stream_initialized_cb)(struct sipe_media_call *,\n\t\t\t\t      struct sipe_media_stream *);\n\tvoid (*media_end_cb)(struct sipe_media_call *);\n\tvoid (*call_accept_cb)(struct sipe_media_call *, gboolean local);\n\tvoid (*call_reject_cb)(struct sipe_media_call *, gboolean local);\n\tvoid (*call_hold_cb)  (struct sipe_media_call *, gboolean local,\n\t\t\t       gboolean state);\n\tvoid (*call_hangup_cb)(struct sipe_media_call *, gboolean local);\n\tvoid (*error_cb)(struct sipe_media_call *, gchar *message);\n};\n\nstruct sipe_media_relay {\n\tgchar\t\t      *hostname;\n\tguint\t\t       udp_port;\n\tguint\t\t       tcp_port;\n\tstruct sipe_dns_query *dns_query;\n};\n\n/* Media handling */\nstruct sipe_backend_media *sipe_backend_media_new(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t  struct sipe_media_call *call,\n\t\t\t\t\t\t  const gchar *participant,\n\t\t\t\t\t\t  SipeMediaCallFlags flags);\nvoid sipe_backend_media_free(struct sipe_backend_media *media);\n\nvoid sipe_backend_media_set_cname(struct sipe_backend_media *media, gchar *cname);\n\nstruct sipe_backend_media_relays * sipe_backend_media_relays_convert(GSList *media_relays,\n\t\t\t\t\t\t\t\t     gchar *username,\n\t\t\t\t\t\t\t\t     gchar *password);\nvoid sipe_backend_media_relays_free(struct sipe_backend_media_relays *media_relays);\n\nstruct sipe_backend_media_stream *sipe_backend_media_add_stream(struct sipe_media_stream *stream,\n\t\t\t\t\t\t\t  SipeMediaType type,\n\t\t\t\t\t\t\t  SipeIceVersion ice_version,\n\t\t\t\t\t\t\t  gboolean initiator,\n\t\t\t\t\t\t\t  struct sipe_backend_media_relays *media_relays,\n\t\t\t\t\t\t\t  guint min_port, guint max_port);\nvoid sipe_backend_media_add_remote_candidates(struct sipe_media_call *media,\n\t\t\t\t\t      struct sipe_media_stream *stream,\n\t\t\t\t\t      GList *candidates);\ngboolean sipe_backend_media_is_initiator(struct sipe_media_call *media,\n\t\t\t\t\t struct sipe_media_stream *stream);\ngboolean sipe_backend_media_accepted(struct sipe_backend_media *media);\ngboolean sipe_backend_stream_initialized(struct sipe_media_call *media,\n\t\t\t\t\t struct sipe_media_stream *stream);\nvoid sipe_backend_media_set_encryption_keys(struct sipe_media_call *media,\n\t\t\t\t\t    struct sipe_media_stream *stream,\n\t\t\t\t\t    const guchar *encryption_key,\n\t\t\t\t\t    const guchar *decryption_key);\nvoid sipe_backend_media_set_require_encryption(struct sipe_media_call *media,\n\t\t\t\t\t       struct sipe_media_stream *stream,\n\t\t\t\t\t       const gboolean require_encryption);\n\n/* Stream handling */\nvoid sipe_backend_stream_hold(struct sipe_media_call *media,\n\t\t\t      struct sipe_media_stream *stream,\n\t\t\t      gboolean local);\nvoid sipe_backend_stream_unhold(struct sipe_media_call *media,\n\t\t\t\tstruct sipe_media_stream *stream,\n\t\t\t\tgboolean local);\ngboolean sipe_backend_stream_is_held(struct sipe_media_stream *stream);\n\nGList *sipe_backend_media_stream_get_active_local_candidates(struct sipe_media_stream *stream);\nGList *sipe_backend_media_stream_get_active_remote_candidates(struct sipe_media_stream *stream);\n\ngssize sipe_backend_media_stream_read(struct sipe_media_stream *stream,\n\t\t\t\t     guint8 *buffer, gsize len);\ngssize sipe_backend_media_stream_write(struct sipe_media_stream *stream,\n\t\t\t\t       guint8 *buffer, gsize len);\n\nvoid sipe_backend_media_stream_end(struct sipe_media_call *media,\n\t\t\t\t   struct sipe_media_stream *stream);\nvoid sipe_backend_media_stream_free(struct sipe_backend_media_stream *stream);\n\n/* Codec handling */\nstruct sipe_backend_codec *sipe_backend_codec_new(int id,\n\t\t\t\t\t\t  const char *name,\n\t\t\t\t\t\t  SipeMediaType type,\n\t\t\t\t\t\t  guint clock_rate,\n\t\t\t\t\t\t  guint channels);\nvoid sipe_backend_codec_free(struct sipe_backend_codec *codec);\nint sipe_backend_codec_get_id(struct sipe_backend_codec *codec);\n/**\n * @return codec name. Will be g_free'd() by the core.\n */\ngchar *sipe_backend_codec_get_name(struct sipe_backend_codec *codec);\nguint sipe_backend_codec_get_clock_rate(struct sipe_backend_codec *codec);\nvoid sipe_backend_codec_add_optional_parameter(struct sipe_backend_codec *codec,\n\t\t\t\t\t       const gchar *name,\n\t\t\t\t\t       const gchar *value);\nGList *sipe_backend_codec_get_optional_parameters(struct sipe_backend_codec *codec);\ngboolean sipe_backend_set_remote_codecs(struct sipe_media_call *media,\n\t\t\t\t\tstruct sipe_media_stream *stream,\n\t\t\t\t\tGList *codecs);\nGList* sipe_backend_get_local_codecs(struct sipe_media_call *media,\n\t\t\t\t     struct sipe_media_stream *stream);\n\n/* Candidate handling */\nstruct sipe_backend_candidate * sipe_backend_candidate_new(const gchar *foundation,\n\t\t\t\t\t\t\t   SipeComponentType component,\n\t\t\t\t\t\t\t   SipeCandidateType type,\n\t\t\t\t\t\t\t   SipeNetworkProtocol proto,\n\t\t\t\t\t\t\t   const gchar *ip, guint port,\n\t\t\t\t\t\t\t   const gchar *username,\n\t\t\t\t\t\t\t   const gchar *password);\nvoid sipe_backend_candidate_free(struct sipe_backend_candidate *candidate);\n/**\n * @return user name. Will be g_free'd() by the core.\n */\ngchar *sipe_backend_candidate_get_username(struct sipe_backend_candidate *candidate);\n/**\n * @return password. Will be g_free'd() by the core.\n */\ngchar *sipe_backend_candidate_get_password(struct sipe_backend_candidate *candidate);\n/**\n * @return foundation. Will be g_free'd() by the core.\n */\ngchar *sipe_backend_candidate_get_foundation(struct sipe_backend_candidate *candidate);\n/**\n * @return IP address string. Will be g_free'd() by the core.\n */\ngchar *sipe_backend_candidate_get_ip(struct sipe_backend_candidate *candidate);\nguint sipe_backend_candidate_get_port(struct sipe_backend_candidate *candidate);\n/**\n * @return IP address string. Will be g_free'd() by the core.\n */\ngchar *sipe_backend_candidate_get_base_ip(struct sipe_backend_candidate *candidate);\nguint sipe_backend_candidate_get_base_port(struct sipe_backend_candidate *candidate);\nguint32 sipe_backend_candidate_get_priority(struct sipe_backend_candidate *candidate);\nvoid sipe_backend_candidate_set_priority(struct sipe_backend_candidate *candidate, guint32 priority);\nSipeComponentType sipe_backend_candidate_get_component_type(struct sipe_backend_candidate *candidate);\nSipeCandidateType sipe_backend_candidate_get_type(struct sipe_backend_candidate *candidate);\nSipeNetworkProtocol sipe_backend_candidate_get_protocol(struct sipe_backend_candidate *candidate);\nGList* sipe_backend_get_local_candidates(struct sipe_media_call *media,\n\t\t\t\t\t struct sipe_media_stream *stream);\nvoid sipe_backend_media_accept(struct sipe_backend_media *media, gboolean local);\nvoid sipe_backend_media_hangup(struct sipe_backend_media *media, gboolean local);\nvoid sipe_backend_media_reject(struct sipe_backend_media *media, gboolean local);\n\n/** NETWORK ******************************************************************/\n\nstruct sipe_backend_listendata;\n\ntypedef void (*sipe_listen_start_cb)(unsigned short port, gpointer data);\ntypedef void (*sipe_client_connected_cb)(struct sipe_backend_fd *fd, gpointer data);\n\nstruct sipe_backend_listendata *\nsipe_backend_network_listen_range(unsigned short port_min,\n\t\t\t\t  unsigned short port_max,\n\t\t\t\t  sipe_listen_start_cb listen_cb,\n\t\t\t\t  sipe_client_connected_cb connect_cb,\n\t\t\t\t  gpointer data);\nvoid sipe_backend_network_listen_cancel(struct sipe_backend_listendata *ldata);\n\nstruct sipe_backend_fd * sipe_backend_fd_from_int(int fd);\ngboolean sipe_backend_fd_is_valid(struct sipe_backend_fd *fd);\nvoid sipe_backend_fd_free(struct sipe_backend_fd *fd);\n\n/** NOTIFICATIONS *************************************************************/\n\nvoid sipe_backend_notify_message_error(struct sipe_core_public *sipe_public,\n\t\t\t\t       struct sipe_backend_chat_session *backend_session,\n\t\t\t\t       const gchar *who,\n\t\t\t\t       const gchar *message);\nvoid sipe_backend_notify_message_info(struct sipe_core_public *sipe_public,\n\t\t\t\t      struct sipe_backend_chat_session *backend_session,\n\t\t\t\t      const gchar *who,\n\t\t\t\t      const gchar *message);\n\n/**\n * @param msg  error message. Maybe @NULL\n */\nvoid sipe_backend_notify_error(struct sipe_core_public *sipe_public,\n\t\t\t       const gchar *title,\n\t\t\t       const gchar *msg);\n\n/** SCHEDULE *****************************************************************/\n\ngpointer sipe_backend_schedule_seconds(struct sipe_core_public *sipe_public,\n\t\t\t\t       guint timeout,\n\t\t\t\t       gpointer data);\ngpointer sipe_backend_schedule_mseconds(struct sipe_core_public *sipe_public,\n\t\t\t\t\tguint timeout,\n\t\t\t\t\tgpointer data);\nvoid sipe_backend_schedule_cancel(struct sipe_core_public *sipe_public,\n\t\t\t\t  gpointer data);\n\n/** SEARCH *******************************************************************/\n\nstruct sipe_backend_search_results;\nstruct sipe_backend_search_token;\n\nvoid sipe_backend_search_failed(struct sipe_core_public *sipe_public,\n\t\t\t\tstruct sipe_backend_search_token *token,\n\t\t\t\tconst gchar *msg);\nstruct sipe_backend_search_results *sipe_backend_search_results_start(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t\t      struct sipe_backend_search_token *token);\nvoid sipe_backend_search_results_add(struct sipe_core_public *sipe_public,\n\t\t\t\t     struct sipe_backend_search_results *results,\n\t\t\t\t     const gchar *uri,\n\t\t\t\t     const gchar *name,\n\t\t\t\t     const gchar *company,\n\t\t\t\t     const gchar *country,\n\t\t\t\t     const gchar *email);\nvoid sipe_backend_search_results_finalize(struct sipe_core_public *sipe_public,\n\t\t\t\t\t  struct sipe_backend_search_results *results,\n\t\t\t\t\t  const gchar *description,\n\t\t\t\t\t  gboolean more);\n\n/** SETTINGS *****************************************************************/\n\ntypedef enum {\n  SIPE_SETTING_EMAIL_URL = 0,\n  SIPE_SETTING_EMAIL_LOGIN,\n  SIPE_SETTING_EMAIL_PASSWORD,\n  SIPE_SETTING_GROUPCHAT_USER,\n  SIPE_SETTING_RDP_CLIENT,\n  SIPE_SETTING_USER_AGENT,\n  SIPE_SETTING_LAST\n} sipe_setting;\nconst gchar *sipe_backend_setting(struct sipe_core_public *sipe_public,\n\t\t\t\t  sipe_setting type);\n\n/** STATUS *******************************************************************/\n\nguint sipe_backend_status(struct sipe_core_public *sipe_public);\ngboolean sipe_backend_status_changed(struct sipe_core_public *sipe_public,\n\t\t\t\t     guint activity,\n\t\t\t\t     const gchar *message);\n\n/**\n * Update user client with new status and note received from server\n *\n * NOTE: this must *NOT* trigger a call to @c sipe_core_status_set()!\n *\n * @param sipe_public   The handle representing the protocol instance\n * @param activity      New activity\n * @param message       New note text\n */\nvoid sipe_backend_status_and_note(struct sipe_core_public *sipe_public,\n\t\t\t\t  guint activity,\n\t\t\t\t  const gchar *message);\n\n/** TRANSPORT ****************************************************************/\n\ntypedef void transport_connected_cb(struct sipe_transport_connection *conn);\ntypedef void transport_input_cb(struct sipe_transport_connection *conn);\ntypedef void transport_error_cb(struct sipe_transport_connection *conn,\n\t\t\t\tconst gchar *msg);\n\ntypedef struct {\n\tguint type;\n\tconst gchar *server_name;\n\tguint server_port;\n\tgpointer user_data;\n\ttransport_connected_cb *connected;\n\ttransport_input_cb *input;\n\ttransport_error_cb *error;\n} sipe_connect_setup;\nstruct sipe_transport_connection *sipe_backend_transport_connect(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t\t const sipe_connect_setup *setup);\nvoid sipe_backend_transport_disconnect(struct sipe_transport_connection *conn);\ngchar *sipe_backend_transport_ip_address(struct sipe_transport_connection *conn);\nvoid sipe_backend_transport_message(struct sipe_transport_connection *conn,\n\t\t\t\t    const gchar *buffer);\nvoid sipe_backend_transport_flush(struct sipe_transport_connection *conn);\n\n/** USER *********************************************************************/\n\nvoid sipe_backend_user_feedback_typing(struct sipe_core_public *sipe_public,\n\t\t\t\t       const gchar *from);\nvoid sipe_backend_user_feedback_typing_stop(struct sipe_core_public *sipe_public,\n\t\t\t\t\t    const gchar *from);\n\n/**\n * Present a query that is to be accepted or declined by the user\n *\n * @param sipe_public   The handle representing the protocol instance\n * @param message       Text of the query to be shown to user\n * @param accept_label  Label to be displayed on UI control that accepts query\n * @param decline_label Label to be displayed on UI control that declines query.\n *                      When @c NULL, the control will not be shown.\n * @param key           Opaque handle uniquely identifying the query. Backend\n *                      should store it for the case SIPE core requests the\n *                      query to be closed prematurely.\n */\nvoid sipe_backend_user_ask(struct sipe_core_public *sipe_public,\n\t\t\t   const gchar *message,\n\t\t\t   const gchar *accept_label,\n\t\t\t   const gchar *decline_label,\n\t\t\t   gpointer key);\n\n/**\n * Present a set of options to the user to choose from.\n *\n * @param sipe_public (in) The handle representing the protocol instance\n * @param message     (in) Text message to be shown to the user\n * @param choices     (in) List of choice options\n * @param key         (in) Opaque handle uniquely identifying the query. Backend\n *                    should store it for the case SIPE core requests the query\n *                    to be closed prematurely.\n */\nvoid sipe_backend_user_ask_choice(struct sipe_core_public *sipe_public,\n\t\t\t\t  const gchar *message,\n\t\t\t\t  GSList *choices,\n\t\t\t\t  gpointer key);\n\n/**\n * Closes the pending user query\n *\n * @param key Opaque handle uniquely identifying the query.\n */\nvoid sipe_backend_user_close_ask(gpointer key);\n\n/** BUDDIES ******************************************************************/\n\n/*\n * sipe_backend_buddy_get/set_string(): properties a buddy can have\n * sipe_backend_buddy_info_add():       mapped, e.g. to a string label\n */\ntypedef enum\n{\n\tSIPE_BUDDY_INFO_DISPLAY_NAME = 0,\n\tSIPE_BUDDY_INFO_JOB_TITLE,\n\tSIPE_BUDDY_INFO_CITY,\n\tSIPE_BUDDY_INFO_STATE,\n\tSIPE_BUDDY_INFO_OFFICE,\n\tSIPE_BUDDY_INFO_DEPARTMENT,\n\tSIPE_BUDDY_INFO_COUNTRY,\n\tSIPE_BUDDY_INFO_WORK_PHONE,\n\tSIPE_BUDDY_INFO_WORK_PHONE_DISPLAY,\n\tSIPE_BUDDY_INFO_COMPANY,\n\tSIPE_BUDDY_INFO_EMAIL,\n\tSIPE_BUDDY_INFO_SITE,\n\tSIPE_BUDDY_INFO_ZIPCODE,\n\tSIPE_BUDDY_INFO_STREET,\n\tSIPE_BUDDY_INFO_MOBILE_PHONE,\n\tSIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY,\n\tSIPE_BUDDY_INFO_HOME_PHONE,\n\tSIPE_BUDDY_INFO_HOME_PHONE_DISPLAY,\n\tSIPE_BUDDY_INFO_OTHER_PHONE,\n\tSIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY,\n\tSIPE_BUDDY_INFO_CUSTOM1_PHONE,\n\tSIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY,\n\tSIPE_BUDDY_INFO_ALIAS,  /* only for sipe_backend_buddy_info_add() */\n\tSIPE_BUDDY_INFO_DEVICE, /* only for sipe_backend_buddy_info_add() */\n} sipe_buddy_info_fields;\n\n/* Opaque token */\ntypedef void* sipe_backend_buddy;\n\n/**\n * Find a buddy in the given group of the buddy list, or anywhere on the\n * list if @group_name is empty\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param buddy_name The name of the buddy\n * @param group_name The name of the group to look in, or NULL for any group\n * @return opaque handle to the buddy, or NULL if no buddy found\n */\nsipe_backend_buddy sipe_backend_buddy_find(struct sipe_core_public *sipe_public,\n\t\t\t\t\t   const gchar *buddy_name,\n\t\t\t\t\t   const gchar *group_name);\n\n/*\n * Find all named buddies in the given group of the buddy list, or anywhere on the\n * list if @group_name is empty; or all buddies if @name is empty\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param name The name of the buddy\n * @param group_name The name of the group to look in, or NULL for any group\n * @return GSList of opaque handles to the buddies\n */\nGSList* sipe_backend_buddy_find_all(struct sipe_core_public *sipe_public,\n\t\t\t\t    const gchar *buddy_name,\n\t\t\t\t    const gchar *group_name);\n\n/**\n * Gets the name of a contact.\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param who The opaque handle to the contact as found by find_buddy\n * @return The name. Must be freed.\n */\ngchar* sipe_backend_buddy_get_name(struct sipe_core_public *sipe_public,\n\t\t\t\t   const sipe_backend_buddy who);\n\n/**\n * Gets the alias for a contact.\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param who The opaque handle to the contact as found by find_buddy\n * @return The alias. Must be gfree'd.\n */\ngchar* sipe_backend_buddy_get_alias(struct sipe_core_public *sipe_public,\n\t\t\t\t    const sipe_backend_buddy who);\n\n/**\n * Gets the server alias for a contact.\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param who The opaque handle to the contact as found by find_buddy\n * @return The alias. Must be freed.\n */\ngchar* sipe_backend_buddy_get_server_alias(struct sipe_core_public *sipe_public,\n\t\t\t\t\t   const sipe_backend_buddy who);\n\n/**\n * Gets the local alias for a contact\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param uri         the budyy name\n *\n * @return the alias. Must be @g_free()'d.\n */\ngchar *sipe_backend_buddy_get_local_alias(struct sipe_core_public *sipe_public,\n\t\t\t\t\t  const sipe_backend_buddy who);\n\n/**\n * Gets the name of the group a contact belongs to.\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param who The opaque handle to the contact as found by find_buddy\n * @return The name. Must be freed.\n */\ngchar* sipe_backend_buddy_get_group_name(struct sipe_core_public *sipe_public,\n\t\t\t\t\t const sipe_backend_buddy who);\n\n/**\n * Called to retrieve a buddy-specific setting.\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param buddy The handle representing the buddy\n * @param key The name of the setting\n * @return The value of the setting. Must be freed.\n */\ngchar* sipe_backend_buddy_get_string(struct sipe_core_public *sipe_public,\n\t\t\t\t     sipe_backend_buddy buddy,\n\t\t\t\t     const sipe_buddy_info_fields key);\n\n/**\n * Called to set a buddy-specific setting.\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param buddy The handle representing the buddy\n * @param key The name of the setting\n * @param val The value to set\n */\nvoid sipe_backend_buddy_set_string(struct sipe_core_public *sipe_public,\n\t\t\t\t   sipe_backend_buddy buddy,\n\t\t\t\t   const sipe_buddy_info_fields key,\n\t\t\t\t   const gchar *val);\n\n/**\n * Called after one ore more buddy-specific settings have been updated.\n *\n * Can be used by the backend to trigger an UI update event\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param uri         SIP URI of the contact\n */\nvoid sipe_backend_buddy_refresh_properties(struct sipe_core_public *sipe_public,\n\t\t\t\t\t   const gchar *uri);\n\n/**\n * Get the status token for a contact\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param uri         SIP URI of the contact\n *\n * @return activity\n */\nguint sipe_backend_buddy_get_status(struct sipe_core_public *sipe_public,\n\t\t\t\t    const gchar *uri);\n\n/**\n * Sets the alias for a contact.\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param who The opaque handle to the contact as found by find_buddy\n * @param alias The location where the alias will be put\n * case. FALSE if the buddy was not found. The value of alias will not be changed.\n */\nvoid sipe_backend_buddy_set_alias(struct sipe_core_public *sipe_public,\n\t\t\t\t  const sipe_backend_buddy who,\n\t\t\t\t  const gchar *alias);\n\n/**\n * Sets the server alias for a contact.\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param who The opaque handle to the contact as found by find_buddy\n * @param alias The server alias of the contact\n */\nvoid sipe_backend_buddy_set_server_alias(struct sipe_core_public *sipe_public,\n\t\t\t\t\t const sipe_backend_buddy who,\n\t\t\t\t\t const gchar *alias);\n\n/**\n * Start processing buddy list\n *\n * Will be called every time we receive a buddy list in roaming contacts\n *\n * @param sipe_public The handle representing the protocol instance making the call\n */\nvoid sipe_backend_buddy_list_processing_start(struct sipe_core_public *sipe_public);\n\n/**\n * Finished processing buddy list\n *\n * Will be called every time we receive a buddy list in roaming contacts\n *\n * @param sipe_public The handle representing the protocol instance making the call\n */\nvoid sipe_backend_buddy_list_processing_finish(struct sipe_core_public *sipe_public);\n\n/**\n * Add a contact to the buddy list\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param name The name of the contact\n * @param alias The alias of the contact\n * @param groupname The name of the group to add this contact to\n * @return A handle to the newly created buddy\n */\nsipe_backend_buddy sipe_backend_buddy_add(struct sipe_core_public *sipe_public,\n\t\t\t\t\t  const gchar *name,\n\t\t\t\t\t  const gchar *alias,\n\t\t\t\t\t  const gchar *groupname);\n\n/**\n * Remove a contact from the buddy list\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param who The opaque handle to the contact as found by find_buddy\n */\nvoid sipe_backend_buddy_remove(struct sipe_core_public *sipe_public,\n\t\t\t       const sipe_backend_buddy who);\n\n/**\n * Notifies the user that a remote user has wants to add the local user to his\n * or her buddy list and requires authorization to do so.\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param who The name of the user that added this account\n * @param alias The optional alias of the remote user\n * @param on_list True if the user is already in our list\n * @param auth_cb The callback called when the local user accepts\n * @param deny_cb The callback called when the local user rejects\n * @param data Data to be passed back to the above callbacks\n */\ntypedef void (*sipe_backend_buddy_request_authorization_cb)(void *);\n\nvoid sipe_backend_buddy_request_add(struct sipe_core_public *sipe_public,\n\t\t\t\t    const gchar *who,\n\t\t\t\t    const gchar *alias);\n\nvoid sipe_backend_buddy_request_authorization(struct sipe_core_public *sipe_public,\n\t\t\t\t\t      const gchar *who,\n\t\t\t\t\t      const gchar *alias,\n\t\t\t\t\t      gboolean on_list,\n\t\t\t\t\t      sipe_backend_buddy_request_authorization_cb auth_cb,\n\t\t\t\t\t      sipe_backend_buddy_request_authorization_cb deny_cb,\n\t\t\t\t\t      gpointer data);\n\ngboolean sipe_backend_buddy_is_blocked(struct sipe_core_public *sipe_public,\n\t\t\t\t       const gchar *who);\n\nvoid sipe_backend_buddy_set_blocked_status(struct sipe_core_public *sipe_public,\n\t\t\t\t\t   const gchar *who,\n\t\t\t\t\t   gboolean blocked);\n\n/**\n * Set the buddy status\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param who The name of the user whose status should be updated\n * @param activity New activity\n * @param last_active Seconds since epoch when user entered idle state.\n *        May be @c 0 if unknown.\n */\nvoid sipe_backend_buddy_set_status(struct sipe_core_public *sipe_public,\n\t\t\t\t   const gchar *who,\n\t\t\t\t   guint activity,\n\t                           time_t last_active);\n\n/**\n * Checks whether backend has a capability to use buddy photos. If this function\n * returns @c FALSE, SIPE core will not attempt to download the photos from\n * server to save bandwidth.\n *\n * @return @c TRUE if backend is photo capable, otherwise @FALSE\n */\ngboolean sipe_backend_uses_photo(void);\n\n/**\n * Gives backend a photo image associated with a SIP URI. Backend has ownership\n * of the data and must free it when not needed.\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param who The name of the user whose photo is being set\n * @param image_data The photo image data, must be g_free()'d by backend\n * @param image_len Size of the image in Bytes\n * @param photo_hash A data checksum provided by the server\n */\nvoid sipe_backend_buddy_set_photo(struct sipe_core_public *sipe_public,\n\t\t\t\t  const gchar *who,\n\t\t\t\t  gpointer image_data,\n\t\t\t\t  gsize image_len,\n\t\t\t\t  const gchar *photo_hash);\n\n/**\n * Retrieves a photo hash stored together with image data by\n * @c sipe_backend_buddy_set_photo. Value is used by the core to detect photo\n * file changes on server.\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param who The name of the user whose photo hash to retrieve\n * @return a photo hash (may be NULL)\n */\nconst gchar *sipe_backend_buddy_get_photo_hash(struct sipe_core_public *sipe_public,\n\t\t\t\t\t       const gchar *who);\n\n/**\n * Called when a new internal group is about to be added. If this returns FALSE,\n * the group will not be added.\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param group_name  The group being added\n * @return TRUE if everything is ok, FALSE if the group should not be added\n */\ngboolean sipe_backend_buddy_group_add(struct sipe_core_public *sipe_public,\n\t\t\t\t      const gchar *group_name);\n\n/**\n * Called when a new internal group has been renamed\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param old_name old name of the group\n * @param new_name new name of the group\n * @return TRUE if the group was found and renamed\n */\ngboolean sipe_backend_buddy_group_rename(struct sipe_core_public *sipe_public,\n\t\t\t\t\t const gchar *old_name,\n\t\t\t\t\t const gchar *new_name);\n\n/**\n * Called when a new internal group should be deleted\n *\n * NOTE: this will only be called on empty groups.\n *\n * @param sipe_public The handle representing the protocol instance making the call\n * @param group_name  The group that should be removed\n */\nvoid sipe_backend_buddy_group_remove(struct sipe_core_public *sipe_public,\n\t\t\t\t     const gchar *group_name);\n\n/**\n * Present requested buddy information to the user\n */\nstruct sipe_backend_buddy_info;\nstruct sipe_backend_buddy_info *sipe_backend_buddy_info_start(struct sipe_core_public *sipe_public);\nvoid sipe_backend_buddy_info_add(struct sipe_core_public *sipe_public,\n\t\t\t\t struct sipe_backend_buddy_info *info,\n\t\t\t\t sipe_buddy_info_fields key,\n\t\t\t\t const gchar *value);\nvoid sipe_backend_buddy_info_break(struct sipe_core_public *sipe_public,\n\t\t\t\t   struct sipe_backend_buddy_info *info);\nvoid sipe_backend_buddy_info_finalize(struct sipe_core_public *sipe_public,\n\t\t\t\t      struct sipe_backend_buddy_info *info,\n\t\t\t\t      const gchar *uri);\n\nstruct sipe_backend_buddy_tooltip;\nvoid sipe_backend_buddy_tooltip_add(struct sipe_core_public *sipe_public,\n\t\t\t\t    struct sipe_backend_buddy_tooltip *tooltip,\n\t\t\t\t    const gchar *description,\n\t\t\t\t    const gchar *value);\n\n/**\n * Buddy menu creation\n */\nenum sipe_buddy_menu_type {\n\tSIPE_BUDDY_MENU_MAKE_CHAT_LEADER = 0,\n\tSIPE_BUDDY_MENU_REMOVE_FROM_CHAT,\n\tSIPE_BUDDY_MENU_INVITE_TO_CHAT,\n\tSIPE_BUDDY_MENU_NEW_CHAT,\n\tSIPE_BUDDY_MENU_MAKE_CALL,\n\tSIPE_BUDDY_MENU_SEND_EMAIL,\n\tSIPE_BUDDY_MENU_ACCESS_LEVEL_HELP,\n\tSIPE_BUDDY_MENU_CHANGE_ACCESS_LEVEL,\n\tSIPE_BUDDY_MENU_ADD_NEW_DOMAIN,\n\tSIPE_BUDDY_MENU_SHARE_DESKTOP,\n\tSIPE_BUDDY_MENU_GIVE_DESKTOP_CONTROL,\n\tSIPE_BUDDY_MENU_TAKE_DESKTOP_CONTROL,\n\tSIPE_BUDDY_MENU_TYPES\n};\n\nstruct sipe_backend_buddy_menu *sipe_backend_buddy_menu_start(struct sipe_core_public *sipe_public);\nstruct sipe_backend_buddy_menu *sipe_backend_buddy_menu_add(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t    struct sipe_backend_buddy_menu *menu,\n\t\t\t\t\t\t\t    const gchar *label,\n\t\t\t\t\t\t\t    enum sipe_buddy_menu_type type,\n\t\t\t\t\t\t\t    gpointer parameter);\nstruct sipe_backend_buddy_menu *sipe_backend_buddy_menu_separator(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t\t  struct sipe_backend_buddy_menu *menu,\n\t\t\t\t\t\t\t\t  const gchar *label);\nstruct sipe_backend_buddy_menu *sipe_backend_buddy_sub_menu_add(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t\tstruct sipe_backend_buddy_menu *menu,\n\t\t\t\t\t\t\t\tconst gchar *label,\n\t\t\t\t\t\t\t\tstruct sipe_backend_buddy_menu *sub);\n\nSipeEncryptionPolicy sipe_backend_media_get_encryption_policy(struct sipe_core_public *sipe_public);\n\n#ifdef __cplusplus\n}\n#endif\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/api/sipe-common.h",
    "content": "/**\n * @file sipe-common.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2017 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/*\n * Everything in here must be independent of any other header file!\n *\n * I.e. it must be possible to include this header\n * in any module without requiring any other #include.\n */\n\n#ifdef __GNUC__\n#define SIPE_UNUSED_PARAMETER __attribute__((unused))\n#else\n#define SIPE_UNUSED_PARAMETER\n#endif\n\n#if defined(__GNUC__) && (__GNUC__ >= 7)\n#define SIPE_FALLTHROUGH __attribute__((fallthrough));\n#else\n#define SIPE_FALLTHROUGH\n#endif\n\n/* in order to remove internal.h dependency in mingw builds */\n#ifndef G_GNUC_NULL_TERMINATED\n#\tif    defined(__GNUC__) && (__GNUC__ >= 4)\n#\t\tdefine G_GNUC_NULL_TERMINATED __attribute__((__sentinel__))\n#\telse\n#\t\tdefine G_GNUC_NULL_TERMINATED\n#\tendif\n#endif\n\n#ifdef _MSC_VER\ntypedef long ssize_t;\n#endif\n"
  },
  {
    "path": "src/api/sipe-core.h",
    "content": "/**\n * @file sipe-core.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/**\n *\n * Backend -> SIPE Core API - functions called by backend code\n *\n ***************** !!! IMPORTANT NOTE FOR BACKEND CODERS !!! *****************\n *\n *            The SIPE core assumes atomicity and is *NOT* thread-safe.\n *\n * It *does not* protect any of its data structures or code paths with locks!\n *\n * In no circumstances it must be interrupted by another thread calling\n * sipe_core_xxx() while the first thread has entered the SIPE core through\n * a sipe_core_xxx() function.\n *\n ***************** !!! IMPORTANT NOTE FOR BACKEND CODERS !!! *****************\n */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * Transport type\n */\n#define SIPE_TRANSPORT_AUTO 0\n#define SIPE_TRANSPORT_TLS  1\n#define\tSIPE_TRANSPORT_TCP  2\n\n/**\n * Transport connection (public part)\n *\n * The receiver in the backend fills \"buffer\". The backend has to zero\n * terminate the buffer before calling the processing function in the core.\n *\n * The processing function in the core can remove content from the buffer.\n * It has to update buffer_used accordingly.\n *\n */\nstruct sipe_transport_connection {\n\tgpointer user_data;\n\tgchar *buffer;\n\tgsize buffer_used;        /* 0 < buffer_used < buffer_length */\n\tgsize buffer_length;      /* read-only */\n\tguint type;               /* read-only */\n\tguint client_port;        /* read-only */\n};\n\n/**\n * Opaque data type for chat session\n */\nstruct sipe_chat_session;\n\n/**\n * File transport (public part)\n */\nstruct sipe_file_transfer {\n\tstruct sipe_backend_file_transfer *backend_private;\n\n\tvoid (* ft_init)(struct sipe_file_transfer *ft, const gchar *filename,\n\t\t\t gsize size, const gchar *who);\n\tvoid (* ft_start)(struct sipe_file_transfer *ft, gsize total_size);\n\tgssize (* ft_read)(struct sipe_file_transfer *ft, guchar **buffer,\n\t\t\t   gsize bytes_remaining, gsize bytes_available);\n\tgssize (* ft_write)(struct sipe_file_transfer *ft, const guchar *buffer,\n\t\t\t    gsize size);\n\tgboolean (* ft_end)(struct sipe_file_transfer *ft);\n\tvoid (* ft_request_denied)(struct sipe_file_transfer *ft);\n\tvoid (* ft_cancelled)(struct sipe_file_transfer *ft);\n};\n\n/**\n * Opaque data type for backend private data.\n * The backend is responsible to allocate and free it.\n */\nstruct sipe_backend_private;\n\n/**\n * SIP transport authentication scheme\n */\n#define SIPE_AUTHENTICATION_TYPE_UNSET     0\n#define SIPE_AUTHENTICATION_TYPE_BASIC     1 /* internal use only */\n#define SIPE_AUTHENTICATION_TYPE_NTLM      2\n#define SIPE_AUTHENTICATION_TYPE_KERBEROS  3\n#define SIPE_AUTHENTICATION_TYPE_NEGOTIATE 4 /* internal use only */\n#define SIPE_AUTHENTICATION_TYPE_TLS_DSK   5\n#define SIPE_AUTHENTICATION_TYPE_AUTOMATIC 6 /* always last */\n\n/**\n * Flags\n */\n/* user disabled calendar information publishing */\n#define SIPE_CORE_FLAG_DONT_PUBLISH    0x00000001\n/* user enabled insecure buddy icon download from web */\n#define SIPE_CORE_FLAG_ALLOW_WEB_PHOTO 0x00000002\n\n#define SIPE_CORE_FLAG_IS(flag)    \\\n\t((sipe_public->flags & SIPE_CORE_FLAG_ ## flag) == SIPE_CORE_FLAG_ ## flag)\n#define SIPE_CORE_FLAG_SET(flag)   \\\n\t(sipe_public->flags |= SIPE_CORE_FLAG_ ## flag)\n#define SIPE_CORE_FLAG_UNSET(flag) \\\n\t(sipe_public->flags &= ~SIPE_CORE_FLAG_ ## flag)\n\n/**\n * Byte length of cryptographic key for call encryption.\n */\n#define SIPE_SRTP_KEY_LEN 30\n\n/**\n * Public part of the Sipe data structure\n *\n * This part contains the information needed by the core and the backend.\n */\nstruct sipe_core_public {\n\t/**\n\t * This points to the private data for the backend.\n\t * The backend is responsible to allocate and free it.\n\t */\n\tstruct sipe_backend_private *backend_private;\n\n\t/* flags (see above) */\n\tguint32 flags;\n\n\t/* user information */\n\tgchar *sip_name;\n\tgchar *sip_domain;\n\n\t/* server information */\n\t/* currently nothing */\n};\n\n/**\n * Initialize & destroy functions for the SIPE core\n * Should be called on loading and unloading of the plugin.\n */\nvoid sipe_core_init(const char *locale_dir);\nvoid sipe_core_destroy(void);\n\n/** Utility functions exported by the core to backends ***********************/\ngboolean sipe_strequal(const gchar *left, const gchar *right);\ngboolean sipe_strcase_equal(const gchar *left, const gchar *right);\n\nGSList *\nsipe_utils_nameval_add(GSList *list, const gchar *name, const gchar *value);\n\nconst gchar *\nsipe_utils_nameval_find(const GSList *list, const gchar *name);\n\nconst gchar *\nsipe_utils_nameval_find_instance(const GSList *list, const gchar *name, int which);\n\nvoid\nsipe_utils_nameval_free(GSList *list);\n\ngchar *sip_uri_from_name(const gchar *name);\ngchar *sip_uri_if_valid(const gchar *string);\n\n/*****************************************************************************/\n\n/**\n * Other functions (need to be sorted once structure becomes clear.\n */\n\n/* Get translated about string. Must be g_free'd(). */\ngchar *sipe_core_about(void);\n\n/* Execute a scheduled action */\nvoid sipe_core_schedule_execute(gpointer data);\n\n/* menu actions */\nvoid sipe_core_update_calendar(struct sipe_core_public *sipe_public);\nvoid sipe_core_reset_status(struct sipe_core_public *sipe_public);\n\n/* access levels */\nvoid sipe_core_change_access_level_from_container(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t  gpointer parameter);\nvoid sipe_core_change_access_level_for_domain(struct sipe_core_public *sipe_public,\n\t\t\t\t\t      const gchar *domain,\n\t\t\t\t\t      guint index);\n\n/**\n * Activity\n *   - core:    maps this to OCS protocol values\n *              maps this to translated descriptions\n *   - backend: maps this to backend status values\n *              backend token string can be used as \"ID\" in protocol\n *\n * This is passed back-and-forth and therefore defined as list, not as enum.\n * Can be used as array index\n */\n#define SIPE_ACTIVITY_UNSET        0\n#define\tSIPE_ACTIVITY_AVAILABLE    1\n#define SIPE_ACTIVITY_ONLINE       2\n#define SIPE_ACTIVITY_INACTIVE     3\n#define SIPE_ACTIVITY_BUSY         4\n#define SIPE_ACTIVITY_BUSYIDLE     5\n#define SIPE_ACTIVITY_DND          6\n#define SIPE_ACTIVITY_BRB          7\n#define SIPE_ACTIVITY_AWAY         8\n#define SIPE_ACTIVITY_LUNCH        9\n#define SIPE_ACTIVITY_INVISIBLE   10\n#define SIPE_ACTIVITY_OFFLINE     11\n#define SIPE_ACTIVITY_ON_PHONE    12\n#define SIPE_ACTIVITY_IN_CONF     13\n#define SIPE_ACTIVITY_IN_MEETING  14\n#define SIPE_ACTIVITY_OOF         15\n#define SIPE_ACTIVITY_URGENT_ONLY 16\n#define SIPE_ACTIVITY_IN_PRES     17\n#define SIPE_ACTIVITY_NUM_TYPES   18 /* use to define array size */\n\nconst gchar *sipe_core_activity_description(guint type);\n\n/* buddy actions */\n/**\n * Get status text for buddy.\n *\n * @param sipe_public Sipe core public data structure.\n * @param uri         SIP URI of the buddy\n * @param activity    activity value for buddy\n * @param status_text backend-specific buddy status text for activity.\n *\n * @return HTML status text for the buddy or NULL. Must be g_free()'d.\n */\ngchar *sipe_core_buddy_status(struct sipe_core_public *sipe_public,\n\t\t\t      const gchar *uri,\n\t\t\t      guint activity,\n\t\t\t      const gchar *status_text);\n\n/**\n * Received new status for buddy.\n *\n * @param sipe_public Sipe core public data structure.\n * @param uri         SIP URI of the buddy\n * @param activity    Activity value for buddy\n * @param last_active Seconds since epoch when buddy entered idle state\n *                    May be @c 0 if unknown or buddy is not idle.\n */\nvoid sipe_core_buddy_got_status(struct sipe_core_public *sipe_public,\n\t\t\t\tconst gchar *uri,\n\t\t\t\tguint activity,\n\t                        time_t last_active);\n\n/**\n * Trigger generation of buddy information label/text pairs\n *\n * @param sipe_public Sipe core public data structure.\n * @param uri         SIP URI of the buddy\n * @param status_text backend-specific buddy status text for ID.\n * @param is_online   backend considers buddy to be online.\n * @param tooltip     opaque backend identifier for tooltip info. This is the\n *                    parameter given to @c sipe_backend_buddy_tooltip_add()\n */\nstruct sipe_backend_buddy_tooltip;\nvoid sipe_core_buddy_tooltip_info(struct sipe_core_public *sipe_public,\n\t\t\t\t  const gchar *uri,\n\t\t\t\t  const gchar *status_name,\n\t\t\t\t  gboolean is_online,\n\t\t\t\t  struct sipe_backend_buddy_tooltip *tooltip);\n\n/**\n * Add a buddy\n *\n * @param sipe_public Sipe core public data structure\n * @param uri         SIP URI of the buddy\n * @param group_name  backend-specific group name\n */\nvoid sipe_core_buddy_add(struct sipe_core_public *sipe_public,\n\t\t\t const gchar *uri,\n\t\t\t const gchar *group_name);\n\n/**\n * Remove a buddy\n *\n * @param sipe_public Sipe core public data structure\n * @param uri         SIP URI of the buddy\n * @param group_name  backend-specific group name\n */\nvoid sipe_core_buddy_remove(struct sipe_core_public *sipe_public,\n\t\t\t    const gchar *uri,\n\t\t\t    const gchar *group_name);\n\nvoid sipe_core_contact_allow_deny(struct sipe_core_public *sipe_public,\n\t\t\t\t  const gchar *who,\n\t\t\t\t  gboolean allow);\nvoid sipe_core_group_set_alias(struct sipe_core_public *sipe_public,\n\t\t\t       const gchar *who,\n\t\t\t       const gchar *alias);\n\n/**\n * Setup core data\n */\nstruct sipe_core_public *sipe_core_allocate(const gchar *signin_name,\n\t\t\t\t\t    gboolean sso,\n\t\t\t\t\t    const gchar *login_account,\n\t\t\t\t\t    const gchar *password,\n\t\t\t\t\t    const gchar *email,\n\t\t\t\t\t    const gchar *email_url,\n\t\t\t\t\t    const gchar **errmsg);\nvoid sipe_core_deallocate(struct sipe_core_public *sipe_public);\n\n/**\n * Check if SIP authentication scheme requires a password\n *\n * NOTE: this can be called *BEFORE* @c sipe_core_allocate()!\n *\n * @param authentication SIP transport authentication type\n * @param sso            TRUE if user selected Single-Sign On\n *\n * @return TRUE if password is required\n */\ngboolean sipe_core_transport_sip_requires_password(guint authentication,\n\t\t\t\t\t\t   gboolean sso);\n\n/**\n * Connect to SIP server\n */\nvoid sipe_core_transport_sip_connect(struct sipe_core_public *sipe_public,\n\t\t\t\t     guint transport,\n\t\t\t\t     guint authentication,\n\t\t\t\t     const gchar *server,\n\t\t\t\t     const gchar *port);\n\n/**\n * Get SIP server host name\n *\n * @param sipe_public Sipe core public data structure\n *\n * @return server host name (may be @c NULL if not fully connected yet)\n */\nconst gchar *sipe_core_transport_sip_server_name(struct sipe_core_public *sipe_public);\n\n/**\n * Get chat ID, f.ex. group chat URI\n */\nconst gchar *sipe_core_chat_id(struct sipe_core_public *sipe_public,\n\t\t\t       struct sipe_chat_session *chat_session);\n\n/**\n * Get type of chat session, e.g. group chat\n */\n#define SIPE_CHAT_TYPE_UNKNOWN    0\n#define SIPE_CHAT_TYPE_MULTIPARTY 1\n#define SIPE_CHAT_TYPE_CONFERENCE 2\n#define SIPE_CHAT_TYPE_GROUPCHAT  3\nguint sipe_core_chat_type(struct sipe_chat_session *chat_session);\n\n/**\n * Invite to chat\n */\nvoid sipe_core_chat_invite(struct sipe_core_public *sipe_public,\n\t\t\t   struct sipe_chat_session *chat_session,\n\t\t\t   const char *name);\n\n/**\n * Rejoin a chat after connection re-establishment\n */\nvoid sipe_core_chat_rejoin(struct sipe_core_public *sipe_public,\n\t\t\t   struct sipe_chat_session *chat_session);\n\n/**\n * Leave a chat\n */\nvoid sipe_core_chat_leave(struct sipe_core_public *sipe_public,\n\t\t\t  struct sipe_chat_session *chat_session);\n\n/**\n * Send message to chat\n */\nvoid sipe_core_chat_send(struct sipe_core_public *sipe_public,\n\t\t\t struct sipe_chat_session *chat_session,\n\t\t\t const char *what);\n\n/**\n * Check chat lock status\n */\ntypedef enum {\n\tSIPE_CHAT_LOCK_STATUS_NOT_ALLOWED = 0,\n\tSIPE_CHAT_LOCK_STATUS_UNLOCKED,\n\tSIPE_CHAT_LOCK_STATUS_LOCKED\n} sipe_chat_lock_status;\nsipe_chat_lock_status sipe_core_chat_lock_status(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t struct sipe_chat_session *chat_session);\n\n/**\n * Lock chat\n */\nvoid sipe_core_chat_modify_lock(struct sipe_core_public *sipe_public,\n\t\t\t\tstruct sipe_chat_session *chat_session,\n\t\t\t\tconst gboolean locked);\n\n/**\n * Create new session with Focus URI\n *\n * @param sipe_public (in) SIPE core data.\n * @param focus_uri (in) focus URI string\n */\nvoid sipe_core_conf_create(struct sipe_core_public *sipe_public,\n\t\t\t   const gchar *focus_uri,\n\t\t\t   const gchar *organizer,\n\t\t\t   const gchar *meeting_id);\n\n/* buddy menu callback: parameter == chat_session */\nvoid sipe_core_conf_make_leader(struct sipe_core_public *sipe_public,\n\t\t\t\tgpointer parameter,\n\t\t\t\tconst gchar *buddy_name);\nvoid sipe_core_conf_remove_from(struct sipe_core_public *sipe_public,\n\t\t\t\tgpointer parameter,\n\t\t\t\tconst gchar *buddy_name);\n\ngchar *\nsipe_core_conf_entry_info(struct sipe_core_public *sipe_public,\n\t\t\t  struct sipe_chat_session *chat_session);\n\ntypedef enum {\n\tSIPE_APPSHARE_ROLE_NONE,\n\tSIPE_APPSHARE_ROLE_VIEWER,\n\tSIPE_APPSHARE_ROLE_PRESENTER\n} sipe_appshare_role;\n\n/**\n * Gets user's application sharing role in given chat session.\n *\n * @param sipe_public (in) SIPE core data.\n * @param chat_session (in) chat session structure\n *\n * @return User's application sharing role.\n */\nsipe_appshare_role\nsipe_core_conf_get_appshare_role(struct sipe_core_public *sipe_public,\n\t\t\t\t struct sipe_chat_session *chat_session);\n\n/* call control (CSTA) */\nvoid sipe_core_buddy_make_call(struct sipe_core_public *sipe_public,\n\t\t\t       const gchar *phone);\n\n/* media */\nvoid sipe_core_media_initiate_call(struct sipe_core_public *sipe_public,\n\t\t\t\t   const char *participant,\n\t\t\t\t   gboolean with_video);\nstruct sipe_media_call;\nstruct sipe_media_stream *\nsipe_core_media_get_stream_by_id(struct sipe_media_call *call, const gchar *id);\n\n/**\n * Called by media backend after a candidate pair for a media stream component\n * has been established.\n *\n * @param stream (in) SIPE media stream data.\n */\nvoid\nsipe_core_media_stream_candidate_pair_established(struct sipe_media_stream *stream);\n\nvoid\nsipe_core_media_stream_readable(struct sipe_media_stream *stream);\n\n/**\n * Called by media backend when a @c SIPE_MEDIA_APPLICATION stream changes its\n * state between writable and unwritable.\n *\n * @param stream (in) SIPE media stream data.\n * @param writable (in) @c TRUE if stream has become writable, otherwise\n *                 @c FALSE.\n */\nvoid\nsipe_core_media_stream_writable(struct sipe_media_stream *stream,\n\t\t\t\tgboolean writable);\n\n/**\n * Called by media backend when @c stream has ended and should be destroyed.\n *\n * @param stream (in) SIPE media stream data.\n */\nvoid\nsipe_core_media_stream_end(struct sipe_media_stream *stream);\n\n/**\n * Connects to a conference call specified by given chat session\n *\n * @param sipe_public (in) SIPE core data.\n * @param chat_session (in) chat session structure\n * @param with_video (in) TRUE if a video call should be created.\n */\nvoid sipe_core_media_connect_conference(struct sipe_core_public *sipe_public,\n\t\t\t\t\tstruct sipe_chat_session *chat_session,\n\t\t\t\t\tgboolean with_video);\n\n/**\n * Retrieves the media call in progress\n *\n * The function checks only for voice and video calls, ignoring other types of\n * data transfers.\n *\n * @param sipe_public (in) SIPE core data.\n *\n * @return @c sipe_media_call structure or @c NULL if call is not in progress.\n */\nstruct sipe_media_call *\nsipe_core_media_get_call(struct sipe_core_public *sipe_public);\n\n/**\n * Initiates a call with given phone number\n *\n * @param sipe_public (in) SIPE core data.\n * @parem phone_number (in) a mobile or landline phone number, i.e. +46123456\n */\nvoid sipe_core_media_phone_call(struct sipe_core_public *sipe_public,\n\t\t\t\tconst gchar *phone_number);\n\n/**\n * Checks voice quality by making a call to the test service\n *\n * @param sipe_public (in) SIPE core data.\n */\nvoid sipe_core_media_test_call(struct sipe_core_public *sipe_public);\n\n/* file transfer */\nstruct sipe_file_transfer *\nsipe_core_ft_create_outgoing(struct sipe_core_public *sipe_public,\n\t\t\t     const gchar *who,\n\t\t\t     const gchar *file);\n\n/* application sharing */\n\n/**\n * Connects to a meeting's presentation\n *\n * @param sipe_public (in) SIPE core data.\n * @param chat_session (in) chat session structure\n * @param user_must_accept (in) @c TRUE if user should be shown accept/decline\n * \t\t\t   dialog before the action can proceed.\n */\nvoid sipe_core_appshare_connect_conference(struct sipe_core_public *sipe_public,\n\t\t\t\t\t   struct sipe_chat_session *chat_session,\n\t\t\t\t\t   gboolean user_must_accept);\n\n/**\n * Starts presenting user's desktop\n *\n * @param sipe_public (in) SIPE core data.\n * @param with (in) SIP URI of the contact to share the desktop with.\n */\nvoid sipe_core_appshare_share_desktop(struct sipe_core_public *sipe_public,\n\t\t\t\t      const gchar *with);\n\n/**\n * Starts presenting user's desktop with a conference call\n *\n * @param sipe_public (in) SIPE core data.\n * @param chat_session (in) chat session structure.\n */\nvoid\nsipe_core_conf_share_desktop(struct sipe_core_public *sipe_public,\n\t\t\t     struct sipe_chat_session *chat_session);\n\n/**\n * Changes the state of remote desktop control on an application sharing call.\n *\n * @param call (in) media call structure.\n * @param enabled (in) @c TRUE to enable remote control, @c FALSE to disable it.\n */\nvoid\nsipe_core_appshare_set_remote_control(struct sipe_media_call *call,\n\t\t\t\t      gboolean enabled);\n\n/**\n * Gets the state of remote desktop control on an application sharing call.\n *\n * @param call (in) media call structure.\n *\n * @return @c TRUE if remote control is enabled, otherwise @c FALSE.\n */\ngboolean\nsipe_core_appshare_get_remote_control(struct sipe_media_call *call);\n\n/* group chat */\ngboolean sipe_core_groupchat_query_rooms(struct sipe_core_public *sipe_public);\nvoid sipe_core_groupchat_join(struct sipe_core_public *sipe_public,\n\t\t\t      const gchar *uri);\n\n/* IM */\nvoid sipe_core_im_send(struct sipe_core_public *sipe_public,\n\t\t       const gchar *who,\n\t\t       const gchar *what);\nvoid sipe_core_im_close(struct sipe_core_public *sipe_public,\n\t\t\tconst gchar *who);\n\n/* user */\nvoid sipe_core_user_feedback_typing(struct sipe_core_public *sipe_public,\n\t\t\t\t    const gchar *to,\n\t\t\t\t    gboolean typing);\n\nvoid sipe_core_user_ask_cb(gpointer key, gboolean accepted);\n\nstatic const guint SIPE_CHOICE_CANCELLED = G_MAXUINT;\n\nvoid sipe_core_user_ask_choice_cb(gpointer key, guint choice_id);\n\n/* groups */\nvoid sipe_core_group_rename(struct sipe_core_public *sipe_public,\n\t\t\t    const gchar *old_name,\n\t\t\t    const gchar *new_name);\n\nvoid sipe_core_group_remove(struct sipe_core_public *sipe_public,\n\t\t\t    const gchar *name);\n\n/* buddies */\nvoid sipe_core_buddy_group(struct sipe_core_public *sipe_public,\n\t\t\t   const gchar *who,\n\t\t\t   const gchar *old_group_name,\n\t\t\t   const gchar *new_group_name);\n\nstruct sipe_backend_search_token;\nvoid sipe_core_buddy_search(struct sipe_core_public *sipe_public,\n\t\t\t    struct sipe_backend_search_token *token,\n\t\t\t    const gchar *given_name,\n\t\t\t    const gchar *surname,\n\t\t\t    const gchar *email,\n\t\t\t    const gchar *sipid,\n\t\t\t    const gchar *company,\n\t\t\t    const gchar *country);\n\nvoid sipe_core_buddy_get_info(struct sipe_core_public *sipe_public,\n\t\t\t      const gchar *who);\n\nvoid sipe_core_buddy_new_chat(struct sipe_core_public *sipe_public,\n\t\t\t      const gchar *who);\nvoid sipe_core_buddy_send_email(struct sipe_core_public *sipe_public,\n\t\t\t\tconst gchar *who);\n\nstruct sipe_backend_buddy_menu;\nstruct sipe_backend_buddy_menu *sipe_core_buddy_create_menu(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t    const gchar *buddy_name,\n\t\t\t\t\t\t\t    struct sipe_backend_buddy_menu *menu);\n\nvoid sipe_core_buddy_menu_free(struct sipe_core_public *sipe_public);\n\n/**\n * User/Machine has changed the user status\n *\n * NOTE: must *NEVER* be triggered by @c sipe_backend_status_and_note()!\n *\n * @param sipe_public   The handle representing the protocol instance\n * @param set_by_user   @c TRUE if status has been changed by user\n * @param activity      New activity\n * @param message       New note text\n */\nvoid sipe_core_status_set(struct sipe_core_public *sipe_public,\n\t\t\t  gboolean set_by_user,\n\t\t\t  guint activity,\n\t\t\t  const gchar *note);\n\n#define SIPE_MSRTP_VSR_HEADER_LEN  20\n#define SIPE_MSRTP_VSR_ENTRY_LEN   0x44\n#define SIPE_MSRTP_VSR_FCI_WORDLEN \\\n\t(SIPE_MSRTP_VSR_HEADER_LEN + SIPE_MSRTP_VSR_ENTRY_LEN) / 4\n\n#define SIPE_MSRTP_VSR_SOURCE_ANY  0xFFFFFFFE\n#define SIPE_MSRTP_VSR_SOURCE_NONE 0xFFFFFFFF\n\n/**\n * Fills @buffer with Video Source Request described in [MS-RTP] 2.2.12.2.\n *\n * @param buffer (out) destination the VSR will be written to. The byte length\n *               of @c buffer MUST be at least @c SIPE_MSRTP_VSR_HEADER_LEN +\n *               @c SIPE_MSRTP_VSR_ENTRY_LEN.\n * @param payload_type (in) payload ID of the codec negotiated with the peer.\n * @param media_source_id (in) ID of the video stream to request.\n */\nvoid sipe_core_msrtp_write_video_source_request(guint8 *buffer,\n\t\t\t\t\t\tguint8 payload_type,\n\t\t\t\t\t\tguint32 media_source_id);\n\n/**\n * Fills @buffer with customized Payload Content Scalability Information packet\n * described in [MS-H264PF] consisting of a Stream Layout SEI Message (section\n * 2.2.5) and a Bitstream Info SEI Message (section 2.2.7).\n *\n * @param buffer (out) destination the PACSI will be written to.\n * @param nal_count (in) number of NAL units this packet describes.\n *\n * @return Byte length of the PACSI packet.\n */\ngsize sipe_core_msrtp_write_video_scalability_info(guint8 *buffer,\n\t\t\t\t\t\t   guint8 nal_count);\n\n#ifdef __cplusplus\n}\n#endif\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/api/sipe-mime.h",
    "content": "/**\n * @file sipe-mime.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2015 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/**\n * MIME backend initialization\n */\nvoid sipe_mime_init(void);\n\n/**\n * MIME backend shutdown\n */\nvoid sipe_mime_shutdown(void);\n\n/**\n * Callback type for sipe_mime_parts_foreach().\n *\n * @param user_data callback data.\n * @param fields    list of @c sipnameval structures with the header fields\n * @param body      text of the MIME part.\n * @param length    length of the body text.\n */\ntypedef void (*sipe_mime_parts_cb)(gpointer user_data,\n\t\t\t\t   const GSList *fields,\n\t\t\t\t   const gchar *body,\n\t\t\t\t   gsize length);\n\n/**\n * Parse MIME document and call a function for each part.\n *\n * @param type      content type of the MIME document.\n * @param body      body of the MIME document.\n * @param callback  function to call for each MIME part.\n * @param user_data callback data.\n */\nvoid sipe_mime_parts_foreach(const gchar *type,\n\t\t\t     const gchar *body,\n\t\t\t     sipe_mime_parts_cb callback,\n\t\t\t     gpointer user_data);\n\n/**\n * Checks whether MIME document contains a part with given type.\n *\n * @param type      content type of the whole MIME document.\n * @param body      body of the MIME document.\n * @param part_type the MIME type to search for in document parts.\n *\n * @return @c TRUE if @c body contains such part, otherwise @c FALSE.\n */\ngboolean sipe_mime_parts_contain(const gchar *type,\n\t\t\t\t const gchar *body,\n\t\t\t\t const gchar *part_type);\n"
  },
  {
    "path": "src/api/sipe-nls.h",
    "content": "/**\n * @file sipe-nls.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2009-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/*\n * config.h must be included for correct definition of ENABLE_NLS.\n * PACKAGE_NAME is always defined when config.h has been included.\n */\n#if defined(HAVE_CONFIG_H) && !defined(PACKAGE_NAME)\n#error you must include \"config.h\" before \"sipe-nls.h\"\n#endif\n\n#ifdef ENABLE_NLS\n#include <glib/gi18n.h>\n#else\n#define _(String) ((const char *) (String))\n#define N_(String) ((const char *) (String))\n#define gettext(String) ((const char *) (String))\n#define dngettext(package, StringS, StringP, p) ((const char *) ((p) ? (StringP) : (StringS)))\n#endif /* ENABLE_NLS */\n"
  },
  {
    "path": "src/core/Makefile.am",
    "content": "EXTRA_DIST = \\\n\tMakefile.mingw \\\n\tlibsiperc.rc.in\n\nnoinst_LTLIBRARIES = \\\n\tlibsipe_core.la \\\n\tlibsipe_core_crypto.la \\\n\tlibsipe_core_libxml2.la\n\nMAINTAINERCLEANFILES = \\\n\tMakefile.in\n\nlibsipe_core_la_SOURCES = \\\n\tsipmsg.h \\\n\tsipmsg.c \\\n\tsip-csta.h \\\n\tsip-csta.c \\\n\tsip-sec.h \\\n\tsip-sec.c \\\n\tsip-sec-basic.h \\\n\tsip-sec-basic.c \\\n\tsip-sec-digest.h \\\n\tsip-sec-digest.c \\\n\tsip-sec-mech.h \\\n\tsip-sec-tls-dsk.h \\\n\tsip-sec-tls-dsk.c \\\n\tsip-soap.h \\\n\tsip-soap.c \\\n\tsip-transport.h \\\n\tsip-transport.c \\\n\tsipe-buddy.h \\\n\tsipe-buddy.c \\\n\tsipe-cal.h \\\n\tsipe-cal.c \\\n\tsipe-certificate.h \\\n\tsipe-certificate.c \\\n\tsipe-cert-crypto.h \\\n\tsipe-chat.h \\\n\tsipe-chat.c \\\n\tsipe-conf.h \\\n\tsipe-conf.c \\\n\tsipe-core-private.h \\\n\tsipe-core.c \\\n\tsipe-crypt.h \\\n\tsipe-dialog.h \\\n\tsipe-dialog.c \\\n\tsipe-digest.h \\\n\tsipe-ews.h \\\n\tsipe-ews.c \\\n\tsipe-ews-autodiscover.h \\\n\tsipe-ews-autodiscover.c \\\n\tsipe-ft.h \\\n\tsipe-ft.c \\\n\tsipe-ft-tftp.h \\\n\tsipe-ft-tftp.c \\\n\tsipe-group.h \\\n\tsipe-group.c \\\n\tsipe-groupchat.h \\\n\tsipe-groupchat.c \\\n\tsipe-http.h \\\n\tsipe-http.c \\\n\tsipe-http-request.h \\\n\tsipe-http-request.c \\\n\tsipe-http-transport.h \\\n\tsipe-http-transport.c \\\n\tsipe-im.h \\\n\tsipe-im.c \\\n\tsipe-incoming.h \\\n\tsipe-incoming.c \\\n\tsipe-lync-autodiscover.h \\\n\tsipe-lync-autodiscover.c \\\n\tsipe-mime-common.c \\\n\tsipe-notify.h \\\n\tsipe-notify.c \\\n\tsipe-ocs2005.h \\\n\tsipe-ocs2005.c \\\n\tsipe-ocs2007.h \\\n\tsipe-ocs2007.c \\\n\tsipe-rtf.h \\\n\tsipe-rtf.l \\\n\tsipe-schedule.h \\\n\tsipe-schedule.c \\\n\tsipe-session.h \\\n\tsipe-session.c \\\n\tsipe-sign.h \\\n\tsipe-sign.c \\\n\tsipe-status.h \\\n\tsipe-status.c \\\n\tsipe-subscriptions.h \\\n\tsipe-subscriptions.c \\\n\tsipe-svc.h \\\n\tsipe-svc.c \\\n\tsipe-tls.h \\\n\tsipe-tls.c \\\n\tsipe-ucs.h \\\n\tsipe-ucs.c \\\n\tsipe-user.h \\\n\tsipe-user.c \\\n\tsipe-utils.h \\\n\tsipe-utils.c \\\n\tsipe-webticket.h \\\n\tsipe-webticket.c \\\n\tsipe-xml.h \\\n\tuuid.h \\\n\tuuid.c\n\nif SIPE_OS_WIN32\nlibsipe_core_la_SOURCES += \\\n\tsip-sec-sspi.h \\\n\tsip-sec-sspi.c \\\n\tsipe-domino.h \\\n\tsipe-domino.c \\\n\tsipe-win32dep.h \\\n\tsipe-win32dep.c\nelse\n\nif !SIP_SEC_GSSAPI_ONLY\nlibsipe_core_la_SOURCES += \\\n\tsip-sec-ntlm.h \\\n\tsip-sec-ntlm.c\n\nnoinst_LTLIBRARIES += \\\n\tlibsipe_core_tests.la\n\nlibsipe_core_tests_la_SOURCES = \\\n\tsip-sec-ntlm-tests.c\nlibsipe_core_tests_la_LIBADD = \\\n\tlibsipe_core_la-sipmsg.lo \\\n\tlibsipe_core_la-sipe-rtf.lo \\\n\tlibsipe_core_la-sipe-sign.lo \\\n\tlibsipe_core_la-sipe-utils.lo \\\n\tlibsipe_core_la-uuid.lo\nendif\n\nendif\n\nif SIPE_OPENSSL\nlibsipe_core_crypto_la_SOURCES = \\\n\tsipe-cert-crypto-openssl.c \\\n\tsipe-crypt-openssl.c \\\n\tsipe-digest-openssl.c\nelse\nlibsipe_core_crypto_la_SOURCES = \\\n\tsipe-cert-crypto-nss.c \\\n\tsipe-crypt-nss.c \\\n\tsipe-digest-nss.c\nif !SIP_SEC_GSSAPI_ONLY\nlibsipe_core_crypto_la_SOURCES += \\\n\tmd4.h \\\n\tmd4.c\nendif\nendif\n\nlibsipe_core_libxml2_la_SOURCES = \\\n\tsipe-xml.c\n\nAM_CFLAGS = $(st)\n\nlibsipe_core_la_CFLAGS = \\\n        $(DEBUG_CFLAGS) \\\n        $(QUALITY_CFLAGS) \\\n        $(GLIB_CFLAGS) \\\n        $(LOCALE_CPPFLAGS) \\\n\t-I$(srcdir)/../api\n\nif !SIPE_OS_WIN32\nif !SIP_SEC_GSSAPI_ONLY\nlibsipe_core_tests_la_CFLAGS = $(libsipe_core_la_CFLAGS)\nendif\nendif\n\nif SIP_SEC_GSSAPI\nlibsipe_core_la_SOURCES += \\\n\tsip-sec-gssapi.h \\\n\tsip-sec-gssapi.c\nlibsipe_core_la_CFLAGS  += $(KRB5_CFLAGS)\n\nif !SIP_SEC_GSSAPI_ONLY\nlibsipe_core_la_SOURCES += \\\n\tsip-sec-negotiate.h \\\n\tsip-sec-negotiate.c\nendif\nendif\n\n\nif SIPE_MIME_GMIME\nnoinst_LTLIBRARIES           += libsipe_core_mime.la\nlibsipe_core_mime_la_SOURCES  = sipe-mime.c\nlibsipe_core_mime_la_CFLAGS   = $(libsipe_core_la_CFLAGS) $(GMIME_CFLAGS)\nendif\n\nif SIPE_OS_WIN32\nlibsipe_core_la_CFLAGS  += -DHAVE_SSPI=1\nendif\n\nlibsipe_core_crypto_la_CFLAGS = \\\n\t$(libsipe_core_la_CFLAGS)\nif SIPE_OPENSSL\nlibsipe_core_crypto_la_CFLAGS += \\\n\t$(OPENSSL_CFLAGS)\nelse\nlibsipe_core_crypto_la_CFLAGS += \\\n\t$(NSS_CFLAGS) \\\n\t$(VALGRIND_CFLAGS)\nendif\n\nlibsipe_core_libxml2_la_CFLAGS = $(libsipe_core_la_CFLAGS) $(LIBXML2_CFLAGS)\n\nif SIPE_WITH_VV\nlibsipe_core_la_SOURCES += sipe-media.h sipe-media.c \\\n\tsdpmsg.h sdpmsg.c \\\n\tsipe-msrtp.c\nendif\n\nif SIPE_HAVE_XDATA\nlibsipe_core_la_SOURCES += \\\n\tsipe-ft-lync.h sipe-ft-lync.c\n\nif SIPE_HAVE_APPSHARE\nlibsipe_core_la_SOURCES += \\\n\tsipe-appshare.c \\\n\tsipe-appshare.h \\\n\tsipe-appshare-client.h \\\n\tsipe-appshare-remmina.c \\\n\tsipe-appshare-xfreerdp.c\n\nlibsipe_core_la_CFLAGS += $(GIO_CFLAGS)\n\nif SIPE_HAVE_APPSHARE_SERVER\nlibsipe_core_la_CFLAGS += \\\n\t$(FREERDP_SHADOW_CFLAGS)\nendif\nendif\nendif\n\ncheck_PROGRAMS =\n\ncheck_PROGRAMS += sipe_generic_tests\nsipe_generic_tests_SOURCES = sipe-generic-tests.c\nsipe_generic_tests_CFLAGS = $(libsipe_core_la_CFLAGS)\nsipe_generic_tests_LDADD = \\\n\tlibsipe_core_la-sipe-utils.lo \\\n\tlibsipe_core_la-uuid.lo\nif SIPE_OPENSSL\nsipe_generic_tests_LDADD += \\\n\tlibsipe_core_crypto_la-sipe-crypt-openssl.lo \\\n\tlibsipe_core_crypto_la-sipe-digest-openssl.lo \\\n\t$(OPENSSL_LIBS)\nelse\nsipe_generic_tests_LDADD += \\\n\tlibsipe_core_crypto_la-sipe-crypt-nss.lo \\\n\tlibsipe_core_crypto_la-sipe-digest-nss.lo \\\n\t$(NSS_LIBS)\nendif\nsipe_generic_tests_LDADD += \\\n\t$(GLIB_LIBS)\n\ncheck_PROGRAMS += sipe_sipmsg_tests\nsipe_sipmsg_tests_SOURCES = sipe-sipmsg-tests.c\nsipe_sipmsg_tests_CFLAGS = $(libsipe_core_la_CFLAGS)\nsipe_sipmsg_tests_LDADD = \\\n\tlibsipe_core_la-sipe-sign.lo \\\n\tlibsipe_core_la-sipe-utils.lo \\\n\tlibsipe_core_la-sipmsg.lo \\\n\tlibsipe_core_la-uuid.lo\nif SIPE_OPENSSL\nsipe_sipmsg_tests_LDADD += \\\n\tlibsipe_core_crypto_la-sipe-crypt-openssl.lo \\\n\tlibsipe_core_crypto_la-sipe-digest-openssl.lo \\\n\t$(OPENSSL_LIBS)\nelse\nsipe_sipmsg_tests_LDADD += \\\n\tlibsipe_core_crypto_la-sipe-crypt-nss.lo \\\n\tlibsipe_core_crypto_la-sipe-digest-nss.lo \\\n\t$(NSS_LIBS)\nendif\nsipe_sipmsg_tests_LDADD += \\\n\t$(GLIB_LIBS)\n\ncheck_PROGRAMS += sipe_rtf_tests\nsipe_rtf_tests_SOURCES = sipe-rtf-tests.c\nsipe_rtf_tests_CFLAGS = $(libsipe_core_la_CFLAGS)\nsipe_rtf_tests_LDADD = \\\n\tlibsipe_core_la-sipe-rtf.lo \\\n\t$(GLIB_LIBS)\n\ncheck_PROGRAMS += sipe_xml_tests\nsipe_xml_tests_SOURCES = sipe-xml-tests.c\nsipe_xml_tests_CFLAGS = $(libsipe_core_la_CFLAGS)\nsipe_xml_tests_LDADD = \\\n\tlibsipe_core_libxml2.la \\\n\tlibsipe_core_la-sipe-utils.lo \\\n\t$(LIBXML2_LIBS) \\\n\t$(GLIB_LIBS)\n\ncheck_PROGRAMS += sip_sec_digest_tests\nsip_sec_digest_tests_SOURCES = sip-sec-digest-tests.c\nsip_sec_digest_tests_CFLAGS = $(libsipe_core_la_CFLAGS)\nsip_sec_digest_tests_LDADD = \\\n\tlibsipe_core_la-sipe-utils.lo\nif SIPE_OPENSSL\nsip_sec_digest_tests_LDADD += \\\n\tlibsipe_core_crypto_la-sipe-crypt-openssl.lo \\\n\tlibsipe_core_crypto_la-sipe-digest-openssl.lo \\\n\t$(OPENSSL_LIBS)\nelse\nsip_sec_digest_tests_LDADD += \\\n\tlibsipe_core_crypto_la-sipe-crypt-nss.lo \\\n\tlibsipe_core_crypto_la-sipe-digest-nss.lo \\\n\t$(NSS_LIBS)\nendif\nsip_sec_digest_tests_LDADD += \\\n\t$(GLIB_LIBS)\n\n# disables \"caching\" of memory blocks in tests\nTESTS_ENVIRONMENT = G_SLICE=\"always-malloc\"\nTESTS = $(check_PROGRAMS)\n\nnoinst_PROGRAMS =\n\nif !SIPE_OS_WIN32\n# TODO: the code needs some TLC from a MinGW expert to compile...\nnoinst_PROGRAMS += sipe_tls_analyzer\nsipe_tls_analyzer_SOURCES = sipe-tls-analyzer.c\nsipe_tls_analyzer_CFLAGS = $(libsipe_core_la_CFLAGS)\nsipe_tls_analyzer_LDADD = \\\n\t$(GLIB_LIBS)\n\nnoinst_PROGRAMS += sipe_tls_tester\nsipe_tls_tester_SOURCES = sipe-tls-tester.c\nsipe_tls_tester_CFLAGS = $(libsipe_core_la_CFLAGS)\nsipe_tls_tester_LDADD = \\\n\tlibsipe_core_la-sipe-tls.lo\n\nif SIPE_OPENSSL\nsipe_tls_tester_LDADD += \\\n\tlibsipe_core_crypto_la-sipe-cert-crypto-openssl.lo \\\n\tlibsipe_core_crypto_la-sipe-crypt-openssl.lo \\\n\tlibsipe_core_crypto_la-sipe-digest-openssl.lo \\\n\t$(OPENSSL_LIBS)\nelse\nsipe_tls_tester_LDADD += \\\n\tlibsipe_core_crypto_la-sipe-cert-crypto-nss.lo \\\n\tlibsipe_core_crypto_la-sipe-crypt-nss.lo \\\n\tlibsipe_core_crypto_la-sipe-digest-nss.lo \\\n\t$(NSS_LIBS)\nendif\nsipe_tls_tester_LDADD += \\\n\t$(GLIB_LIBS)\nendif\n\nnoinst_PROGRAMS += sipe_ntlm_analyzer\nsipe_ntlm_analyzer_SOURCES = sip-sec-ntlm-analyzer.c\nsipe_ntlm_analyzer_CFLAGS = $(libsipe_core_la_CFLAGS)\nsipe_ntlm_analyzer_LDADD = \\\n\t$(GLIB_LIBS)\n"
  },
  {
    "path": "src/core/Makefile.mingw",
    "content": "################################### tell Emacs this is a -*- makefile-gmake -*-\n#\n# Copyright (C) 2011-2018 SIPE Project <http://sipe.sourceforge.net/>\n#\n# Makefile.mingw\n#\n# Author: zup@sbox.tugraz.at\n# Date 8/28/07\n# Description: Makefile for win32 (mingw) version of libsipe\n#\n###############################################################################\n#\n# Configuration option:\n#  - USE_SSPI defined:     NTLM, Kerberos, TLS-DSK & Single Sign-On supported\n#  - USE_SSPI not defined: NTLM & TLS-DSK but without Single Sign-On support\n#             [eg.: make -f Makefile.mingw USE_SSPI= ]\n#\n# @TODO: HAVE_GSSAPI_GSSAPI_H support for USE_SSPI=. Where to find the libraries?\n#        Those would need to be packaged alongside the plugin.\n#\nUSE_SSPI := 1\n\nifdef PIDGIN_TREE_TOP\n# standalone MinGW build\nOLD_PIDGIN_TREE_TOP := $(PIDGIN_TREE_TOP)\nPIDGIN_TREE_TOP     := ../$(OLD_PIDGIN_TREE_TOP)\nelse\n# MinGW cross-compile build (see contrib/mingw-cross-compile/README.txt)\nPIDGIN_TREE_TOP := ../../..\nVERSION         := $(shell cat ../../VERSION)\nendif\n\ninclude $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak\n\nTARGET = libsipe\n\nDLL_INSTALL_DIR = $(PURPLE_INSTALL_PLUGINS_DIR)\n\n# dump higher level defines\nDEFINES  =\nDEFINES += -DENABLE_NLS=1\nDEFINES += -DPACKAGE_BUGREPORT=\\\"https://sourceforge.net/p/sipe/bugs/\\\"\nDEFINES += -DPACKAGE_NAME=\\\"pidgin-sipe\\\"\nDEFINES += -DPACKAGE_URL=\\\"http://sipe.sourceforge.net/\\\"\nDEFINES += -DPACKAGE_VERSION=\\\"$(VERSION)\\\"\nDEFINES += -DSIPE_TRANSLATIONS_URL=\\\"https://www.transifex.com/stefanb/pidgin-sipe/\\\"\n#DEFINES += -DENABLE_OCS2005_MESSAGE_HACK=1\n\nifdef USE_SSPI\nDEFINES += -DHAVE_SSPI=1\nendif\n\n##\n## INCLUDE PATHS\n##\nINCLUDE_PATHS +=\t-I. \\\n\t\t\t-I../api \\\n\t\t\t-I../purple \\\n\t\t\t-I$(GTK_TOP)/include \\\n\t\t\t-I$(GTK_TOP)/include/glib-2.0 \\\n\t\t\t-I$(GTK_TOP)/lib/glib-2.0/include \\\n\t\t\t-I$(LIBXML2_TOP)/include/libxml2 \\\n\t\t\t-I$(NSPR_TOP)/include \\\n\t\t\t-I$(NSS_TOP)/include\n\nPURPLE_INCLUDE_PATHS += -I$(PURPLE_TOP) \\\n\t\t\t-I$(PURPLE_TOP)/win32 \\\n\t\t\t-I$(PIDGIN_TREE_TOP)\n\n##\n##  SOURCES, OBJECTS\n##\nCLEAN_C_SRC =\t\tsip-soap.c \\\n\t\t\tsip-transport.c \\\n\t\t\tsipe-conf.c \\\n\t\t\tsipe-core.c \\\n\t\t\tsipe-domino.c \\\n\t\t\tsipe-buddy.c \\\n\t\t\tsipe-cal.c \\\n\t\t\tsipe-certificate.c \\\n\t\t\tsipe-cert-crypto-nss.c \\\n\t\t\tsipe-chat.c \\\n\t\t\tsipe-crypt-nss.c \\\n\t\t\tsipe-dialog.c \\\n\t\t\tsipe-digest-nss.c \\\n\t\t\tsipe-ft.c \\\n\t\t\tsipe-ft-tftp.c \\\n\t\t\tsipe-group.c \\\n\t\t\tsipe-groupchat.c \\\n\t\t\tsipe-http.c \\\n\t\t\tsipe-http-request.c \\\n\t\t\tsipe-http-transport.c \\\n\t\t\tsipe-im.c \\\n\t\t\tsipe-incoming.c \\\n\t\t\tsipe-lync-autodiscover.c \\\n\t\t\tsipe-mime-common.c \\\n\t\t\tsipe-notify.c \\\n\t\t\tsipe-ocs2005.c \\\n\t\t\tsipe-ocs2007.c \\\n\t\t\tsipe-rtf.c \\\n\t\t\tsipe-schedule.c \\\n\t\t\tsipe-session.c \\\n\t\t\tsipe-status.c \\\n\t\t\tsipe-subscriptions.c \\\n\t\t\tsipe-svc.c \\\n\t\t\tsipe-tls.c \\\n\t\t\tsipe-ucs.c \\\n\t\t\tsipe-user.c \\\n\t\t\tsipe-utils.c \\\n\t\t\tsipe-ews.c \\\n\t\t\tsipe-ews-autodiscover.c \\\n\t\t\tsipmsg.c \\\n\t\t\tsipe-sign.c \\\n\t\t\tsip-sec.c \\\n\t\t\tsip-sec-basic.c \\\n\t\t\tsip-sec-digest.c \\\n\t\t\tsip-sec-tls-dsk.c \\\n\t\t\tsip-csta.c \\\n\t\t\tsipe-webticket.c \\\n\t\t\tsipe-xml.c \\\n\t\t\tuuid.c \\\n\t\t\tsipe-win32dep.c\n\nPURPLE_C_SRC = \t\t../purple/purple-buddy.c \\\n\t\t\t../purple/purple-chat.c \\\n\t\t\t../purple/purple-connection.c \\\n\t\t\t../purple/purple-debug.c \\\n\t\t\t../purple/purple-dnsquery.c \\\n\t\t\t../purple/purple-ft.c \\\n\t\t\t../purple/purple-groupchat.c \\\n\t\t\t../purple/purple-im.c \\\n\t\t\t../purple/purple-markup.c \\\n\t\t\t../purple/purple-mime.c \\\n\t\t\t../purple/purple-network.c \\\n\t\t\t../purple/purple-notify.c \\\n\t\t\t../purple/purple-plugin.c \\\n\t\t\t../purple/purple-plugin-common.c \\\n\t\t\t../purple/purple-schedule.c \\\n\t\t\t../purple/purple-search.c \\\n\t\t\t../purple/purple-setting.c \\\n\t\t\t../purple/purple-status.c \\\n\t\t\t../purple/purple-transport.c \\\n\t\t\t../purple/purple-user.c\n\nC_TEST_SRC = \t\tsipe-xml-tests.c\n\nifdef USE_SSPI\nCLEAN_C_SRC +=\t\tsip-sec-sspi.c\nelse\nCLEAN_C_SRC +=\t\tmd4.c \\\n\t\t\tsip-sec-ntlm.c\n\nC_TEST_SRC += \t\tsip-sec-ntlm-tests.c \\\n\t\t\t../purple/tests.c\nendif\n\nC_SRC =\t\t\t$(CLEAN_C_SRC) $(PURPLE_C_SRC)\n\nRC_SRC =\t\tlibsiperc.rc\n\nCLEAN_OBJECTS =\t\t$(CLEAN_C_SRC:%.c=%.o)\nPURPLE_OBJECTS = \t$(PURPLE_C_SRC:%.c=%.o)\nRC_OBJECTS =\t\t$(RC_SRC:%.rc=%.o)\nOBJECTS = \t\t$(CLEAN_OBJECTS) $(PURPLE_OBJECTS) $(RC_OBJECTS)\n\n# Only these modules need the purple headers\n$(PURPLE_OBJECTS):\tINCLUDE_PATHS += $(PURPLE_INCLUDE_PATHS)\n\nTEST_OBJECTS = \t\t$(C_TEST_SRC:%.c=%.o)\n\n##\n## LIBRARIES\n##\nLIB_PATHS =\t\t-L$(GTK_TOP)/lib \\\n\t\t\t-L$(LIBXML2_TOP)/lib \\\n\t\t\t-L$(NSS_TOP)/lib \\\n\t\t\t-L$(PURPLE_TOP)\n\nLIBS =\t\t\t-lglib-2.0 \\\n\t\t\t-lgobject-2.0 \\\n\t\t\t-lintl \\\n\t\t\t-lxml2 \\\n\t\t\t-lnss3 \\\n\t\t\t-lsmime3 \\\n\t\t\t-lnspr4 \\\n\t\t\t-lws2_32 \\\n\t\t\t-lpurple\n\nifdef USE_SSPI\nLIBS +=\t\t\t-lsecur32\nendif\n\n# These flags are used in mingw build\nTESTS_WARN = -Werror -Wall -Wextra -Waggregate-return -Wcast-align -Winit-self -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wundef\n\ninclude $(PIDGIN_COMMON_RULES)\n\n##\n## TARGET DEFINITIONS\n##\n.PHONY: all clean install\n\nall: $(TARGET).dll\n\n_comma = ,\n\nlibsiperc.rc: libsiperc.rc.in\n\tsed \\\n\t\t-e 's/@SIPE_VERSION@/$(VERSION)/' \\\n\t\t-e 's/#SIPE_VERSION#/$(subst .,$(_comma),$(VERSION))/' \\\n\t\t<$< >$@\n\n$(OBJECTS): $(PURPLE_CONFIG_H)\n\n$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)\n\t$(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $@.dbgsym\n\t$(STRIP) --strip-unneeded $@.dbgsym -o $@\n\n##\n## CLEAN RULES\n##\nclean: tests-clean\n\trm -f $(RC_SRC)\n\trm -f $(OBJECTS)\n\trm -f $(TARGET).dll\n\nrmbak:\n\trm -f *~\n\ninstall:\n\ttest -z \"$(DLL_INSTALL_DIR)\" || mkdir -p \"$(DLL_INSTALL_DIR)\"\n\t/usr/bin/install -c $(TARGET).dll $(TARGET).dll.dbgsym '$(DLL_INSTALL_DIR)'\n\n$(TEST_OBJECTS):\n\ntests: tests-clean $(TEST_OBJECTS)\n\t$(CC) sipe-utils.o uuid.o sipe-xml.o sipe-xml-tests.o -L. $(LIB_PATHS) $(LIBS) -lsipe -o sipe-xml-tests.exe\n\t./sipe-xml-tests.exe\nifdef USE_SSPI\n# nothing to do\nelse\n\t$(CC) ../purple/purple-debug.o ../purple/purple-markup.o ../purple/purple-network.o md4.o sipe-digest.o sipe-crypt.o sipe-mime.o sipe-sign.o sipmsg.o sipe-utils.o uuid.o sip-sec-ntlm-tests.o ../purple/tests.o  -L. $(LIB_PATHS) $(LIBS) -lsipe -o ../purple/tests.exe\n\t../purple/tests.exe\nendif\n\ntests-clean:\n\trm -f $(TEST_OBJECTS)\n\trm -f sipe-xml-tests.exe ../purple/tests.exe\n\ninclude $(PIDGIN_COMMON_TARGETS)\n"
  },
  {
    "path": "src/core/libsiperc.rc.in",
    "content": "#include <winver.h>\n\nVS_VERSION_INFO VERSIONINFO\n  FILEVERSION #SIPE_VERSION#,0\n  PRODUCTVERSION #SIPE_VERSION#,0\n  FILEFLAGSMASK 0\n  FILEFLAGS 0\n  FILEOS VOS__WINDOWS32\n  FILETYPE VFT_DLL\n  FILESUBTYPE VFT2_UNKNOWN\n  BEGIN\n    BLOCK \"StringFileInfo\"\n    BEGIN\n      BLOCK \"040904B0\"\n      BEGIN\n        VALUE \"CompanyName\", \"SIPE Project <http://sipe.sourceforge.net/>\"\n        VALUE \"FileDescription\", \"LibSipe third-party plugin for LibPurple\"\n        VALUE \"FileVersion\", \"@SIPE_VERSION@\"\n        VALUE \"InternalName\", \"libsipe\"\n        VALUE \"LegalCopyright\", \"Copyright (C) 2010-2013 SIPE Project (See the COPYRIGHT file in the source distribution).\"\n        VALUE \"OriginalFilename\", \"libsipe.dll\"\n        VALUE \"ProductName\", \"LibSipe\"\n        VALUE \"ProductVersion\", \"@SIPE_VERSION@\"\n      END\n    END\n    BLOCK \"VarFileInfo\"\n    BEGIN\n      VALUE \"Translation\", 0x409, 1200\n    END\n  END\n"
  },
  {
    "path": "src/core/md4.c",
    "content": "/* vim:set ts=2 sw=2 et cindent: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/*\n * \"clean room\" MD4 implementation (see RFC 1320)\n */\n\n#include <string.h>\n#include \"md4.h\"\n\n/* the \"conditional\" function */\n#define F(x,y,z) (((x) & (y)) | (~(x) & (z)))\n\n/* the \"majority\" function */\n#define G(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))\n\n/* the \"parity\" function */\n#define H(x,y,z) ((x) ^ (y) ^ (z))\n\n/* rotate n-bits to the left */\n#define ROTL(x,n) (((x) << (n)) | ((x) >> (0x20 - n)))\n\n/* round 1: [abcd k s]: a = (a + F(b,c,d) + X[k]) <<< s */\n#define RD1(a,b,c,d,k,s) a += F(b,c,d) + X[k]; a = ROTL(a,s)\n\n/* round 2: [abcd k s]: a = (a + G(b,c,d) + X[k] + MAGIC) <<< s */\n#define RD2(a,b,c,d,k,s) a += G(b,c,d) + X[k] + 0x5A827999; a = ROTL(a,s)\n\n/* round 3: [abcd k s]: a = (a + H(b,c,d) + X[k] + MAGIC) <<< s */\n#define RD3(a,b,c,d,k,s) a += H(b,c,d) + X[k] + 0x6ED9EBA1; a = ROTL(a,s)\n\n/* converts from word array to byte array, len is number of bytes */\nstatic void w2b(uint8_t *out, const uint32_t *in, uint32_t len)\n{\n  uint8_t *bp; const uint32_t *wp, *wpend;\n\n  bp = out;\n  wp = in;\n  wpend = wp + (len >> 2);\n\n  for (; wp != wpend; ++wp, bp += 4)\n  {\n    bp[0] = (uint8_t) ((*wp      ) & 0xFF);\n    bp[1] = (uint8_t) ((*wp >>  8) & 0xFF);\n    bp[2] = (uint8_t) ((*wp >> 16) & 0xFF);\n    bp[3] = (uint8_t) ((*wp >> 24) & 0xFF);\n  }\n}\n\n/* converts from byte array to word array, len is number of bytes */\nstatic void b2w(uint32_t *out, const uint8_t *in, uint32_t len)\n{\n  uint32_t *wp; const uint8_t *bp, *bpend;\n\n  wp = out;\n  bp = in;\n  bpend = in + len;\n\n  for (; bp != bpend; bp += 4, ++wp)\n  {\n    *wp = (uint32_t) (bp[0]      ) |\n          (uint32_t) (bp[1] <<  8) |\n          (uint32_t) (bp[2] << 16) |\n          (uint32_t) (bp[3] << 24);\n  }\n}\n\n/* update state: data is 64 bytes in length */\nstatic void md4step(uint32_t state[4], const uint8_t *data)\n{\n  uint32_t A, B, C, D, X[16];\n\n  b2w(X, data, 64);\n\n  A = state[0];\n  B = state[1];\n  C = state[2];\n  D = state[3];\n\n  RD1(A,B,C,D, 0,3); RD1(D,A,B,C, 1,7); RD1(C,D,A,B, 2,11); RD1(B,C,D,A, 3,19);\n  RD1(A,B,C,D, 4,3); RD1(D,A,B,C, 5,7); RD1(C,D,A,B, 6,11); RD1(B,C,D,A, 7,19);\n  RD1(A,B,C,D, 8,3); RD1(D,A,B,C, 9,7); RD1(C,D,A,B,10,11); RD1(B,C,D,A,11,19);\n  RD1(A,B,C,D,12,3); RD1(D,A,B,C,13,7); RD1(C,D,A,B,14,11); RD1(B,C,D,A,15,19);\n\n  RD2(A,B,C,D, 0,3); RD2(D,A,B,C, 4,5); RD2(C,D,A,B, 8, 9); RD2(B,C,D,A,12,13);\n  RD2(A,B,C,D, 1,3); RD2(D,A,B,C, 5,5); RD2(C,D,A,B, 9, 9); RD2(B,C,D,A,13,13);\n  RD2(A,B,C,D, 2,3); RD2(D,A,B,C, 6,5); RD2(C,D,A,B,10, 9); RD2(B,C,D,A,14,13);\n  RD2(A,B,C,D, 3,3); RD2(D,A,B,C, 7,5); RD2(C,D,A,B,11, 9); RD2(B,C,D,A,15,13);\n\n  RD3(A,B,C,D, 0,3); RD3(D,A,B,C, 8,9); RD3(C,D,A,B, 4,11); RD3(B,C,D,A,12,15);\n  RD3(A,B,C,D, 2,3); RD3(D,A,B,C,10,9); RD3(C,D,A,B, 6,11); RD3(B,C,D,A,14,15);\n  RD3(A,B,C,D, 1,3); RD3(D,A,B,C, 9,9); RD3(C,D,A,B, 5,11); RD3(B,C,D,A,13,15);\n  RD3(A,B,C,D, 3,3); RD3(D,A,B,C,11,9); RD3(C,D,A,B, 7,11); RD3(B,C,D,A,15,15);\n\n  state[0] += A;\n  state[1] += B;\n  state[2] += C;\n  state[3] += D;\n}\n\nvoid md4sum(const uint8_t *input, uint32_t inputLen, uint8_t *result)\n{\n  uint8_t final[128];\n  uint32_t i, n, m, state[4];\n  uint64_t inputLenBits;\n  uint32_t inputLenBitsLow;\n  uint32_t inputLenBitsHigh;\n\n  /* magic initial states */\n  state[0] = 0x67452301;\n  state[1] = 0xEFCDAB89;\n  state[2] = 0x98BADCFE;\n  state[3] = 0x10325476;\n\n  /* compute number of complete 64-byte segments contained in input */\n  m = inputLen >> 6;\n\n  /* digest first m segments */\n  for (i=0; i<m; ++i)\n    md4step(state, (input + (i << 6)));\n\n  /* build final buffer */\n  n = inputLen % 64;\n  memcpy(final, input + (m << 6), n);\n  final[n] = 0x80;\n  memset(final + n + 1, 0, 120 - (n + 1));\n\n  /* Append the original input length in bits as a 64-bit number. This is done\n   * in two 32-bit chunks, with the least-significant 32 bits first.\n   * w2b will handle endianness. */\n  inputLenBits = inputLen << 3;\n  inputLenBitsLow = (uint32_t)(inputLenBits & 0xFFFFFFFF);\n  w2b(final + (n >= 56 ? 120 : 56), &inputLenBitsLow, 4);\n  inputLenBitsHigh = (uint32_t)((inputLenBits >> 32) & 0xFFFFFFFF);\n  w2b(final + (n >= 56 ? 124 : 60), &inputLenBitsHigh, 4);\n\n  md4step(state, final);\n  if (n >= 56)\n    md4step(state, final + 64);\n\n  /* copy state to result */\n  w2b(result, state, 16);\n}\n"
  },
  {
    "path": "src/core/md4.h",
    "content": "/* vim:set ts=2 sw=2 et cindent: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef md4_h__\n#define md4_h__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <stdint.h>\n\n/**\n * md4sum - computes the MD4 sum over the input buffer per RFC 1320\n *\n * @param input\n *        buffer containing input data\n * @param inputLen\n *        length of input buffer (number of bytes)\n * @param result\n *        16-byte buffer that will contain the MD4 sum upon return\n *\n * NOTE: MD4 is superceded by MD5.  do not use MD4 unless required by the\n * protocol you are implementing (e.g., NTLM requires MD4).\n *\n * NOTE: this interface is designed for relatively small buffers.  A streaming\n * interface would make more sense if that were a requirement.  Currently, this\n * is good enough for the applications we care about.\n */\nvoid md4sum(const uint8_t *input, uint32_t inputLen, uint8_t *result);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* md4_h__ */\n"
  },
  {
    "path": "src/core/sdpmsg.c",
    "content": "/**\n * @file sdpmsg.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013-2017 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2010 Jakub Adam <jakub.adam@ktknet.cz>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sdpmsg.h\"\n#include \"sipe-utils.h\"\n\nstatic gboolean\nappend_attribute(struct sdpmedia *media, gchar *attr)\n{\n\tgchar **parts = g_strsplit(attr + 2, \":\", 2);\n\n\tif(!parts[0]) {\n\t\tg_strfreev(parts);\n\t\treturn FALSE;\n\t}\n\n\tmedia->attributes = sipe_utils_nameval_add(media->attributes,\n\t\t\t\t\t\t   parts[0],\n\t\t\t\t\t\t   parts[1] ? parts[1] : \"\");\n\tg_strfreev(parts);\n\treturn TRUE;\n}\n\nstatic gboolean\nparse_attributes(struct sdpmsg *smsg, const gchar *msg) {\n\tgchar\t\t**lines = g_strsplit(msg, \"\\r\\n\", 0);\n\tgchar\t\t**ptr = lines;\n\n\twhile (*ptr != NULL) {\n\t\tif (g_str_has_prefix(*ptr, \"o=\")) {\n\t\t\tgchar **parts = g_strsplit(*ptr + 2, \" \", 6);\n\t\t\tif (g_strv_length(parts) != 6) {\n\t\t\t\tg_strfreev(parts);\n\t\t\t\tg_strfreev(lines);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tsmsg->ip = g_strdup(parts[5]);\n\t\t\tg_strfreev(parts);\n\t\t} else if (g_str_has_prefix(*ptr, \"m=\")) {\n\t\t\tgchar **parts;\n\t\t\tstruct sdpmedia *media;\n\n\t\t\tparts = g_strsplit(*ptr + 2, \" \", 3);\n\t\t\tif (g_strv_length(parts) < 3) {\n\t\t\t\tg_strfreev(parts);\n\t\t\t\tg_strfreev(lines);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tmedia = g_new0(struct sdpmedia, 1);\n\n\t\t\tsmsg->media = g_slist_append(smsg->media, media);\n\n\t\t\tmedia->name = g_strdup(parts[0]);\n\t\t\tmedia->port = atoi(parts[1]);\n\t\t\tmedia->encryption_active =\n\t\t\t\t\tg_strstr_len(parts[2], -1, \"/SAVP\") != NULL;\n\n\t\t\tg_strfreev(parts);\n\n\t\t\twhile (*(++ptr) && !g_str_has_prefix(*ptr, \"m=\")) {\n\n\t\t\t\tif (g_str_has_prefix(*ptr, \"a=\")) {\n\t\t\t\t\tif (!append_attribute(media, *ptr)) {\n\t\t\t\t\t\tg_strfreev(lines);\n\t\t\t\t\t\treturn FALSE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\t++ptr;\n\t}\n\n\tg_strfreev(lines);\n\n\treturn TRUE;\n}\n\nstatic struct sdpcandidate * sdpcandidate_copy(struct sdpcandidate *candidate);\n\nstatic SipeComponentType\nparse_component(const gchar *str)\n{\n\tswitch (atoi(str)) {\n\t\tcase 1: return  SIPE_COMPONENT_RTP;\n\t\tcase 2: return  SIPE_COMPONENT_RTCP;\n\t\tdefault: return SIPE_COMPONENT_NONE;\n\t}\n}\n\nstatic gchar *\nbase64_pad(const gchar* str)\n{\n\tsize_t str_len = strlen(str);\n\tint mod = str_len % 4;\n\n\tif (mod > 0) {\n\t\tgchar *result = NULL;\n\t\tint pad = 4 - mod;\n\t\tgchar *ptr = result = g_malloc(str_len + pad + 1);\n\n\t\tmemcpy(ptr, str, str_len);\n\t\tptr += str_len;\n\t\tmemset(ptr, '=', pad);\n\t\tptr += pad;\n\t\t*ptr = '\\0';\n\n\t\treturn result;\n\t} else\n\t\treturn g_strdup(str);\n}\n\nstatic gboolean\nparse_append_candidate_draft_6(gchar **tokens, GSList **candidates)\n{\n\tstruct sdpcandidate *candidate;\n\n\tif (g_strv_length(tokens) < 7 || strlen(tokens[4]) < 3) {\n\t\treturn FALSE;\n\t}\n\n\tcandidate = g_new0(struct sdpcandidate, 1);\n\n\tcandidate->username = base64_pad(tokens[0]);\n\tcandidate->component = parse_component(tokens[1]);\n\tcandidate->password = base64_pad(tokens[2]);\n\n\tif (sipe_strequal(tokens[3], \"UDP\"))\n\t\tcandidate->protocol = SIPE_NETWORK_PROTOCOL_UDP;\n\telse if (sipe_strequal(tokens[3], \"TCP\"))\n\t\tcandidate->protocol = SIPE_NETWORK_PROTOCOL_TCP_ACTIVE;\n\telse {\n\t\tsdpcandidate_free(candidate);\n\t\treturn FALSE;\n\t}\n\n\tcandidate->priority = atoi(tokens[4] + 2);\n\tcandidate->ip = g_strdup(tokens[5]);\n\tcandidate->port = atoi(tokens[6]);\n\n\t*candidates = g_slist_append(*candidates, candidate);\n\n\t// draft 6 candidates are both active and passive\n\tif (candidate->protocol == SIPE_NETWORK_PROTOCOL_TCP_ACTIVE) {\n\t\tcandidate = sdpcandidate_copy(candidate);\n\t\tcandidate->protocol = SIPE_NETWORK_PROTOCOL_TCP_PASSIVE;\n\t\t*candidates = g_slist_append(*candidates, candidate);\n\t}\n\n\treturn TRUE;\n}\n\nstatic gboolean\nparse_append_candidate_rfc_5245(gchar **tokens, GSList **candidates)\n{\n\tstruct sdpcandidate *candidate;\n\n\tif (g_strv_length(tokens) < 8) {\n\t\treturn FALSE;\n\t}\n\n\tcandidate = g_new0(struct sdpcandidate, 1);\n\tcandidate->foundation = g_strdup(tokens[0]);\n\tcandidate->component = parse_component(tokens[1]);\n\n\tif (sipe_strcase_equal(tokens[2], \"UDP\"))\n\t\tcandidate->protocol = SIPE_NETWORK_PROTOCOL_UDP;\n\telse if (sipe_strcase_equal(tokens[2], \"TCP-ACT\"))\n\t\tcandidate->protocol = SIPE_NETWORK_PROTOCOL_TCP_ACTIVE;\n\telse if (sipe_strcase_equal(tokens[2], \"TCP-PASS\"))\n\t\tcandidate->protocol = SIPE_NETWORK_PROTOCOL_TCP_PASSIVE;\n\telse {\n\t\tsdpcandidate_free(candidate);\n\t\treturn FALSE;\n\t}\n\n\tcandidate->priority = atoi(tokens[3]);\n\tcandidate->ip = g_strdup(tokens[4]);\n\tcandidate->port = atoi(tokens[5]);\n\n\tif (sipe_strcase_equal(tokens[7], \"host\"))\n\t\tcandidate->type = SIPE_CANDIDATE_TYPE_HOST;\n\telse if (sipe_strcase_equal(tokens[7], \"relay\"))\n\t\tcandidate->type = SIPE_CANDIDATE_TYPE_RELAY;\n\telse if (sipe_strcase_equal(tokens[7], \"srflx\"))\n\t\tcandidate->type = SIPE_CANDIDATE_TYPE_SRFLX;\n\telse if (sipe_strcase_equal(tokens[7], \"prflx\"))\n\t\tcandidate->type = SIPE_CANDIDATE_TYPE_PRFLX;\n\telse {\n\t\tsdpcandidate_free(candidate);\n\t\treturn FALSE;\n\t}\n\n\t*candidates = g_slist_append(*candidates, candidate);\n\n\treturn TRUE;\n}\n\nstatic gboolean\nparse_candidates(GSList *attrs, SipeIceVersion *ice_version, GSList **candidates)\n{\n\tconst gchar *attr;\n\tint i = 0;\n\n\tg_return_val_if_fail(*candidates == NULL, FALSE);\n\n\t*ice_version = SIPE_ICE_NO_ICE;\n\n\twhile ((attr = sipe_utils_nameval_find_instance(attrs, \"candidate\", i++))) {\n\t\tgchar **tokens = g_strsplit_set(attr, \" \", 0);\n\t\tgboolean parsed_ok;\n\n\t\tif (g_strv_length(tokens) < 7) {\n\t\t\tg_strfreev(tokens);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (sipe_strequal(tokens[6], \"typ\")) {\n\t\t\tparsed_ok = parse_append_candidate_rfc_5245(tokens,\n\t\t\t\t\t\t\t\t    candidates);\n\t\t\tif (*candidates)\n\t\t\t\t*ice_version = SIPE_ICE_RFC_5245;\n\t\t} else {\n\t\t\tparsed_ok = parse_append_candidate_draft_6(tokens,\n\t\t\t\t\t\t\t\t   candidates);\n\t\t\tif (*candidates)\n\t\t\t\t*ice_version = SIPE_ICE_DRAFT_6;\n\t\t}\n\n\t\tg_strfreev(tokens);\n\n\t\tif (!parsed_ok) {\n\t\t\treturn FALSE;\n\t\t}\n\t}\n\n\tif (*ice_version == SIPE_ICE_RFC_5245) {\n\t\tconst gchar *username = sipe_utils_nameval_find(attrs, \"ice-ufrag\");\n\t\tconst gchar *password = sipe_utils_nameval_find(attrs, \"ice-pwd\");\n\n\t\tif (username && password) {\n\t\t\tGSList *i;\n\t\t\tfor (i = *candidates; i; i = i->next) {\n\t\t\t\tstruct sdpcandidate *c = i->data;\n\t\t\t\tc->username = g_strdup(username);\n\t\t\t\tc->password = g_strdup(password);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn TRUE;\n}\n\nstatic GSList *\ncreate_legacy_candidates(gchar *ip, guint16 port)\n{\n\tstruct sdpcandidate *candidate;\n\tGSList *candidates = NULL;\n\n\tcandidate = g_new0(struct sdpcandidate, 1);\n\tcandidate->foundation = g_strdup(\"1\");\n\tcandidate->component = SIPE_COMPONENT_RTP;\n\tcandidate->type = SIPE_CANDIDATE_TYPE_HOST;\n\tcandidate->protocol = SIPE_NETWORK_PROTOCOL_UDP;\n\tcandidate->ip = g_strdup(ip);\n\tcandidate->port = port;\n\n\tcandidates = g_slist_append(candidates, candidate);\n\n\tcandidate = g_new0(struct sdpcandidate, 1);\n\tcandidate->foundation = g_strdup(\"1\");\n\tcandidate->component = SIPE_COMPONENT_RTCP;\n\tcandidate->type = SIPE_CANDIDATE_TYPE_HOST;\n\tcandidate->protocol = SIPE_NETWORK_PROTOCOL_UDP;\n\tcandidate->ip = g_strdup(ip);\n\tcandidate->port = port + 1;\n\n\tcandidates = g_slist_append(candidates, candidate);\n\n\treturn candidates;\n}\n\nstatic gboolean\nparse_codec_parameters(GSList *attrs, struct sdpcodec *codec)\n{\n\tconst gchar* params;\n\tint i = 0;\n\n\twhile((params = sipe_utils_nameval_find_instance(attrs, \"fmtp\", i++))) {\n\t\tgchar **tokens;\n\t\tgchar **param;\n\n\t\ttokens = g_strsplit(params, \" \", 0);\n\t\tif (g_strv_length(tokens) < 1) {\n\t\t\tg_strfreev(tokens);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (atoi(tokens[0]) != codec->id) {\n\t\t\tg_strfreev(tokens);\n\t\t\tcontinue;\n\t\t}\n\n\t\tfor (param = tokens + 1; *param; ++param) {\n\t\t\tgchar **nameval = g_strsplit(*param, \"=\", 2);\n\n\t\t\tif (g_strv_length(nameval) != 2) {\n\t\t\t\tg_strfreev(nameval);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcodec->parameters =\n\t\t\t\t\tsipe_utils_nameval_add(codec->parameters,\n\t\t\t\t\t\t\t       nameval[0],\n\t\t\t\t\t\t\t       nameval[1]);\n\n\t\t\tg_strfreev(nameval);\n\t\t}\n\n\t\tg_strfreev(tokens);\n\t}\n\n\treturn TRUE;\n}\n\n\nstatic gboolean\nparse_codecs(GSList *attrs, SipeMediaType type, GSList **codecs)\n{\n\tint i = 0;\n\tconst gchar *attr;\n\n\twhile ((attr = sipe_utils_nameval_find_instance(attrs, \"rtpmap\", i++))) {\n\t\tstruct sdpcodec *codec;\n\t\tgchar **tokens;\n\n\t\ttokens = g_strsplit_set(attr, \" /\", 4);\n\t\tif (g_strv_length(tokens) < 3) {\n\t\t\tg_strfreev(tokens);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tcodec = g_new0(struct sdpcodec, 1);\n\t\tcodec->id = atoi(tokens[0]);\n\t\tcodec->name = g_strdup(tokens[1]);\n\t\tcodec->clock_rate = atoi(tokens[2]);\n\t\tcodec->type = type;\n\n\t\tif (type == SIPE_MEDIA_AUDIO) {\n\t\t\tcodec->channels = tokens[3] ? atoi(tokens[3]) : 1;\n\t\t}\n\n\t\tg_strfreev(tokens);\n\n\t\tif (!parse_codec_parameters(attrs, codec)) {\n\t\t\tsdpcodec_free(codec);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t*codecs = g_slist_append(*codecs, codec);\n\t}\n\n\treturn TRUE;\n}\n\nstatic void\nparse_encryption_key(GSList *attrs, guchar **key, int *key_id)\n{\n\tint i = 0;\n\tconst gchar *attr;\n\n\twhile ((attr = sipe_utils_nameval_find_instance(attrs, \"crypto\", i++))) {\n\t\tgchar **tokens = g_strsplit_set(attr, \" :|\", 6);\n\n\t\tif (tokens[0] && tokens[1] && tokens[2] && tokens[3] && tokens[4] &&\n\t\t    sipe_strcase_equal(tokens[1], \"AES_CM_128_HMAC_SHA1_80\") &&\n\t\t    sipe_strequal(tokens[2], \"inline\") &&\n\t\t    !tokens[5]) {\n\t\t\tgsize key_len;\n\t\t\t*key = g_base64_decode(tokens[3], &key_len);\n\t\t\tif (key_len != SIPE_SRTP_KEY_LEN) {\n\t\t\t\tg_free(*key);\n\t\t\t\t*key = NULL;\n\t\t\t}\n\t\t\t*key_id = atoi(tokens[0]);\n\t\t}\n\n\t\tg_strfreev(tokens);\n\n\t\tif (*key) {\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nstruct sdpmsg *\nsdpmsg_parse_msg(const gchar *msg)\n{\n\tstruct sdpmsg *smsg = g_new0(struct sdpmsg, 1);\n\tGSList *i;\n\n\tif (!parse_attributes(smsg, msg)) {\n\t\tsdpmsg_free(smsg);\n\t\treturn NULL;\n\t}\n\n\tsmsg->ice_version = SIPE_ICE_NO_ICE;\n\tfor (i = smsg->media; i; i = i->next) {\n\t\tstruct sdpmedia *media = i->data;\n\t\tSipeMediaType type;\n\t\tSipeIceVersion detected_ice_version;\n\n\t\tif (!parse_candidates(media->attributes, &detected_ice_version,\n\t\t\t\t      &media->candidates)) {\n\t\t\tsdpmsg_free(smsg);\n\t\t\treturn NULL;\n\t\t}\n\n\t\tif (media->port != 0) {\n\t\t\tsmsg->ice_version = detected_ice_version;\n\n\t\t\tif (!media->candidates) {\n\t\t\t\t// No a=candidate in SDP message, this seems to be MSOC 2005\n\t\t\t\tmedia->candidates = create_legacy_candidates(smsg->ip, media->port);\n\t\t\t}\n\t\t}\n\n\t\tif (sipe_strequal(media->name, \"audio\"))\n\t\t\ttype = SIPE_MEDIA_AUDIO;\n\t\telse if (sipe_strequal(media->name, \"video\"))\n\t\t\ttype = SIPE_MEDIA_VIDEO;\n\t\telse if (sipe_strequal(media->name, \"data\"))\n\t\t\ttype = SIPE_MEDIA_APPLICATION;\n\t\telse if (sipe_strequal(media->name, \"applicationsharing\"))\n\t\t\ttype = SIPE_MEDIA_APPLICATION;\n\t\telse {\n\t\t\t// Unknown media type\n\t\t\tsdpmsg_free(smsg);\n\t\t\treturn NULL;\n\t\t}\n\n\t\tif (!parse_codecs(media->attributes, type, &media->codecs)) {\n\t\t\tsdpmsg_free(smsg);\n\t\t\treturn NULL;\n\t\t}\n\n\t\tparse_encryption_key(media->attributes, &media->encryption_key,\n\t\t\t\t&media->encryption_key_id);\n\t}\n\n\treturn smsg;\n}\n\nstatic gchar *\ncodecs_to_string(GSList *codecs)\n{\n\tGString *result = g_string_new(NULL);\n\n\tfor (; codecs; codecs = codecs->next) {\n\t\tstruct sdpcodec *c = codecs->data;\n\t\tGSList *params = c->parameters;\n\n\t\tg_string_append_printf(result,\n\t\t\t\t       \"a=rtpmap:%d %s/%d\\r\\n\",\n\t\t\t\t       c->id,\n\t\t\t\t       c->name,\n\t\t\t\t       c->clock_rate);\n\n\t\tif (params) {\n\t\t\tGString *param_str = g_string_new(NULL);\n\t\t\tint written_params = 0;\n\n\t\t\tg_string_append_printf(param_str, \"a=fmtp:%d\", c->id);\n\n\t\t\tfor (; params; params = params->next) {\n\t\t\t\tstruct sipnameval* par = params->data;\n\t\t\t\tif (sipe_strequal(par->name, \"farsight-send-profile\")) {\n\t\t\t\t\t// Lync AVMCU doesn't like this property.\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tg_string_append_printf(param_str, \" %s=%s\",\n\t\t\t\t\t\t       par->name, par->value);\n\t\t\t\t++written_params;\n\t\t\t}\n\n\t\t\tg_string_append(param_str, \"\\r\\n\");\n\n\t\t\tif (written_params > 0) {\n\t\t\t\tg_string_append(result, param_str->str);\n\t\t\t}\n\n\t\t\tg_string_free(param_str, TRUE);\n\t\t}\n\t}\n\n\treturn g_string_free(result, FALSE);\n}\n\nstatic gchar *\ncodec_ids_to_string(GSList *codecs)\n{\n\tGString *result = g_string_new(NULL);\n\n\tfor (; codecs; codecs = codecs->next) {\n\t\tstruct sdpcodec *c = codecs->data;\n\t\tg_string_append_printf(result, \" %d\", c->id);\n\t}\n\n\treturn g_string_free(result, FALSE);\n}\n\nstatic gchar *\nbase64_unpad(const gchar *str)\n{\n\tgchar *result = g_strdup(str);\n\tgchar *ptr;\n\n\tfor (ptr = result + strlen(result); ptr != result; --ptr) {\n\t\tif (*(ptr - 1) != '=') {\n\t\t\t*ptr = '\\0';\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn result;\n}\n\nstatic gchar *\ncandidates_to_string(GSList *candidates, SipeIceVersion ice_version)\n{\n\tGString *result = g_string_new(\"\");\n\tGSList *i;\n\tGSList *processed_tcp_candidates = NULL;\n\n\tfor (i = candidates; i; i = i->next) {\n\t\tstruct sdpcandidate *c = i->data;\n\t\tconst gchar *protocol;\n\t\tconst gchar *type;\n\t\tgchar *related = NULL;\n\n\t\tif (ice_version == SIPE_ICE_RFC_5245) {\n\n\t\t\tswitch (c->protocol) {\n\t\t\t\tcase SIPE_NETWORK_PROTOCOL_TCP_ACTIVE:\n\t\t\t\t\tprotocol = \"TCP-ACT\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase SIPE_NETWORK_PROTOCOL_TCP_PASSIVE:\n\t\t\t\t\tprotocol = \"TCP-PASS\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase SIPE_NETWORK_PROTOCOL_UDP:\n\t\t\t\t\tprotocol = \"UDP\";\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t/* error unknown/unsupported type */\n\t\t\t\t\tprotocol = \"UNKNOWN\";\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tswitch (c->type) {\n\t\t\t\tcase SIPE_CANDIDATE_TYPE_HOST:\n\t\t\t\t\ttype = \"host\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase SIPE_CANDIDATE_TYPE_RELAY:\n\t\t\t\t\ttype = \"relay\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase SIPE_CANDIDATE_TYPE_SRFLX:\n\t\t\t\t\ttype = \"srflx\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase SIPE_CANDIDATE_TYPE_PRFLX:\n\t\t\t\t\ttype = \"prflx\";\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t/* error unknown/unsupported type */\n\t\t\t\t\ttype = \"unknown\";\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tswitch (c->type) {\n\t\t\t\tcase SIPE_CANDIDATE_TYPE_RELAY:\n\t\t\t\tcase SIPE_CANDIDATE_TYPE_SRFLX:\n\t\t\t\tcase SIPE_CANDIDATE_TYPE_PRFLX:\n\t\t\t\t\trelated = g_strdup_printf(\"raddr %s rport %d\",\n\t\t\t\t\t\t\t\t  c->base_ip,\n\t\t\t\t\t\t\t\t  c->base_port);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tg_string_append_printf(result,\n\t\t\t\t\t       \"a=candidate:%s %u %s %u %s %d typ %s %s\\r\\n\",\n\t\t\t\t\t       c->foundation,\n\t\t\t\t\t       c->component,\n\t\t\t\t\t       protocol,\n\t\t\t\t\t       c->priority,\n\t\t\t\t\t       c->ip,\n\t\t\t\t\t       c->port,\n\t\t\t\t\t       type,\n\t\t\t\t\t       related ? related : \"\");\n\t\t\tg_free(related);\n\n\t\t} else if (ice_version == SIPE_ICE_DRAFT_6) {\n\t\t\tgchar *username;\n\t\t\tgchar *password;\n\n\t\t\tswitch (c->protocol) {\n\t\t\t\tcase SIPE_NETWORK_PROTOCOL_TCP_ACTIVE:\n\t\t\t\tcase SIPE_NETWORK_PROTOCOL_TCP_PASSIVE: {\n\t\t\t\t\tGSList *prev_cand = processed_tcp_candidates;\n\t\t\t\t\tfor (; prev_cand; prev_cand = prev_cand->next) {\n\t\t\t\t\t\tstruct sdpcandidate *c2 = (struct sdpcandidate *)prev_cand->data;\n\n\t\t\t\t\t\tif (sipe_strequal(c->ip, c2->ip) &&\n\t\t\t\t\t\t    c->component == c2->component) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (prev_cand) {\n\t\t\t\t\t\tprotocol = NULL;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tprotocol = \"TCP\";\n\t\t\t\t\t\tprocessed_tcp_candidates =\n\t\t\t\t\t\t\tg_slist_append(processed_tcp_candidates, c);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase SIPE_NETWORK_PROTOCOL_UDP:\n\t\t\t\t\tprotocol = \"UDP\";\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t/* unknown/unsupported type, ignore */\n\t\t\t\t\tprotocol = NULL;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (!protocol) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tusername = base64_unpad(c->username);\n\t\t\tpassword = base64_unpad(c->password);\n\n\t\t\tg_string_append_printf(result,\n\t\t\t\t\t       \"a=candidate:%s %u %s %s 0.%u %s %d\\r\\n\",\n\t\t\t\t\t       username,\n\t\t\t\t\t       c->component,\n\t\t\t\t\t       password,\n\t\t\t\t\t       protocol,\n\t\t\t\t\t       c->priority,\n\t\t\t\t\t       c->ip,\n\t\t\t\t\t       c->port);\n\n\t\t\tg_free(username);\n\t\t\tg_free(password);\n\t\t}\n\t}\n\n\tg_slist_free(processed_tcp_candidates);\n\n\treturn g_string_free(result, FALSE);\n}\n\nstatic gint\nremote_candidates_sort_cb(struct sdpcandidate *c1, struct sdpcandidate *c2)\n{\n\treturn c1->component - c2->component;\n}\n\nstatic gchar *\nremote_candidates_to_string(GSList *candidates, SipeIceVersion ice_version)\n{\n\tGString *result = g_string_new(\"\");\n\n\tif (candidates) {\n\t\t// Sort the candidates by increasing component IDs.\n\t\tcandidates = g_slist_sort(candidates,\n\t\t\t\t\t  (GCompareFunc)remote_candidates_sort_cb);\n\n\t\tif (ice_version == SIPE_ICE_RFC_5245) {\n\t\t\tGSList *i;\n\t\t\tg_string_append(result, \"a=remote-candidates:\");\n\n\t\t\tfor (i = candidates; i; i = i->next) {\n\t\t\t\tstruct sdpcandidate *c = i->data;\n\t\t\t\tg_string_append_printf(result, \"%u %s %u \",\n\t\t\t\t\t\t       c->component, c->ip, c->port);\n\t\t\t}\n\n\t\t\tg_string_append(result, \"\\r\\n\");\n\t\t} else if (ice_version == SIPE_ICE_DRAFT_6) {\n\t\t\tstruct sdpcandidate *c = candidates->data;\n\t\t\tg_string_append_printf(result, \"a=remote-candidate:%s\\r\\n\",\n\t\t\t\t\t       c->username);\n\t\t}\n\t}\n\n\treturn g_string_free(result, FALSE);\n}\n\nstatic gchar *\nattributes_to_string(GSList *attributes)\n{\n\tGString *result = g_string_new(\"\");\n\n\tfor (; attributes; attributes = attributes->next) {\n\t\tstruct sipnameval *a = attributes->data;\n\t\tg_string_append_printf(result, \"a=%s\", a->name);\n\t\tif (!sipe_strequal(a->value, \"\"))\n\t\t\tg_string_append_printf(result, \":%s\", a->value);\n\t\tg_string_append(result, \"\\r\\n\");\n\t}\n\n\treturn g_string_free(result, FALSE);\n}\n\nstatic gchar *\nmedia_to_string(const struct sdpmsg *msg, const struct sdpmedia *media)\n{\n\tgchar *media_str;\n\n\tgchar *transport_profile = NULL;\n\n\tgchar *media_conninfo = NULL;\n\n\tgchar *codecs_str = NULL;\n\tgchar *codec_ids_str = codec_ids_to_string(media->codecs);\n\n\tgchar *candidates_str = NULL;\n\tgchar *remote_candidates_str = NULL;\n\n\tgchar *attributes_str = NULL;\n\tgchar *credentials = NULL;\n\n\tgchar *crypto = NULL;\n\n\tgboolean uses_tcp_transport = TRUE;\n\n\tif (media->port != 0) {\n\t\tif (!sipe_strequal(msg->ip, media->ip)) {\n\t\t\tmedia_conninfo = g_strdup_printf(\"c=IN %s %s\\r\\n\",\n\t\t\t\t\t\t\t sipe_utils_ip_sdp_address_marker(media->ip),\n\t\t\t\t\t\t\t media->ip);\n\t\t}\n\n\t\tcodecs_str = codecs_to_string(media->codecs);\n\t\tcandidates_str = candidates_to_string(media->candidates, msg->ice_version);\n\t\tremote_candidates_str = remote_candidates_to_string(media->remote_candidates,\n\t\t\t\t\t\t\t\t    msg->ice_version);\n\n\t\tif (media->remote_candidates) {\n\t\t\tstruct sdpcandidate *c = media->remote_candidates->data;\n\t\t\tuses_tcp_transport =\n\t\t\t\tc->protocol == SIPE_NETWORK_PROTOCOL_TCP_ACTIVE ||\n\t\t\t\tc->protocol == SIPE_NETWORK_PROTOCOL_TCP_PASSIVE ||\n\t\t\t\tc->protocol == SIPE_NETWORK_PROTOCOL_TCP_SO;\n\t\t} else {\n\t\t\tGSList *candidates = media->candidates;\n\t\t\tfor (; candidates; candidates = candidates->next) {\n\t\t\t\tstruct sdpcandidate *c = candidates->data;\n\t\t\t\tif (c->protocol == SIPE_NETWORK_PROTOCOL_UDP) {\n\t\t\t\t\tuses_tcp_transport = FALSE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tattributes_str = attributes_to_string(media->attributes);\n\n\t\tif (msg->ice_version == SIPE_ICE_RFC_5245 && media->candidates) {\n\t\t\tstruct sdpcandidate *c = media->candidates->data;\n\n\t\t\tcredentials = g_strdup_printf(\"a=ice-ufrag:%s\\r\\n\"\n\t\t\t\t\t\t      \"a=ice-pwd:%s\\r\\n\",\n\t\t\t\t\t\t      c->username,\n\t\t\t\t\t\t      c->password);\n\t\t}\n\n\t\tif (media->encryption_key) {\n\t\t\tgchar *key_encoded = g_base64_encode(media->encryption_key, SIPE_SRTP_KEY_LEN);\n\t\t\tcrypto = g_strdup_printf(\"a=crypto:%d AES_CM_128_HMAC_SHA1_80 inline:%s|2^31\\r\\n\",\n\t\t\t\t\tmedia->encryption_key_id, key_encoded);\n\t\t\tg_free(key_encoded);\n\t\t}\n\t}\n\n\ttransport_profile = g_strdup_printf(\"%sRTP/%sAVP\",\n\t\t\t\t\t    uses_tcp_transport ? \"TCP/\" : \"\",\n\t\t\t\t\t    media->encryption_active ? \"S\" : \"\");\n\n\tmedia_str = g_strdup_printf(\"m=%s %d %s%s\\r\\n\"\n\t\t\t\t    \"%s\"\n\t\t\t\t    \"%s\"\n\t\t\t\t    \"%s\"\n\t\t\t\t    \"%s\"\n\t\t\t\t    \"%s\"\n\t\t\t\t    \"%s\"\n\t\t\t\t    \"%s\",\n\t\t\t\t    media->name, media->port, transport_profile, codec_ids_str,\n\t\t\t\t    media_conninfo ? media_conninfo : \"\",\n\t\t\t\t    candidates_str ? candidates_str : \"\",\n\t\t\t\t    crypto ? crypto : \"\",\n\t\t\t\t    remote_candidates_str ? remote_candidates_str : \"\",\n\t\t\t\t    codecs_str ? codecs_str : \"\",\n\t\t\t\t    attributes_str ? attributes_str : \"\",\n\t\t\t\t    credentials ? credentials : \"\");\n\n\tg_free(transport_profile);\n\tg_free(media_conninfo);\n\tg_free(codecs_str);\n\tg_free(codec_ids_str);\n\tg_free(candidates_str);\n\tg_free(remote_candidates_str);\n\tg_free(attributes_str);\n\tg_free(credentials);\n\tg_free(crypto);\n\n\treturn media_str;\n}\n\ngchar *\nsdpmsg_to_string(const struct sdpmsg *msg)\n{\n\tGString *body = g_string_new(NULL);\n\tGSList *i;\n\tconst gchar *marker = sipe_utils_ip_sdp_address_marker(msg->ip);\n\n\tg_string_append_printf(\n\t\tbody,\n\t\t\"v=0\\r\\n\"\n\t\t\"o=- 0 0 IN %s %s\\r\\n\"\n\t\t\"s=session\\r\\n\"\n\t\t\"c=IN %s %s\\r\\n\"\n\t\t\"b=CT:99980\\r\\n\"\n\t\t\"t=0 0\\r\\n\",\n\t\tmarker, msg->ip,\n\t\tmarker, msg->ip);\n\n\n\tfor (i = msg->media; i; i = i->next) {\n\t\tgchar *media_str = media_to_string(msg, i->data);\n\t\tg_string_append(body, media_str);\n\t\tg_free(media_str);\n\t}\n\n\treturn g_string_free(body, FALSE);\n}\n\nstatic struct sdpcandidate *\nsdpcandidate_copy(struct sdpcandidate *candidate)\n{\n\tif (candidate) {\n\t\tstruct sdpcandidate *copy = g_new0(struct sdpcandidate, 1);\n\n\t\tcopy->foundation = g_strdup(candidate->foundation);\n\t\tcopy->component  = candidate->component;\n\t\tcopy->type       = candidate->type;\n\t\tcopy->protocol   = candidate->protocol;\n\t\tcopy->priority   = candidate->priority;\n\t\tcopy->ip         = g_strdup(candidate->ip);\n\t\tcopy->port       = candidate->port;\n\t\tcopy->base_ip    = g_strdup(candidate->base_ip);\n\t\tcopy->base_port  = candidate->base_port;\n\t\tcopy->username   = g_strdup(candidate->username);\n\t\tcopy->password   = g_strdup(candidate->password);\n\n\t\treturn copy;\n\t} else\n\t\treturn NULL;\n}\n\nvoid\nsdpcandidate_free(struct sdpcandidate *candidate)\n{\n\tif (candidate) {\n\t\tg_free(candidate->foundation);\n\t\tg_free(candidate->ip);\n\t\tg_free(candidate->base_ip);\n\t\tg_free(candidate->username);\n\t\tg_free(candidate->password);\n\t\tg_free(candidate);\n\t}\n}\n\nvoid\nsdpcodec_free(struct sdpcodec *codec)\n{\n\tif (codec) {\n\t\tg_free(codec->name);\n\t\tsipe_utils_nameval_free(codec->parameters);\n\t\tg_free(codec);\n\t}\n}\n\nvoid\nsdpmedia_free(struct sdpmedia *media)\n{\n\tif (media) {\n\t\tg_free(media->name);\n\t\tg_free(media->ip);\n\n\t\tsipe_utils_nameval_free(media->attributes);\n\n\t\tsipe_utils_slist_free_full(media->candidates,\n\t\t\t\t  (GDestroyNotify) sdpcandidate_free);\n\t\tsipe_utils_slist_free_full(media->codecs,\n\t\t\t\t  (GDestroyNotify) sdpcodec_free);\n\t\tsipe_utils_slist_free_full(media->remote_candidates,\n\t\t\t\t  (GDestroyNotify) sdpcandidate_free);\n\n\t\tg_free(media->encryption_key);\n\n\t\tg_free(media);\n\t}\n}\n\nvoid\nsdpmsg_free(struct sdpmsg *msg)\n{\n\tif (msg) {\n\t\tg_free(msg->ip);\n\t\tsipe_utils_slist_free_full(msg->media,\n\t\t\t\t  (GDestroyNotify) sdpmedia_free);\n\t\tg_free(msg);\n\t}\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sdpmsg.h",
    "content": "/**\n * @file sdpmsg.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2014-2017 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2010 Jakub Adam <jakub.adam@ktknet.cz>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\nstruct sdpmsg {\n\tgchar\t\t*ip;    /* currently this has to be an IPv4 address */\n\tGSList\t\t*media;\n\tSipeIceVersion\t ice_version;\n};\n\nstruct sdpmedia {\n\tgchar\t\t*name;\n\tgchar\t\t*ip;    /* currently this has to be an IPv4 address */\n\tguint\t\t port;\n\n\tGSList\t\t*attributes;\n\tGSList\t\t*candidates;\n\tGSList\t\t*codecs;\n\tGSList\t\t*remote_candidates;\n\n\tguchar\t\t*encryption_key;\n\tint\t\t encryption_key_id;\n\tgboolean\t encryption_active;\n};\n\nstruct sdpcandidate {\n\tgchar\t\t\t*foundation;\n\tSipeComponentType\t component;\n\tSipeCandidateType\t type;\n\tSipeNetworkProtocol\t protocol;\n\tguint32\t\t\t priority;\n\tgchar\t\t\t*ip; /* currently this has to be an IPv4 address */\n\tguint\t\t\t port;\n\tgchar\t\t\t*base_ip;\n\tguint\t\t\t base_port;\n\tgchar\t\t\t*username;\n\tgchar\t\t\t*password;\n};\n\nstruct sdpcodec {\n\tgint\t\t id;\n\tgchar\t\t*name;\n\tgint\t\t clock_rate;\n\tgint\t\t channels;\n\tSipeMediaType\t type;\n\tGSList\t\t*parameters;\n};\n\n/**\n * Parses SDP message into @c sdpmsg structure.\n *\n * @param msg SDP message as character string\n *\n * @return New @c sdpmsg or NULL if message can not be parsed.\n */\nstruct sdpmsg *sdpmsg_parse_msg(const gchar *msg);\n\n/**\n * Creates a SDP message from the @c sdpmsg structure.\n *\n * @param msg a @c sdpmsg\n *\n * @return SDP message as a character string that must be g_free'd after use.\n */\ngchar *sdpmsg_to_string(const struct sdpmsg *msg);\n\n/**\n * Deallocates @c sdpmsg.\n */\nvoid sdpmsg_free(struct sdpmsg *msg);\n\n/**\n * Deallocates @c sdpcandidate.\n */\nvoid sdpcandidate_free(struct sdpcandidate *candidate);\n\n/**\n * Deallocates @c sdpcodec.\n */\nvoid sdpcodec_free(struct sdpcodec *codec);\n\n/**\n * Deallocates @c sdpmedia.\n */\nvoid sdpmedia_free(struct sdpmedia *media);\n"
  },
  {
    "path": "src/core/sip-csta.c",
    "content": "/**\n * @file sip-csta.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-11 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2009 pier11 <pier11@operamail.com>\n *\n * Implements Remote Call Control (RCC) feature for\n * integration with legacy enterprise PBX (wired telephony) systems.\n * Should be applicable to 2005 and 2007(R2) systems.\n * Inderlying XML protocol CSTA is defined in ECMA-323.\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipmsg.h\"\n#include \"sip-csta.h\"\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-dialog.h\"\n#include \"sipe-schedule.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n\n#define ORIGINATED_CSTA_STATUS          \"originated\"\n#define DELIVERED_CSTA_STATUS           \"delivered\"\n#define ESTABLISHED_CSTA_STATUS         \"established\"\n\n/**\n * Data model for interaction with SIP/CSTA Gateway\n */\nstruct sip_csta {\n\tgchar *line_uri;\n\t/** SIP/CSTA Gateway's SIP URI */\n\tgchar *gateway_uri;\n\t/** dialog with SIP/CSTA Gateway */\n\tstruct sip_dialog *dialog;\n\n\tgchar *gateway_status;\n\tgchar *monitor_cross_ref_id;\n\n\tgchar *line_status;\n\t/** destination tel: URI */\n\tgchar *to_tel_uri;\n\tgchar *call_id;\n\t/* our device ID as reported by SIP/CSTA gateway */\n\tgchar *device_id;\n};\n\n/**\n * Sends CSTA RequestSystemStatus request to SIP/CSTA Gateway.\n * @param line_uri (%s) Ex.: tel:73124;phone-context=dialstring;partition=BE_BRS_INT\n */\n#define SIP_SEND_CSTA_REQUEST_SYSTEM_STATUS \\\n\"<?xml version=\\\"1.0\\\"?>\"\\\n\"<RequestSystemStatus xmlns=\\\"http://www.ecma-international.org/standards/ecma-323/csta/ed3\\\">\"\\\n    \"<extensions>\"\\\n        \"<privateData>\"\\\n            \"<private>\"\\\n                \"<lcs:line xmlns:lcs=\\\"http://schemas.microsoft.com/Lcs/2005/04/RCCExtension\\\">%s</lcs:line>\"\\\n            \"</private>\"\\\n        \"</privateData>\"\\\n    \"</extensions>\"\\\n\"</RequestSystemStatus>\"\n\n/**\n * Sends CSTA GetCSTAFeatures request to SIP/CSTA Gateway.\n * @param line_uri (%s) Ex.: tel:73124;phone-context=dialstring;partition=BE_BRS_INT\n */\n#define SIP_SEND_CSTA_GET_CSTA_FEATURES \\\n\"<?xml version=\\\"1.0\\\"?>\"\\\n\"<GetCSTAFeatures xmlns=\\\"http://www.ecma-international.org/standards/ecma-323/csta/ed3\\\">\"\\\n\t\"<extensions>\"\\\n\t\t\"<privateData>\"\\\n\t\t\t\"<private>\"\\\n\t\t\t\t\"<lcs:line xmlns:lcs=\\\"http://schemas.microsoft.com/Lcs/2005/04/RCCExtension\\\">%s</lcs:line>\"\\\n\t\t\t\"</private>\"\\\n\t\t\"</privateData>\"\\\n\t\"</extensions>\"\\\n\"</GetCSTAFeatures>\"\n\n/**\n * Sends CSTA start monitor request to SIP/CSTA Gateway.\n * @param line_uri (%s) Ex.: tel:73124;phone-context=dialstring;partition=BE_BRS_INT\n */\n#define SIP_SEND_CSTA_MONITOR_START \\\n\"<?xml version=\\\"1.0\\\"?>\"\\\n\"<MonitorStart xmlns=\\\"http://www.ecma-international.org/standards/ecma-323/csta/ed3\\\">\"\\\n    \"<monitorObject>\"\\\n        \"<deviceObject>%s</deviceObject>\"\\\n    \"</monitorObject>\"\\\n\"</MonitorStart>\"\n\n/**\n * Sends CSTA stop monitor request to SIP/CSTA Gateway.\n * @param monitor_cross_ref_id (%s) Ex.: 99fda87c\n */\n#define SIP_SEND_CSTA_MONITOR_STOP \\\n\"<?xml version=\\\"1.0\\\"?>\"\\\n\"<MonitorStop xmlns=\\\"http://www.ecma-international.org/standards/ecma-323/csta/ed3\\\">\"\\\n\t\"<monitorCrossRefID>%s</monitorCrossRefID>\"\\\n\"</MonitorStop>\"\n\n/**\n * Sends CSTA make call request to SIP/CSTA Gateway.\n * @param line_uri (%s) Ex.: tel:73124;phone-context=dialstring;partition=BE_BRS_INT\n * @param to_tel_uri (%s) Ex.: tel:+3222220220\n */\n#define SIP_SEND_CSTA_MAKE_CALL \\\n\"<?xml version=\\\"1.0\\\"?>\"\\\n\"<MakeCall xmlns=\\\"http://www.ecma-international.org/standards/ecma-323/csta/ed3\\\">\"\\\n    \"<callingDevice>%s</callingDevice>\"\\\n    \"<calledDirectoryNumber>%s</calledDirectoryNumber>\"\\\n    \"<autoOriginate>doNotPrompt</autoOriginate>\"\\\n\"</MakeCall>\"\n\n/**\n * Sends CSTA ClearConnection request to SIP/CSTA Gateway.\n * @param call_id   (%s)  Ex.: 0_99f261b4\n * @param device_id (%s)  Same as in OriginatedEvent, DeliveredEvent notifications.\n *                        Ex.: tel:73124;phone-context=dialstring\n */\n#define SIP_SEND_CSTA_CLEAR_CONNECTION \\\n\"<?xml version=\\\"1.0\\\"?>\"\\\n\"<ClearConnection xmlns=\\\"http://www.ecma-international.org/standards/ecma-323/csta/ed3\\\">\"\\\n\t\"<connectionToBeCleared>\"\\\n\t\t\"<callID>%s</callID>\"\\\n\t\t\"<deviceID>%s</deviceID>\"\\\n\t\"</connectionToBeCleared>\"\\\n\"</ClearConnection>\"\n\n\nstatic gchar *\nsip_to_tel_uri0(const gchar *phone)\n{\n\tif (!phone || strlen(phone) == 0) return NULL;\n\n\tif (g_str_has_prefix(phone, \"tel:\")) {\n\t\treturn g_strdup(phone);\n\t} else {\n\t\tgchar *tel_uri = g_malloc(strlen(phone) + 4 + 1);\n\t\tgchar *dest_p = g_stpcpy(tel_uri, \"tel:\");\n\t\tfor (; *phone; phone++) {\n\t\t\tif (*phone == ' ') continue;\n\t\t\tif (*phone == '(') continue;\n\t\t\tif (*phone == ')') continue;\n\t\t\tif (*phone == '-') continue;\n\t\t\tif (*phone == '.') continue;\n\t\t\t*dest_p++ = *phone;\n\t\t}\n\t\t*dest_p = '\\0';\n\t\treturn tel_uri;\n\t}\n}\n\ngchar *\nsip_to_tel_uri(const gchar *phone)\n{\n\tgchar *res = sip_to_tel_uri0(phone);\n\tgchar *v;\n\t/* strips everything starting with 'v:' if any */\n\tif (res && (v = strstr(res, \"v:\"))) {\n\t\tgchar *tmp = res;\n\n\t\tres = g_strndup(res, v - res);\n\t\tg_free(tmp);\n\t\treturn res;\n\t}\n\treturn res;\n}\n\ngchar *\nsip_tel_uri_denormalize(const gchar *tel_uri)\n{\n\tif (!tel_uri) return NULL;\n\n\tif (g_str_has_prefix(tel_uri, \"tel:\")) {\n\t\treturn g_strdup(tel_uri + 4);\n\t} else {\n\t\treturn g_strdup(tel_uri);\n\t}\n}\n\nstatic void\nsip_csta_initialize(struct sipe_core_private *sipe_private,\n\t\t    const gchar *line_uri,\n\t\t    const gchar *server)\n{\n\tif(!sipe_private->csta) {\n\t\tsipe_private->csta = g_new0(struct sip_csta, 1);\n\t\tsipe_private->csta->line_uri = g_strdup(line_uri);\n\t\tsipe_private->csta->gateway_uri = g_strdup(server);\n\t} else {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_csta_initialize: sipe_private->csta is already instantiated, exiting.\");\n\t}\n}\n\n/** get CSTA feautures's callback */\nstatic gboolean\nprocess_csta_get_features_response(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private,\n\t\t\t\t   struct sipmsg *msg,\n\t\t\t\t   SIPE_UNUSED_PARAMETER struct transaction *trans)\n{\n\tif (msg->response >= 400) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_csta_get_features_response: Get CSTA features response is not 200. Failed to get features.\");\n\t\t/* @TODO notify user of failure to get CSTA features */\n\t\treturn FALSE;\n\t}\n\telse if (msg->response == 200) {\n\t\tSIPE_DEBUG_INFO(\"process_csta_get_features_response:\\n%s\", msg->body ? msg->body : \"\");\n\t}\n\n\treturn TRUE;\n}\n\n/** get CSTA feautures */\nstatic void\nsip_csta_get_features(struct sipe_core_private *sipe_private)\n{\n\tgchar *hdr;\n\tgchar *body;\n\n\tif (!sipe_private->csta || !sipe_private->csta->dialog || !sipe_private->csta->dialog->is_established) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_csta_get_features: no dialog with CSTA, exiting.\");\n\t\treturn;\n\t}\n\n\thdr = g_strdup(\n\t\t\"Content-Disposition: signal;handling=required\\r\\n\"\n\t\t\"Content-Type: application/csta+xml\\r\\n\");\n\n\tbody = g_strdup_printf(\n\t\tSIP_SEND_CSTA_GET_CSTA_FEATURES,\n\t\tsipe_private->csta->line_uri);\n\n\tsip_transport_info(sipe_private,\n\t\t\t   hdr,\n\t\t\t   body,\n\t\t\t   sipe_private->csta->dialog,\n\t\t\t   process_csta_get_features_response);\n\tg_free(body);\n\tg_free(hdr);\n}\n\n/** Monitor Start's callback */\nstatic gboolean\nprocess_csta_monitor_start_response(struct sipe_core_private *sipe_private,\n\t\t\t\t    struct sipmsg *msg,\n\t\t\t\t    SIPE_UNUSED_PARAMETER struct transaction *trans)\n{\n\tSIPE_DEBUG_INFO(\"process_csta_monitor_start_response:\\n%s\", msg->body ? msg->body : \"\");\n\n\tif (!sipe_private->csta) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_csta_monitor_start_response: sipe_private->csta is not initializzed, exiting\");\n\t\treturn FALSE;\n\t}\n\n\tif (msg->response >= 400) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_csta_monitor_start_response: Monitor Start response is not 200. Failed to start monitor.\");\n\t\t/* @TODO notify user of failure to start monitor */\n\t\treturn FALSE;\n\t}\n\telse if (msg->response == 200) {\n\t\tsipe_xml *xml = sipe_xml_parse(msg->body, msg->bodylen);\n\t\tg_free(sipe_private->csta->monitor_cross_ref_id);\n\t\tsipe_private->csta->monitor_cross_ref_id = sipe_xml_data(sipe_xml_child(xml, \"monitorCrossRefID\"));\n\t\tSIPE_DEBUG_INFO(\"process_csta_monitor_start_response: monitor_cross_ref_id=%s\",\n\t\t\t\tsipe_private->csta->monitor_cross_ref_id ? sipe_private->csta->monitor_cross_ref_id : \"\");\n\t\tsipe_xml_free(xml);\n\t}\n\n\treturn TRUE;\n}\n\n/** Monitor Start */\nstatic void\nsip_csta_monitor_start(struct sipe_core_private *sipe_private)\n{\n\tgchar *hdr;\n\tgchar *body;\n\n\tif (!sipe_private->csta || !sipe_private->csta->dialog || !sipe_private->csta->dialog->is_established) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_csta_monitor_start: no dialog with CSTA, exiting.\");\n\t\treturn;\n\t}\n\n\thdr = g_strdup(\n\t\t\"Content-Disposition: signal;handling=required\\r\\n\"\n\t\t\"Content-Type: application/csta+xml\\r\\n\");\n\n\tbody = g_strdup_printf(\n\t\tSIP_SEND_CSTA_MONITOR_START,\n\t\tsipe_private->csta->line_uri);\n\n\tsip_transport_info(sipe_private,\n\t\t\t   hdr,\n\t\t\t   body,\n\t\t\t   sipe_private->csta->dialog,\n\t\t\t   process_csta_monitor_start_response);\n\tg_free(body);\n\tg_free(hdr);\n}\n\n/** Monitor Stop */\nstatic void\nsip_csta_monitor_stop(struct sipe_core_private *sipe_private)\n{\n\tgchar *hdr;\n\tgchar *body;\n\n\tif (!sipe_private->csta || !sipe_private->csta->dialog || !sipe_private->csta->dialog->is_established) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_csta_monitor_stop: no dialog with CSTA, exiting.\");\n\t\treturn;\n\t}\n\n\tif (!sipe_private->csta->monitor_cross_ref_id) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_csta_monitor_stop: no monitor_cross_ref_id, exiting.\");\n\t\treturn;\n\t}\n\n\thdr = g_strdup(\n\t\t\"Content-Disposition: signal;handling=required\\r\\n\"\n\t\t\"Content-Type: application/csta+xml\\r\\n\");\n\n\tbody = g_strdup_printf(\n\t\tSIP_SEND_CSTA_MONITOR_STOP,\n\t\tsipe_private->csta->monitor_cross_ref_id);\n\n\tsip_transport_info(sipe_private,\n\t\t\t   hdr,\n\t\t\t   body,\n\t\t\t   sipe_private->csta->dialog,\n\t\t\t   NULL);\n\tg_free(body);\n\tg_free(hdr);\n}\n\nstatic void\nsipe_invite_csta_gateway(struct sipe_core_private *sipe_private,\n\t\t\t gpointer unused);\n\n/** a callback */\nstatic gboolean\nprocess_invite_csta_gateway_response(struct sipe_core_private *sipe_private,\n\t\t\t\t     struct sipmsg *msg,\n\t\t\t\t     SIPE_UNUSED_PARAMETER struct transaction *trans)\n{\n\tSIPE_DEBUG_INFO(\"process_invite_csta_gateway_response:\\n%s\", msg->body ? msg->body : \"\");\n\n\tif (!sipe_private->csta) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_invite_csta_gateway_response: sipe_private->csta is not initializzed, exiting\");\n\t\treturn FALSE;\n\t}\n\n\tif (!sipe_private->csta->dialog) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_invite_csta_gateway_response: GSTA dialog is NULL, exiting\");\n\t\treturn FALSE;\n\t}\n\n\tsipe_dialog_parse(sipe_private->csta->dialog, msg, TRUE);\n\n\tif (msg->response >= 200) {\n\t\t/* send ACK to CSTA */\n\t\tsipe_private->csta->dialog->cseq = 0;\n\t\tsip_transport_ack(sipe_private, sipe_private->csta->dialog);\n\t\tsipe_private->csta->dialog->outgoing_invite = NULL;\n\t\tsipe_private->csta->dialog->is_established = TRUE;\n\t}\n\n\tif (msg->response >= 400) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_invite_csta_gateway_response: INVITE response is not 200. Failed to join CSTA.\");\n\t\t/* @TODO notify user of failure to join CSTA */\n\t\treturn FALSE;\n\t}\n\telse if (msg->response == 200) {\n\t\tsipe_xml *xml = sipe_xml_parse(msg->body, msg->bodylen);\n\n\t\tg_free(sipe_private->csta->gateway_status);\n\t\tsipe_private->csta->gateway_status = sipe_xml_data(sipe_xml_child(xml, \"systemStatus\"));\n\t\tSIPE_DEBUG_INFO(\"process_invite_csta_gateway_response: gateway_status=%s\",\n\t\t\t\tsipe_private->csta->gateway_status ? sipe_private->csta->gateway_status : \"\");\n\t\tif (sipe_strcase_equal(sipe_private->csta->gateway_status, \"normal\")) {\n\t\t\tif (!sipe_private->csta->monitor_cross_ref_id) {\n\t\t\t\tsip_csta_get_features(sipe_private);\n\t\t\t\tsip_csta_monitor_start(sipe_private);\n\t\t\t}\n\t\t} else {\n\t\t\tSIPE_DEBUG_INFO(\"process_invite_csta_gateway_response: ERROR: CSTA status is %s, won't continue.\",\n\t\t\t\t\tsipe_private->csta->gateway_status);\n\t\t\t/* @TODO notify user of failure to join CSTA */\n\t\t}\n\t\tsipe_xml_free(xml);\n\n\t\t/* schedule re-invite. RFC4028 */\n\t\tif (sipe_private->csta->dialog->expires) {\n\t\t\tsipe_schedule_seconds(sipe_private,\n\t\t\t\t\t      \"<+csta>\",\n\t\t\t\t\t      NULL,\n\t\t\t\t\t      sipe_private->csta->dialog->expires - 60, /* 1 minute earlier */\n\t\t\t\t\t      sipe_invite_csta_gateway,\n\t\t\t\t\t      NULL);\n\t\t}\n\t}\n\n\treturn TRUE;\n}\n\n/** Creates long living dialog with SIP/CSTA Gateway */\n/*  should be re-entrant as require to sent re-invites every 10 min to refresh */\nstatic void\nsipe_invite_csta_gateway(struct sipe_core_private *sipe_private,\n\t\t\t SIPE_UNUSED_PARAMETER gpointer unused)\n{\n\tgchar *hdr;\n\tgchar *contact;\n\tgchar *body;\n\n\tif (!sipe_private->csta) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_invite_csta_gateway: sipe_private->csta is uninitialized, exiting\");\n\t\treturn;\n\t}\n\n\tif(!sipe_private->csta->dialog) {\n\t\tsipe_private->csta->dialog = g_new0(struct sip_dialog, 1);\n\t\tsipe_private->csta->dialog->callid = gencallid();\n\t\tsipe_private->csta->dialog->with = g_strdup(sipe_private->csta->gateway_uri);\n\t}\n\tif (!(sipe_private->csta->dialog->ourtag)) {\n\t\tsipe_private->csta->dialog->ourtag = gentag();\n\t}\n\n\tcontact = get_contact(sipe_private);\n\thdr = g_strdup_printf(\n\t\t\"Contact: %s\\r\\n\"\n\t\t\"Supported: timer\\r\\n\"\n\t\t\"Content-Disposition: signal;handling=required\\r\\n\"\n\t\t\"Content-Type: application/csta+xml\\r\\n\",\n\t\tcontact);\n\tg_free(contact);\n\n\tbody = g_strdup_printf(\n\t\tSIP_SEND_CSTA_REQUEST_SYSTEM_STATUS,\n\t\tsipe_private->csta->line_uri);\n\n\tsipe_private->csta->dialog->outgoing_invite =\n\t\tsip_transport_invite(sipe_private,\n\t\t\t\t     hdr,\n\t\t\t\t     body,\n\t\t\t\t     sipe_private->csta->dialog,\n\t\t\t\t     process_invite_csta_gateway_response);\n\tg_free(body);\n\tg_free(hdr);\n}\n\nvoid\nsip_csta_open(struct sipe_core_private *sipe_private,\n\t      const gchar *line_uri,\n\t      const gchar *server)\n{\n\tsip_csta_initialize(sipe_private, line_uri, server);\n\tsipe_invite_csta_gateway(sipe_private, NULL);\n}\n\nstatic void\nsip_csta_free(struct sip_csta *csta)\n{\n\tif (!csta) return;\n\n\tg_free(csta->line_uri);\n\tg_free(csta->gateway_uri);\n\n\tsipe_dialog_free(csta->dialog);\n\n\tg_free(csta->gateway_status);\n\tg_free(csta->monitor_cross_ref_id);\n\tg_free(csta->line_status);\n\tg_free(csta->to_tel_uri);\n\tg_free(csta->call_id);\n\tg_free(csta->device_id);\n\n\tg_free(csta);\n}\n\nvoid\nsip_csta_close(struct sipe_core_private *sipe_private)\n{\n\tif (sipe_private->csta) {\n\t\tsip_csta_monitor_stop(sipe_private);\n\t}\n\n\tif (sipe_private->csta && sipe_private->csta->dialog) {\n\t\t/* send BYE to CSTA */\n\t\tsip_transport_bye(sipe_private, sipe_private->csta->dialog);\n\t}\n\n\tsip_csta_free(sipe_private->csta);\n}\n\n\n\n/** Make Call's callback */\nstatic gboolean\nprocess_csta_make_call_response(struct sipe_core_private *sipe_private,\n\t\t\t\tstruct sipmsg *msg,\n\t\t\t\tSIPE_UNUSED_PARAMETER struct transaction *trans)\n{\n\tSIPE_DEBUG_INFO(\"process_csta_make_call_response:\\n%s\", msg->body ? msg->body : \"\");\n\n\tif (!sipe_private->csta) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_csta_make_call_response: sipe_private->csta is not initializzed, exiting\");\n\t\treturn FALSE;\n\t}\n\n\tif (msg->response >= 400) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_csta_make_call_response: Make Call response is not 200. Failed to make call.\");\n\t\t/* @TODO notify user of failure to make call */\n\t\treturn FALSE;\n\t}\n\telse if (msg->response == 200) {\n\t\tsipe_xml *xml;\n\t\tconst sipe_xml *xn_calling_device;\n\t\tgchar *device_id;\n\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_csta_make_call_response: SUCCESS\");\n\n\t\txml = sipe_xml_parse(msg->body, msg->bodylen);\n\t\txn_calling_device = sipe_xml_child(xml, \"callingDevice\");\n\t\tdevice_id = sipe_xml_data(sipe_xml_child(xn_calling_device, \"deviceID\"));\n\t\tif (sipe_strequal(sipe_private->csta->line_uri, device_id)) {\n\t\t\tg_free(sipe_private->csta->call_id);\n\t\t\tsipe_private->csta->call_id = sipe_xml_data(sipe_xml_child(xn_calling_device, \"callID\"));\n\t\t\tSIPE_DEBUG_INFO(\"process_csta_make_call_response: call_id=%s\", sipe_private->csta->call_id ? sipe_private->csta->call_id : \"\");\n\t\t}\n\t\tg_free(device_id);\n\t\tsipe_xml_free(xml);\n\t}\n\n\treturn TRUE;\n}\n\n/** Make Call */\nstatic void sip_csta_make_call(struct sipe_core_private *sipe_private,\n\t\t\t       const gchar* to_tel_uri)\n{\n\tgchar *hdr;\n\tgchar *body;\n\n\tif (!to_tel_uri) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_csta_make_call: no tel URI parameter provided, exiting.\");\n\t\treturn;\n\t}\n\n\tif (!sipe_private->csta || !sipe_private->csta->dialog || !sipe_private->csta->dialog->is_established) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_csta_make_call: no dialog with CSTA, exiting.\");\n\t\treturn;\n\t}\n\n\tg_free(sipe_private->csta->to_tel_uri);\n\tsipe_private->csta->to_tel_uri = g_strdup(to_tel_uri);\n\n\thdr = g_strdup(\n\t\t\"Content-Disposition: signal;handling=required\\r\\n\"\n\t\t\"Content-Type: application/csta+xml\\r\\n\");\n\n\tbody = g_strdup_printf(\n\t\tSIP_SEND_CSTA_MAKE_CALL,\n\t\tsipe_private->csta->line_uri,\n\t\tsipe_private->csta->to_tel_uri);\n\n\tsip_transport_info(sipe_private,\n\t\t\t   hdr,\n\t\t\t   body,\n\t\t\t   sipe_private->csta->dialog,\n\t\t\t   process_csta_make_call_response);\n\tg_free(body);\n\tg_free(hdr);\n}\n\nstatic void\nsip_csta_update_id_and_status(struct sip_csta *csta,\n\t\t\t      const sipe_xml *node,\n\t\t\t      const char *status)\n{\n\tgchar *call_id = sipe_xml_data(sipe_xml_child(node, \"callID\"));\n\n\tif (!sipe_strequal(call_id, csta->call_id)) {\n\t\tSIPE_DEBUG_INFO(\"sipe_csta_update_id_and_status: callID (%s) does not match\", call_id);\n\t}\n\telse\n\t{\n\t\t/* free old line status */\n\t\tg_free(csta->line_status);\n\t\tcsta->line_status = NULL;\n\n\t\tif (status)\n\t\t{\n\t\t\t/* save deviceID */\n\t\t\tgchar *device_id = sipe_xml_data(sipe_xml_child(node, \"deviceID\"));\n\t\t\tSIPE_DEBUG_INFO(\"sipe_csta_update_id_and_status: device_id=(%s)\", device_id ? device_id : \"\");\n\t\t\tif (device_id) {\n\t\t\t\tg_free(csta->device_id);\n\t\t\t\tcsta->device_id = device_id;\n\t\t\t}\n\n\t\t\t/* set new line status */\n\t\t\tcsta->line_status = g_strdup(status);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/* clean up cleared connection */\n\t\t\tg_free(csta->to_tel_uri);\n\t\t\tcsta->to_tel_uri = NULL;\n\t\t\tg_free(csta->call_id);\n\t\t\tcsta->call_id = NULL;\n\t\t\tg_free(csta->device_id);\n\t\t\tcsta->device_id = NULL;\n\t\t}\n\t}\n\n\tg_free(call_id);\n}\n\nvoid\nprocess_incoming_info_csta(struct sipe_core_private *sipe_private,\n\t\t\t   struct sipmsg *msg)\n{\n\tgchar *monitor_cross_ref_id;\n\tsipe_xml *xml = sipe_xml_parse(msg->body, msg->bodylen);\n\n\tif (!xml) return;\n\n\tmonitor_cross_ref_id = sipe_xml_data(sipe_xml_child(xml, \"monitorCrossRefID\"));\n\n\tif(!sipe_private->csta || !sipe_strequal(monitor_cross_ref_id, sipe_private->csta->monitor_cross_ref_id))\n\t{\n\t\tSIPE_DEBUG_INFO(\"process_incoming_info_csta: monitorCrossRefID (%s) does not match, exiting\",\n\t\t\t\tmonitor_cross_ref_id ? monitor_cross_ref_id : \"\");\n\t}\n\telse\n\t{\n\t\tif (sipe_strequal(sipe_xml_name(xml), \"OriginatedEvent\"))\n\t\t{\n\t\t\tsip_csta_update_id_and_status(sipe_private->csta,\n\t\t\t\t\t\t      sipe_xml_child(xml, \"originatedConnection\"),\n\t\t\t\t\t\t      ORIGINATED_CSTA_STATUS);\n\t\t}\n\t\telse if (sipe_strequal(sipe_xml_name(xml), \"DeliveredEvent\"))\n\t\t{\n\t\t\tsip_csta_update_id_and_status(sipe_private->csta,\n\t\t\t\t\t\t      sipe_xml_child(xml, \"connection\"),\n\t\t\t\t\t\t      DELIVERED_CSTA_STATUS);\n\t\t}\n\t\telse if (sipe_strequal(sipe_xml_name(xml), \"EstablishedEvent\"))\n\t\t{\n\t\t\tsip_csta_update_id_and_status(sipe_private->csta,\n\t\t\t\t\t\t      sipe_xml_child(xml, \"establishedConnection\"),\n\t\t\t\t\t\t      ESTABLISHED_CSTA_STATUS);\n\t\t}\n\t\telse if (sipe_strequal(sipe_xml_name(xml), \"ConnectionClearedEvent\"))\n\t\t{\n\t\t\tsip_csta_update_id_and_status(sipe_private->csta,\n\t\t\t\t\t\t      sipe_xml_child(xml, \"droppedConnection\"),\n\t\t\t\t\t\t      NULL);\n\t\t}\n\t}\n\n\tg_free(monitor_cross_ref_id);\n\tsipe_xml_free(xml);\n}\n\ngboolean sip_csta_is_idle(struct sipe_core_private *sipe_private)\n{\n\treturn(sipe_private->csta && !sipe_private->csta->line_status);\n}\n\nvoid sipe_core_buddy_make_call(struct sipe_core_public *sipe_public,\n\t\t\t       const gchar *phone)\n{\n\tif (phone) {\n\t\tgchar *tel_uri = sip_to_tel_uri(phone);\n\n\t\tSIPE_DEBUG_INFO(\"sipe_core_buddy_make_call: calling number: %s\",\n\t\t\t\ttel_uri ? tel_uri : \"\");\n\t\tsip_csta_make_call(SIPE_CORE_PRIVATE, tel_uri);\n\n\t\tg_free(tel_uri);\n\t}\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sip-csta.h",
    "content": "/**\n * @file sip-csta.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2009 pier11 <pier11@operamail.com>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/*\n * Interface dependencies:\n *\n * <glib.h>\n */\n\n/* Forward declarations */\nstruct sipmsg;\nstruct sipe_core_private;\n\n/**\n * Transform telephone number representation to tel: URI form.\n * Removes white space, parenthesis ( ), hyphen - symbols\n *\n * @param phone Ex. +32 2 245 00 00\n * @return Ex. tel:+3222450000 or @c NULL. Must be @c g_free()'d after use.\n */\ngchar *sip_to_tel_uri(const gchar *phone);\n\n/**\n * Transform telephone number from tel: URI representation\n * to more human readable form.\n * Removes tel: prefix if such exist.\n * (Maybe will add spaces in the future according to local phone patterns.)\n *\n * @param tel_uri Ex. tel:+3222450000\n * @return Ex. +3222450000. Must be @c g_free()'d after use.\n */\ngchar *sip_tel_uri_denormalize(const gchar *tel_uri);\n\n/**\n * Initializes CSTA\n *\n * @param line_uri (in) our line tel URI.            Ex.: tel:73124;phone-context=dialstring;partition=BE_BRS_INT\n * @param server   (in) SIP URI of SIP/CSTA Gateway. Ex.: sip:73124@euuklhccups01.eu.company.local\n */\nvoid sip_csta_open(struct sipe_core_private *sipe_private,\n\t\t   const gchar *line_uri,\n\t\t   const gchar *server);\n\n/**\n * Closes CSTA\n */\nvoid sip_csta_close(struct sipe_core_private *sipe_private);\n\n/**\n * Processes incoming CSTA commands\n */\nvoid process_incoming_info_csta(struct sipe_core_private *sipe_private,\n\t\t\t\tstruct sipmsg *msg);\n\n/**\n * Is CSTA in idle state?\n */\ngboolean sip_csta_is_idle(struct sipe_core_private *sipe_private);\n"
  },
  {
    "path": "src/core/sip-sec-basic.c",
    "content": "/**\n * @file sip-sec-basic.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013-2015 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * Implementation for HTTP \"WWW-Authenticate: Basic\" scheme (RFC1945).\n */\n\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sip-sec.h\"\n#include \"sip-sec-mech.h\"\n#include \"sip-sec-basic.h\"\n#include \"sipe-backend.h\"\n\n/* Security context for Basic */\ntypedef struct _context_basic {\n\tstruct sip_sec_context common;\n\tgchar *token;\n\tguint length;\n} *context_basic;\n\n/* sip-sec-mech.h API implementation for Basic */\n\nstatic gboolean\nsip_sec_acquire_cred__basic(SipSecContext context,\n\t\t\t    const gchar *username,\n\t\t\t    const gchar *password)\n{\n\tcontext_basic ctx = (context_basic) context;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_sec_acquire_cred__basic: entering\");\n\n\tif (!username || !password)\n\t\treturn(FALSE);\n\n\t/* calculate Basic token (RFC1945 section 11.1) */\n\tctx->token  = g_strdup_printf(\"%s:%s\", username, password);\n\tctx->length = strlen(ctx->token);\n\n\treturn(TRUE);\n}\n\nstatic gboolean\nsip_sec_init_sec_context__basic(SipSecContext context,\n\t\t\t\tSIPE_UNUSED_PARAMETER SipSecBuffer in_buff,\n\t\t\t\tSipSecBuffer *out_buff,\n\t\t\t\tSIPE_UNUSED_PARAMETER const gchar *service_name)\n{\n\tcontext_basic ctx = (context_basic) context;\n\n\tout_buff->length = ctx->length;\n\tout_buff->value  = (guint8 *) g_strdup(ctx->token);\n\n\treturn(TRUE);\n}\n\nstatic gboolean\nsip_sec_make_signature__basic(SIPE_UNUSED_PARAMETER SipSecContext context,\n\t\t\t      SIPE_UNUSED_PARAMETER const gchar *message,\n\t\t\t      SIPE_UNUSED_PARAMETER SipSecBuffer *signature)\n{\n\t/* No implementation needed, as Basic is not used for SIP */\n\treturn(FALSE);\n}\n\nstatic gboolean\nsip_sec_verify_signature__basic(SIPE_UNUSED_PARAMETER SipSecContext context,\n\t\t\t\tSIPE_UNUSED_PARAMETER const gchar *message,\n\t\t\t\tSIPE_UNUSED_PARAMETER SipSecBuffer signature)\n{\n\t/* No implementation needed, as Basic is not used for SIP */\n\treturn(FALSE);\n}\n\nstatic void\nsip_sec_destroy_sec_context__basic(SipSecContext context)\n{\n\tcontext_basic ctx = (context_basic) context;\n\n\tg_free(ctx->token);\n\tg_free(ctx);\n}\n\nstatic const gchar *\nsip_sec_context_name__basic(SIPE_UNUSED_PARAMETER SipSecContext context)\n{\n\treturn(\"Basic\");\n}\n\nSipSecContext\nsip_sec_create_context__basic(SIPE_UNUSED_PARAMETER guint type)\n{\n\tcontext_basic context = g_malloc0(sizeof(struct _context_basic));\n\tif (!context) return(NULL);\n\n\tcontext->common.acquire_cred_func     = sip_sec_acquire_cred__basic;\n\tcontext->common.init_context_func     = sip_sec_init_sec_context__basic;\n\tcontext->common.destroy_context_func  = sip_sec_destroy_sec_context__basic;\n\tcontext->common.make_signature_func   = sip_sec_make_signature__basic;\n\tcontext->common.verify_signature_func = sip_sec_verify_signature__basic;\n\tcontext->common.context_name_func     = sip_sec_context_name__basic;\n\n\treturn((SipSecContext) context);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sip-sec-basic.h",
    "content": "/**\n * @file sip-sec-basic.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\nSipSecContext\nsip_sec_create_context__basic(guint type);\n"
  },
  {
    "path": "src/core/sip-sec-digest-tests.c",
    "content": "/**\n * @file sip-sec-digest-test.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <stdint.h>\n\n#include <glib.h>\n\n#include \"sip-transport.h\"\n#include \"sipe-common.h\"\n#include \"sipe-crypt.h\"\n#include \"uuid.h\"\n\n#define SIP_SEC_DIGEST_COMPILING_TEST\nstatic const gchar *cnonce_fixed;\n#include \"sip-sec-digest.c\"\n\n/*\n * Stubs\n */\ngboolean sipe_backend_debug_enabled(void)\n{\n\treturn(TRUE);\n}\n\nvoid sipe_backend_debug_literal(sipe_debug_level level,\n\t\t\t\tconst gchar *msg)\n{\n\tprintf(\"DEBUG(%d): %s\\n\", level, msg);\n}\n\nvoid sipe_backend_debug(sipe_debug_level level,\n\t\t\tconst gchar *format,\n\t\t\t...)\n{\n\tva_list ap;\n\tgchar *newformat = g_strdup_printf(\"DEBUG(%d): %s\\n\", level, format);\n\n\tva_start(ap, format);\n\tvprintf(newformat, ap);\n\tva_end(ap);\n\n\tg_free(newformat);\n}\n\nconst gchar *sip_transport_epid(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private)\n{\n\treturn(NULL);\n}\n\nconst gchar *sip_transport_ip_address(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private)\n{\n\treturn(NULL);\n}\n\nchar *generateUUIDfromEPID(SIPE_UNUSED_PARAMETER const gchar *epid)\n{\n\treturn(NULL);\n}\n\nchar *sipe_get_epid(SIPE_UNUSED_PARAMETER const char *self_sip_uri,\n\t\t    SIPE_UNUSED_PARAMETER const char *hostname,\n\t\t    SIPE_UNUSED_PARAMETER const char *ip_address)\n{\n\treturn(NULL);\n}\n\n/* needed when linking against NSS */\nvoid md4sum(const uint8_t *data, uint32_t length, uint8_t *digest);\nvoid md4sum(SIPE_UNUSED_PARAMETER const uint8_t *data,\n\t    SIPE_UNUSED_PARAMETER uint32_t length,\n\t    SIPE_UNUSED_PARAMETER uint8_t *digest)\n{\n}\n\n/*\n * Tester code\n */\n#define PARSED_USERNAME 0\n#define PARSED_REALM    1\n#define PARSED_NONCE    2\n#define PARSED_URI      3\n#define PARSED_QOP      4\n#define PARSED_NC       5\n#define PARSED_CNONCE   6\n#define PARSED_RESPONSE 7\n#define PARSED_OPAQUE   8\n#define PARSED_MAX      9\nstatic void parse(const gchar *string,\n\t\t  gchar *parsed[PARSED_MAX])\n{\n\tconst gchar *header;\n\tconst gchar *param;\n\tguint i;\n\n\tfor (i = 0; i < PARSED_MAX; i++)\n\t\tparsed[i] = NULL;\n\n\tif (strstr(string, \"Digest \") == NULL)\n\t\treturn;\n\theader = string + 7;\n\n\t/* skip white space */\n\twhile (*header == ' ')\n\t\theader++;\n\n\t/* start of next parameter value */\n\twhile ((param = strchr(header, '=')) != NULL) {\n\t\tconst gchar *end;\n\n\t\t/* parameter value type */\n\t\tparam++;\n\t\tif (*param == '\"') {\n\t\t\t/* string: xyz=\"...\"(,) */\n\t\t\tend = strchr(++param, '\"');\n\t\t\tif (!end) {\n\t\t\t\tSIPE_DEBUG_ERROR(\"parse: corrupted string parameter near '%s'\", header);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\t/* number: xyz=12345(,) */\n\t\t\tend = strchr(param, ',');\n\t\t\tif (!end) {\n\t\t\t\t/* last parameter */\n\t\t\t\tend = param + strlen(param);\n\t\t\t}\n\t\t}\n\n#define COMPARE(string, index) \\\n\tif (g_str_has_prefix(header, #string \"=\")) { \\\n\t\tg_free(parsed[ PARSED_ ## index]);  \\\n\t\tparsed[ PARSED_ ## index] = g_strndup(param, end - param); \\\n\t} else\n\n\t\tCOMPARE(username, USERNAME)\n\t\tCOMPARE(realm, REALM)\n\t\tCOMPARE(nonce, NONCE)\n\t\tCOMPARE(uri, URI)\n\t\tCOMPARE(qop, QOP)\n\t\tCOMPARE(nc, NC)\n\t\tCOMPARE(cnonce, CNONCE)\n\t\tCOMPARE(response, RESPONSE)\n\t\tCOMPARE(opaque, OPAQUE)\n                { /* ignore */ }\n\n\t\t/* skip to next parameter */\n\t\twhile ((*end == '\"') || (*end == ',') || (*end == ' '))\n\t\t\tend++;\n\t\theader = end;\n\t}\n}\n\nstatic guint expected(const gchar *reference,\n\t\t      const gchar *testvalue)\n{\n\tgchar *reference_parsed[PARSED_MAX];\n\tgchar *testvalue_parsed[PARSED_MAX];\n\tguint i;\n\tguint failed = 0;\n\n\tparse(reference, reference_parsed);\n\tparse(testvalue, testvalue_parsed);\n\tfor (i = 0; i < PARSED_MAX; i++) {\n\t\tgchar *ref  = reference_parsed[i];\n\t\tgchar *test = testvalue_parsed[i];\n\t\tif (!sipe_strequal(ref, test) && (ref || test)) {\n\t\t\tSIPE_DEBUG_ERROR(\"FAILED(%d): expected '%s' got '%s'\",\n\t\t\t\t\t i, ref, test);\n\t\t\tfailed = 1;\n\t\t}\n\t\tg_free(test);\n\t\tg_free(ref);\n\t}\n\tSIPE_DEBUG_INFO(\"Response:  %s\", testvalue);\n\n\treturn(failed);\n}\n\nint main(SIPE_UNUSED_PARAMETER int argc, SIPE_UNUSED_PARAMETER char *argv[])\n{\n\tguint failed = 0;\n\n\t/* Initialization for crypto backend (test mode) */\n\tsipe_crypto_init(FALSE);\n\n#define RUNTEST(_user, _password, _cnonce, _header, _method, _uri, _reference) \\\n\t{\t\t\t\t\t\t\t\t\\\n\t\tstruct sipe_core_private sipe_private;\t\t\t\\\n\t\tgchar *response;\t\t\t\t\t\\\n\t\tprintf(\"\\n\");\t\t\t\t\t\t\\\n\t\tsipe_private.authuser = _user ;\t\t\t\t\\\n\t\tsipe_private.password = _password ;\t\t\t\\\n\t\tcnonce_fixed          = _cnonce;\t\t\t\\\n\t\tresponse = sip_sec_digest_authorization(&sipe_private, _header, _method, _uri); \\\n\t\tfailed  += expected(_reference, response);\t\t\\\n\t\tg_free(response); \\\n\t}\n\n\t/*\n\t * RFC-2617 Section 3.5\n\t */\n\tRUNTEST(\"Mufasa\", \"Circle Of Life\", \"0a4f113b\",\n\t\t\"realm=\\\"testrealm@host.com\\\", qop=\\\"auth,auth-int\\\", nonce=\\\"dcd98b7102dd2f0e8b11d0f600bfb0c093\\\", opaque=\\\"5ccc069c403ebaf9f0171e9517f40e41\\\"\",\n\t\t\"GET\",\n\t\t\"/dir/index.html\",\n\t\t\"Digest username=\\\"Mufasa\\\", realm=\\\"testrealm@host.com\\\", nonce=\\\"dcd98b7102dd2f0e8b11d0f600bfb0c093\\\", uri=\\\"/dir/index.html\\\", qop=auth, nc=00000001, cnonce=\\\"0a4f113b\\\", response=\\\"6629fae49393a05397450978507c4ef1\\\", opaque=\\\"5ccc069c403ebaf9f0171e9517f40e41\\\"\");\n\n\t/*\n\t * http://www.ntu.edu.sg/home/ehchua/programming/webprogramming/HTTP_Authentication.html\n\t */\n\tRUNTEST(\"bob\", \"bob\", \"1672b410efa182c061c2f0a58acaa17d\",\n\t\t/*\n\t\t * The Server challenge shown does not correspond to the\n\t\t * Client response. Use realm/nonce from the Client response.\n\t\t *\n\t\t * \"realm=\\\"Members only\\\", nonce=\\\"LHOKe1l2BAA=5c373ae0d933a0bb6321125a56a2fcdb6fd7c93b\\\", algorithm=MD5, qop=\\\"auth\\\"\",\n\t\t */\n\t\t\"realm=\\\"members only\\\", nonce=\\\"5UImQA==3d76b2ab859e1770ec60ed285ec68a3e63028461\\\", algorithm=MD5, qop=\\\"auth\\\"\",\n\t\t\"GET\",\n\t\t\"/digest_auth/test.html\",\n\t\t\"Digest username=\\\"bob\\\", realm=\\\"members only\\\", qop=\\\"auth\\\", algorithm=\\\"MD5\\\", uri=\\\"/digest_auth/test.html\\\", nonce=\\\"5UImQA==3d76b2ab859e1770ec60ed285ec68a3e63028461\\\", nc=00000001, cnonce=\\\"1672b410efa182c061c2f0a58acaa17d\\\", response=\\\"3d9ebe6b9534a7135a3fde59a5a72668\\\"\");\n\n\treturn(failed);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sip-sec-digest.c",
    "content": "/**\n * @file sip-sec-digest.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <stdlib.h>\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sip-sec-digest.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-digest.h\"\n#include \"sipe-utils.h\"\n\n/*\n * Calculate a response for HTTP MD5 Digest authentication (RFC 2617)\n */\nstatic gchar *digest_HA1(const gchar *user,\n\t\t\t const gchar *realm,\n\t\t\t const gchar *password)\n{\n\t/* H(A1): H(user \":\" realm \":\" password) */\n\tgchar *string = g_strdup_printf(\"%s:%s:%s\", user, realm, password);\n\tgchar *HA1;\n\tguchar digest[SIPE_DIGEST_MD5_LENGTH];\n\tsipe_digest_md5((guchar *)string, strlen(string), digest);\n\tg_free(string);\n\n\t/* Result: LOWER(HEXSTRING(H(A1))) */\n\tstring = buff_to_hex_str(digest, sizeof(digest));\n\tHA1 = g_ascii_strdown(string, -1);\n\tg_free(string);\n\treturn(HA1);\n}\n\nstatic gchar *digest_HA2(const gchar *method,\n\t\t\t const gchar *target)\n{\n\t/* H(A2): H(method \":\" target) */\n\tgchar *string = g_strdup_printf(\"%s:%s\", method, target);\n\tgchar *HA2;\n\tguchar digest[SIPE_DIGEST_MD5_LENGTH];\n\tsipe_digest_md5((guchar *)string, strlen(string), digest);\n\tg_free(string);\n\n\t/* Result: LOWER(HEXSTRING(H(A1))) */\n\tstring = buff_to_hex_str(digest, sizeof(digest));\n\tHA2 = g_ascii_strdown(string, -1);\n\tg_free(string);\n\treturn(HA2);\n}\n\nstatic gchar *generate_cnonce(void)\n{\n#ifdef SIP_SEC_DIGEST_COMPILING_TEST\n\treturn(g_strdup(cnonce_fixed));\n#else\n\treturn(g_strdup_printf(\"%04x%04x\", rand() & 0xFFFF, rand() & 0xFFFF));\n#endif\n}\n\nstatic gchar *digest_response(const gchar *user,\n\t\t\t      const gchar *realm,\n\t\t\t      const gchar *password,\n\t\t\t      const gchar *nonce,\n\t\t\t      const gchar *nc,\n\t\t\t      const gchar *cnonce,\n\t\t\t      const gchar *qop,\n\t\t\t      const gchar *method,\n\t\t\t      const gchar *target)\n{\n\tgchar *HA1 = digest_HA1(user, realm, password);\n\tgchar *HA2 = digest_HA2(method, target);\n\tgchar *string, *Digest;\n\tguchar digest[SIPE_DIGEST_MD5_LENGTH];\n\n#ifdef SIP_SEC_DIGEST_COMPILING_TEST\n\tSIPE_DEBUG_INFO(\"HA1 %s\", HA1);\n\tSIPE_DEBUG_INFO(\"HA2 %s\", HA2);\n#endif\n\n\t/* Digest: H(H(A1) \":\" nonce \":\" nc \":\" cnonce \":\" qop \":\" H(A2) */\n\tstring = g_strdup_printf(\"%s:%s:%s:%s:%s:%s\", HA1, nonce, nc, cnonce, qop, HA2);\n\tg_free(HA2);\n\tg_free(HA1);\n\tsipe_digest_md5((guchar *)string, strlen(string), digest);\n\tg_free(string);\n\n\t/* Result: LOWER(HEXSTRING(H(A1))) */\n\tstring = buff_to_hex_str(digest, sizeof(digest));\n\tDigest = g_ascii_strdown(string, -1);\n\tg_free(string);\n\treturn(Digest);\n}\n\ngchar *sip_sec_digest_authorization(struct sipe_core_private *sipe_private,\n\t\t\t\t    const gchar *header,\n\t\t\t\t    const gchar *method,\n\t\t\t\t    const gchar *target)\n{\n\tconst gchar *param;\n\tgchar *nonce  = NULL;\n\tgchar *opaque = NULL;\n\tgchar *realm  = NULL;\n\tgchar *authorization = NULL;\n\n\t/* sanity checks */\n\tif (!sipe_private->password)\n\t\treturn(NULL);\n\n\t/* skip white space */\n\twhile (*header == ' ')\n\t\theader++;\n\n\t/* start of next parameter value */\n\twhile ((param = strchr(header, '=')) != NULL) {\n\t\tconst gchar *end;\n\n\t\t/* parameter value type */\n\t\tparam++;\n\t\tif (*param == '\"') {\n\t\t\t/* string: xyz=\"...\"(,) */\n\t\t\tend = strchr(++param, '\"');\n\t\t\tif (!end) {\n\t\t\t\tSIPE_DEBUG_ERROR(\"sip_sec_digest_authorization: corrupted string parameter near '%s'\", header);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\t/* number: xyz=12345(,) */\n\t\t\tend = strchr(param, ',');\n\t\t\tif (!end) {\n\t\t\t\t/* last parameter */\n\t\t\t\tend = param + strlen(param);\n\t\t\t}\n\t\t}\n\n\t\t/* parameter type */\n\t\tif        (g_str_has_prefix(header, \"nonce=\\\"\")) {\n\t\t\tg_free(nonce);\n\t\t\tnonce = g_strndup(param, end - param);\n\t\t} else if (g_str_has_prefix(header, \"opaque=\\\"\")) {\n\t\t\tg_free(opaque);\n\t\t\topaque = g_strndup(param, end - param);\n\t\t} else if (g_str_has_prefix(header, \"realm=\\\"\")) {\n\t\t\tg_free(realm);\n\t\t\trealm = g_strndup(param, end - param);\n\t\t}\n\n\t\t/* skip to next parameter */\n\t\twhile ((*end == '\"') || (*end == ',') || (*end == ' '))\n\t\t\tend++;\n\t\theader = end;\n\t}\n\n\tif (nonce && realm) {\n\t\tconst gchar *authuser = sipe_private->authuser ? sipe_private->authuser : sipe_private->username;\n\t\tconst gchar *nc       = \"00000001\";\n\t\tgchar *cnonce         = generate_cnonce();\n\t\tgchar *opt_opaque     = opaque ? g_strdup_printf(\"opaque=\\\"%s\\\", \", opaque) : g_strdup(\"\");\n\t\tgchar *response = digest_response(authuser,\n\t\t\t\t\t\t  realm,\n\t\t\t\t\t\t  sipe_private->password,\n\t\t\t\t\t\t  nonce,\n\t\t\t\t\t\t  nc,\n\t\t\t\t\t\t  cnonce,\n\t\t\t\t\t\t  \"auth\",\n\t\t\t\t\t\t  method,\n\t\t\t\t\t\t  target);\n\n#ifdef SIP_SEC_DIGEST_COMPILING_TEST\n\t\tSIPE_DEBUG_INFO(\"RES %s\", response);\n#endif\n\n\t\tauthorization = g_strdup_printf(\"Digest username=\\\"%s\\\", realm=\\\"%s\\\", nonce=\\\"%s\\\", uri=\\\"%s\\\", qop=auth, nc=%s, cnonce=\\\"%s\\\", %sresponse=\\\"%s\\\"\",\n\t\t\t\t\t\tauthuser,\n\t\t\t\t\t\trealm,\n\t\t\t\t\t\tnonce,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tnc,\n\t\t\t\t\t\tcnonce,\n\t\t\t\t\t\topt_opaque,\n\t\t\t\t\t\tresponse);\n\t\tg_free(response);\n\t\tg_free(opt_opaque);\n\t\tg_free(cnonce);\n\n\t} else\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sip_sec_digest_authorization: no digest parameters found. Giving up.\");\n\n\tg_free(realm);\n\tg_free(opaque);\n\tg_free(nonce);\n\n\treturn(authorization);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sip-sec-digest.h",
    "content": "/**\n * @file sip-sec-digest.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\n\n/**\n * Generate Digest authorization header\n *\n * @param sipe_private SIPE core private data\n * @param header       Digest authentication header contents\n *\n * @return Digest authorization header or @c NULL. Must be @c g_free'd().\n */\ngchar *sip_sec_digest_authorization(struct sipe_core_private *sipe_private,\n\t\t\t\t    const gchar *header,\n\t\t\t\t    const gchar *method,\n\t\t\t\t    const gchar *target);\n"
  },
  {
    "path": "src/core/sip-sec-gssapi.c",
    "content": "/**\n * @file sip-sec-gssapi.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2009 pier11 <pier11@operamail.com>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * This module implements sip-sec authentication API using GSSAPI.\n *\n * It can be compiled in two different modes:\n *\n *  - Kerberos-only: NTLM & SPNEGO are using SIPE internal implementation\n *                   [HAVE_GSSAPI_ONLY is not defined]\n *\n *  - pure GSSAPI:   this modules handles Kerberos, NTLM & SPNEGO\n *                   [HAVE_GSSAPI_ONLY is defined]\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n#include <string.h>\n#include <gssapi/gssapi.h>\n#ifdef HAVE_GSSAPI_PASSWORD_SUPPORT\n#include <gssapi/gssapi_ext.h>\n#endif\n#include <gssapi/gssapi_krb5.h>\n#ifdef HAVE_GSSAPI_ONLY\n#include <gssapi/gssapi_ntlmssp.h>\n#endif\n\n#include \"sipe-common.h\"\n#include \"sip-sec.h\"\n#include \"sip-sec-mech.h\"\n#include \"sip-sec-gssapi.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-utils.h\"\n\n/* Security context for Kerberos */\ntypedef struct _context_gssapi {\n\tstruct sip_sec_context common;\n\tgss_cred_id_t cred_gssapi;\n\tgss_ctx_id_t ctx_gssapi;\n\tgss_name_t target_name;\n} *context_gssapi;\n\n#ifdef HAVE_GSSAPI_ONLY\nstatic const gss_OID_desc gss_mech_ntlmssp = {\n\tGSS_NTLMSSP_OID_LENGTH,\n\t(char *) GSS_NTLMSSP_OID_STRING /* read-only in reality */\n};\n\nstatic const gss_OID_desc gss_mech_spnego = {\n\t6,\n\t(char *) \"\\x2b\\x06\\x01\\x05\\x05\\x02\" /* read-only in reality */\n};\n\n/*\n * The SPNEGO implementation on older Microsoft IIS servers sends a\n * non-conformant final empty token that is not accepted by the SPNEGO\n * implementation in older MIT KRB5 releases:\n *\n *  Base64-encoded DER: oRgwFqADCgEAoQsGCSqGSIb3EgECAqICBAA=\n *\n *  Decoded ASN.1:\n *     0:d=0  hl=2 l=  24 cons: cont [ 1 ]\n *     2:d=1  hl=2 l=  22 cons: SEQUENCE\n *     4:d=2  hl=2 l=   3 cons: cont [ 0 ]\n *     6:d=3  hl=2 l=   1 prim: ENUMERATED        :00\n *     9:d=2  hl=2 l=  11 cons: cont [ 1 ]\n *    11:d=3  hl=2 l=   9 prim: OBJECT            :1.2.840.113554.1.2.2\n *    22:d=2  hl=2 l=   2 cons: cont [ 2 ]     | this empty element is not\n *    24:d=3  hl=2 l=   0 prim: OCTET STRING   | correct according to spec\n *\n * We can circumvent this problem by setting GSS_C_MUTUAL_FLAG which causes\n * the server to send a non-empty final token. We set the following flag to\n * TRUE after the first time gss_init_sec_context() returns with a\n * \"defective token\" error.\n */\nstatic gboolean spnego_mutual_flag = FALSE;\n#endif\n\n#define SIP_SEC_FLAG_GSSAPI_SIP_NTLM           0x00010000\n#define SIP_SEC_FLAG_GSSAPI_NEGOTIATE_FALLBACK 0x00020000\n\nstatic void sip_sec_gssapi_print_gss_error0(const char *func,\n\t\t\t\t\t    OM_uint32 status,\n\t\t\t\t\t    int type)\n{\n\tOM_uint32 minor;\n\tOM_uint32 message_context = 0;\n\tgss_buffer_desc status_string;\n\n\tdo {\n\t\tgss_display_status(&minor,\n\t\t\t\t   status,\n\t\t\t\t   type,\n\t\t\t\t   GSS_C_NO_OID,\n\t\t\t\t   &message_context,\n\t\t\t\t   &status_string);\n\n\t\tSIPE_DEBUG_ERROR(\"sip_sec_gssapi: GSSAPI error in %s (%s): %s\",\n\t\t\t\t func,\n\t\t\t\t (type == GSS_C_GSS_CODE ? \"GSS\" : \"Mech\"),\n\t\t\t\t (gchar *) status_string.value);\n\t\tgss_release_buffer(&minor, &status_string);\n\t} while (message_context != 0);\n}\n\n/* Prints out errors of GSSAPI function invocation */\nstatic void sip_sec_gssapi_print_gss_error(const char *func,\n\t\t\t\t\t   OM_uint32 ret,\n\t\t\t\t\t   OM_uint32 minor)\n{\n\tsip_sec_gssapi_print_gss_error0(func, ret,   GSS_C_GSS_CODE);\n\tsip_sec_gssapi_print_gss_error0(func, minor, GSS_C_MECH_CODE);\n}\n\n#if defined(HAVE_GSSAPI_PASSWORD_SUPPORT) || defined(HAVE_GSSAPI_ONLY)\n/* NOTE: releases \"set\" on error */\nstatic gboolean add_mech(gss_OID_set set,\n\t\t\t gss_OID mech,\n\t\t\t const gchar *name)\n{\n\tOM_uint32 ret;\n\tOM_uint32 minor;\n\n\tret = gss_add_oid_set_member(&minor, mech, &set);\n\tif (GSS_ERROR(ret)) {\n\t\tsip_sec_gssapi_print_gss_error(\"gss_add_oid_set_member\", ret, minor);\n\t\tSIPE_DEBUG_ERROR(\"add_mech: can't add %s to mech set (ret=%u)\", name, ret);\n\t\tgss_release_oid_set(&minor, &set);\n\t\treturn(FALSE);\n\t}\n\tSIPE_DEBUG_INFO(\"add_mech: added %s to mech set\", name);\n\n\treturn(TRUE);\n}\n\nstatic gss_OID_set create_mechs_set(guint type)\n{\n\tOM_uint32 ret;\n\tOM_uint32 minor;\n\tgss_OID_set set = GSS_C_NO_OID_SET;\n\tgss_OID mech_oid;\n\tconst gchar *name;\n\n\tret = gss_create_empty_oid_set(&minor, &set);\n\tif (GSS_ERROR(ret)) {\n\t\tsip_sec_gssapi_print_gss_error(\"gss_create_empty_oid_set\", ret, minor);\n\t\tSIPE_DEBUG_ERROR(\"create_mechs_set: can't create mech set (ret=%u)\", ret);\n\t\treturn(GSS_C_NO_OID_SET);\n\t}\n\n#ifdef HAVE_GSSAPI_ONLY\n\tswitch (type) {\n\tcase SIPE_AUTHENTICATION_TYPE_NTLM:\n\t\tmech_oid = (gss_OID) &gss_mech_ntlmssp;\n\t\tname     = \"NTLM\";\n\t\tbreak;\n\n\tcase SIPE_AUTHENTICATION_TYPE_KERBEROS:\n#else\n\t\t(void) type; /* keep compiler happy */\n#endif\n\t\tmech_oid = (gss_OID) gss_mech_krb5;\n\t\tname     = \"Kerberos\";\n#ifdef HAVE_GSSAPI_ONLY\n\t\tbreak;\n\n\tcase SIPE_AUTHENTICATION_TYPE_NEGOTIATE:\n\t\tmech_oid = (gss_OID) &gss_mech_spnego;\n\t\tname     = \"SPNEGO\";\n\t\tbreak;\n\n\tdefault:\n\t\tSIPE_DEBUG_ERROR(\"create_mechs_set: invoked with invalid type %u\",\n\t\t\t\t type);\n\t\tgss_release_oid_set(&minor, &set);\n\t\treturn(GSS_C_NO_OID_SET);\n\t\tbreak;\n\t}\n#endif\n\n\treturn(add_mech(set, mech_oid, name) ? set : GSS_C_NO_OID_SET);\n}\n#endif\n\n#ifdef HAVE_GSSAPI_ONLY\nstatic gss_OID_set create_neg_mechs_set(void)\n{\n\tOM_uint32 ret;\n\tOM_uint32 minor;\n\tgss_OID_set set = GSS_C_NO_OID_SET;\n\n\tret = gss_create_empty_oid_set(&minor, &set);\n\tif (GSS_ERROR(ret)) {\n\t\tsip_sec_gssapi_print_gss_error(\"gss_create_empty_oid_set\", ret, minor);\n\t\tSIPE_DEBUG_ERROR(\"create_neg_mechs_set: can't create mech set (ret=%u)\", ret);\n\t\treturn(GSS_C_NO_OID_SET);\n\t}\n\n\treturn((add_mech(set, (gss_OID)  gss_mech_krb5,    \"Kerberos\") &&\n\t\tadd_mech(set, (gss_OID) &gss_mech_ntlmssp, \"NTLM\")) ?\n\t       set : GSS_C_NO_OID_SET);\n}\n\nstatic gboolean gssntlm_reset_mic_sequence(context_gssapi context)\n{\n\tOM_uint32 ret;\n\tOM_uint32 minor;\n\tgss_buffer_desc value;\n\tguint sequence = 100;\n\n\tstatic const gss_OID_desc set_sequence_num_oid = {\n\t\tGSS_NTLMSSP_SET_SEQ_NUM_OID_LENGTH,\n\t\t(char *) GSS_NTLMSSP_SET_SEQ_NUM_OID_STRING /* read-only in reality */\n\t};\n\n\tvalue.length = sizeof(sequence);\n\tvalue.value  = &sequence;\n\n\tret = gss_set_sec_context_option(&minor,\n\t\t\t\t\t &context->ctx_gssapi,\n\t\t\t\t\t (gss_OID_desc *) &set_sequence_num_oid,\n\t\t\t\t\t &value);\n\tif (GSS_ERROR(ret)) {\n\t\tsip_sec_gssapi_print_gss_error(\"gss_set_sec_context_option\", ret, minor);\n\t\tSIPE_DEBUG_ERROR(\"gssntlm_reset_mic_sequence: failed to reset MIC sequence number (ret=%u)\", ret);\n\t\treturn(FALSE);\n\t}\n\n\treturn(TRUE);\n}\n#endif\n\nstatic void drop_gssapi_context(SipSecContext context)\n{\n\tcontext_gssapi ctx = (context_gssapi) context;\n\tOM_uint32 ret;\n\tOM_uint32 minor;\n\n\tret = gss_delete_sec_context(&minor,\n\t\t\t\t     &(ctx->ctx_gssapi),\n\t\t\t\t     GSS_C_NO_BUFFER);\n\tif (GSS_ERROR(ret)) {\n\t\tsip_sec_gssapi_print_gss_error(\"gss_delete_sec_context\", ret, minor);\n\t\tSIPE_DEBUG_ERROR(\"drop_gssapi_context: failed to delete security context (ret=%u)\", ret);\n\t}\n\tctx->ctx_gssapi = GSS_C_NO_CONTEXT;\n\tcontext->flags &= ~SIP_SEC_FLAG_COMMON_READY;\n}\n\n/* sip-sec-mech.h API implementation for Kerberos/GSSAPI */\n\nstatic gboolean\nsip_sec_acquire_cred__gssapi(SipSecContext context,\n\t\t\t     const gchar *username,\n\t\t\t     const gchar *password)\n{\n\tcontext_gssapi ctx = (context_gssapi) context;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_sec_acquire_cred__gssapi: started\");\n\n\t/* this is the first time we are allowed to set private flags */\n\tif (((context->flags & SIP_SEC_FLAG_COMMON_HTTP) == 0) &&\n\t    (context->type == SIPE_AUTHENTICATION_TYPE_NTLM))\n\t\tcontext->flags |= SIP_SEC_FLAG_GSSAPI_SIP_NTLM;\n\n\t/* With SSO we use the default credentials */\n\tif ((context->flags & SIP_SEC_FLAG_COMMON_SSO) == 0) {\n#ifdef HAVE_GSSAPI_PASSWORD_SUPPORT\n\t\tgchar *username_new = NULL;\n\t\tOM_uint32 ret;\n\t\tOM_uint32 minor, minor_ignore;\n\t\tgss_OID_set mechs_set;\n\t\tgss_cred_id_t credentials;\n\t\tgss_buffer_desc input_name_buffer;\n\t\tgss_name_t user_name;\n\n\t\t/* Without SSO we need user name and password */\n\t\tif (is_empty(username) || is_empty(password)) {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sip_sec_acquire_cred__gssapi: no valid authentication information provided\");\n\t\t\treturn(FALSE);\n\t\t}\n\n\t\tmechs_set = create_mechs_set(context->type);\n\t\tif (mechs_set == GSS_C_NO_OID_SET)\n\t\t\treturn(FALSE);\n\n\t\tif (!SIP_SEC_USERNAME_IS_ENTERPRISE) {\n\t\t\tSIP_SEC_USERNAME_SPLIT_START;\n\n\t\t\t/* Construct user name to acquire credentials for */\n\t\t\tif (SIP_SEC_USERNAME_HAS_DOMAIN) {\n\t\t\t\t/* User specified a domain */\n\t\t\t\tgchar *realm = g_ascii_strup(SIP_SEC_USERNAME_DOMAIN,\n\t\t\t\t\t\t\t     -1);\n\n\t\t\t\tusername_new = g_strdup_printf(\"%s@%s\",\n\t\t\t\t\t\t\t       SIP_SEC_USERNAME_ACCOUNT,\n\t\t\t\t\t\t\t       realm);\n\t\t\t\tg_free(realm);\n\n\t\t\t} else if (strchr(username, '@')) {\n\t\t\t\t/* No domain, username matches XXX@YYY */\n\t\t\t\tgchar **user_realm = g_strsplit(username, \"@\", 2);\n\t\t\t\tgchar *realm       = g_ascii_strup(user_realm[1], -1);\n\n\t\t\t\t/*\n\t\t\t\t * We should escape the \"@\" to generate a enterprise\n\t\t\t\t * principal, i.e. XXX\\@YYY\n\t\t\t\t *\n\t\t\t\t * But krb5 libraries currently don't support this:\n\t\t\t\t *\n\t\t\t\t * http://krbdev.mit.edu/rt/Ticket/Display.html?id=7729\n\t\t\t\t *\n\t\t\t\t * username_new = g_strdup_printf(\"%s\\\\@%s\",\n\t\t\t\t */\n\t\t\t\tusername_new = g_strdup_printf(\"%s@%s\",\n\t\t\t\t\t\t\t       user_realm[0],\n\t\t\t\t\t\t\t       realm);\n\t\t\t\tg_free(realm);\n\t\t\t\tg_strfreev(user_realm);\n\t\t\t}\n\n\t\t\tSIP_SEC_USERNAME_SPLIT_END;\n\t\t}\n\n\t\tif (username_new)\n\t\t\tusername = username_new;\n\n\t\tSIPE_DEBUG_INFO(\"sip_sec_acquire_cred__gssapi: username '%s'\",\n\t\t\t\tusername);\n\n\t\t/* Import user name into GSS format */\n\t\tinput_name_buffer.value  = (void *) username;\n\t\tinput_name_buffer.length = strlen(username) + 1;\n\n\t\tret = gss_import_name(&minor,\n\t\t\t\t      &input_name_buffer,\n\t\t\t\t      (gss_OID) GSS_C_NT_USER_NAME,\n\t\t\t\t      &user_name);\n\t\tg_free(username_new);\n\n\t\tif (GSS_ERROR(ret)) {\n\t\t\tsip_sec_gssapi_print_gss_error(\"gss_import_name\", ret, minor);\n\t\t\tSIPE_DEBUG_ERROR(\"sip_sec_acquire_cred__gssapi: failed to construct user name (ret=%u)\", ret);\n\t\t\tgss_release_oid_set(&minor, &mechs_set);\n\t\t\treturn(FALSE);\n\t\t}\n\n\t\t/* Acquire user credentials with password */\n\t\tinput_name_buffer.value  = (void *) password;\n\t\tinput_name_buffer.length = strlen(password) + 1;\n\t\tret = gss_acquire_cred_with_password(&minor,\n\t\t\t\t\t\t     user_name,\n\t\t\t\t\t\t     &input_name_buffer,\n\t\t\t\t\t\t     GSS_C_INDEFINITE,\n\t\t\t\t\t\t     mechs_set,\n\t\t\t\t\t\t     GSS_C_INITIATE,\n\t\t\t\t\t\t     &credentials,\n\t\t\t\t\t\t     NULL,\n\t\t\t\t\t\t     NULL);\n\t\tgss_release_name(&minor_ignore, &user_name);\n\t\tgss_release_oid_set(&minor_ignore, &mechs_set);\n\n\t\tif (GSS_ERROR(ret)) {\n\t\t\tsip_sec_gssapi_print_gss_error(\"gss_acquire_cred_with_password\", ret, minor);\n\t\t\tSIPE_DEBUG_ERROR(\"sip_sec_acquire_cred__gssapi: failed to acquire credentials (ret=%u)\", ret);\n\t\t\treturn(FALSE);\n\t\t}\n\n\t\tctx->cred_gssapi = credentials;\n\n#else\n\t\t/*\n\t\t * non-SSO support requires gss_acquire_cred_with_password()\n\t\t * which is not available on older GSSAPI releases.\n\t\t */\n\t\t(void) username; /* keep compiler happy */\n\t\t(void) password; /* keep compiler happy */\n\t\t(void) ctx;      /* keep compiler happy */\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sip_sec_acquire_cred__gssapi: non-SSO mode not supported\");\n\t\treturn(FALSE);\n#endif\n\t}\n#ifdef HAVE_GSSAPI_ONLY\n\telse {\n\t\tOM_uint32 ret;\n\t\tOM_uint32 minor, minor_ignore;\n\t\tgss_OID_set mechs_set;\n\t\tgss_cred_id_t credentials;\n\n\t\tmechs_set = create_mechs_set(context->type);\n\t\tif (mechs_set == GSS_C_NO_OID_SET)\n\t\t\treturn(FALSE);\n\n\t\tret = gss_acquire_cred(&minor,\n\t\t\t\t       GSS_C_NO_NAME,\n\t\t\t\t       GSS_C_INDEFINITE,\n\t\t\t\t       mechs_set,\n\t\t\t\t       GSS_C_INITIATE,\n\t\t\t\t       &credentials,\n\t\t\t\t       NULL,\n\t\t\t\t       NULL);\n\t\tgss_release_oid_set(&minor_ignore, &mechs_set);\n\n\t\tif (GSS_ERROR(ret)) {\n\t\t\tsip_sec_gssapi_print_gss_error(\"gss_acquire_cred\", ret, minor);\n\t\t\tSIPE_DEBUG_ERROR(\"sip_sec_acquire_cred__gssapi: failed to acquire credentials (ret=%u)\", ret);\n\t\t\treturn(FALSE);\n\t\t}\n\n\t\tctx->cred_gssapi = credentials;\n\t}\n\n\tif (context->type == SIPE_AUTHENTICATION_TYPE_NEGOTIATE) {\n\t\tOM_uint32 ret;\n\t\tOM_uint32 minor, minor_ignore;\n\t\tgss_OID_set mechs_set = create_neg_mechs_set();\n\n\t\tif (mechs_set == GSS_C_NO_OID_SET)\n\t\t\treturn(FALSE);\n\n\t\tret = gss_set_neg_mechs(&minor,\n\t\t\t\t\tctx->cred_gssapi,\n\t\t\t\t\tmechs_set);\n\t\tgss_release_oid_set(&minor_ignore, &mechs_set);\n\n\t\tif (GSS_ERROR(ret)) {\n\t\t\tsip_sec_gssapi_print_gss_error(\"gss_set_neg_mechs\", ret, minor);\n\t\t\tSIPE_DEBUG_ERROR(\"sip_sec_acquire_cred__gssapi: failed to set negotiate mechanisms (ret=%u)\", ret);\n\t\t\treturn(FALSE);\n\t\t}\n\t}\n#endif\n\n\treturn(TRUE);\n}\n\nstatic gboolean\nsip_sec_init_sec_context__gssapi(SipSecContext context,\n\t\t\t\t SipSecBuffer in_buff,\n\t\t\t\t SipSecBuffer *out_buff,\n\t\t\t\t const gchar *service_name)\n{\n\tcontext_gssapi ctx = (context_gssapi) context;\n\tOM_uint32 ret;\n\tOM_uint32 minor, minor_ignore;\n\tOM_uint32 expiry;\n\tgss_buffer_desc input_token;\n\tgss_buffer_desc output_token;\n#ifdef HAVE_GSSAPI_ONLY\n\tgss_OID mech_oid;\n\tOM_uint32 flags = GSS_C_INTEG_FLAG;\n#endif\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_sec_init_sec_context__gssapi: started\");\n\n\t/*\n\t * If authentication was already completed, then this mean a new\n\t * authentication handshake has started on the existing connection.\n\t * We must throw away the old context, because we need a new one.\n\t */\n\tif ((context->flags & SIP_SEC_FLAG_COMMON_READY) &&\n\t    (ctx->ctx_gssapi != GSS_C_NO_CONTEXT)) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_sec_init_sec_context__gssapi: dropping old context\");\n\t\tdrop_gssapi_context(context);\n\t}\n\n\t/* Import service name to GSS */\n\tif (ctx->target_name == GSS_C_NO_NAME) {\n\t\tgchar *hostbased_service_name = sipe_utils_str_replace(service_name,\n\t\t\t\t\t\t\t\t       \"/\",\n\t\t\t\t\t\t\t\t       \"@\");\n\n\t\tinput_token.value = (void *) hostbased_service_name;\n\t\tinput_token.length = strlen(input_token.value) + 1;\n\t\tret = gss_import_name(&minor,\n\t\t\t\t      &input_token,\n\t\t\t\t      (gss_OID) GSS_C_NT_HOSTBASED_SERVICE,\n\t\t\t\t      &(ctx->target_name));\n\t\tg_free(hostbased_service_name);\n\n\t\tif (GSS_ERROR(ret)) {\n\t\t\tsip_sec_gssapi_print_gss_error(\"gss_import_name\", ret, minor);\n\t\t\tSIPE_DEBUG_ERROR(\"sip_sec_init_sec_context__gssapi: failed to construct target name (ret=%u)\", ret);\n\t\t\treturn(FALSE);\n\t\t}\n\t}\n\n#ifdef HAVE_GSSAPI_ONLY\n\tswitch(context->type) {\n\tcase SIPE_AUTHENTICATION_TYPE_NTLM:\n\t\tmech_oid = (gss_OID) &gss_mech_ntlmssp;\n\t\tif (context->flags & SIP_SEC_FLAG_GSSAPI_SIP_NTLM)\n\t\t\tflags |= GSS_C_DATAGRAM_FLAG;\n\t\tbreak;\n\n\tcase SIPE_AUTHENTICATION_TYPE_KERBEROS:\n\t\tmech_oid = (gss_OID) gss_mech_krb5;\n\t\tbreak;\n\n\tcase SIPE_AUTHENTICATION_TYPE_NEGOTIATE:\n\t\t/*\n\t\t * Some servers do not accept SPNEGO for Negotiate.\n\t\t * If come back here with an existing security context\n\t\t * and NULL input token we will fall back to NTLM\n\t\t */\n\t\tif (ctx->ctx_gssapi && (in_buff.value == NULL)) {\n\n\t\t\t/* Only try this once */\n\t\t\tif (context->flags & SIP_SEC_FLAG_GSSAPI_NEGOTIATE_FALLBACK) {\n\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sip_sec_init_sec_context__gssapi: SPNEGO-to-NTLM fallback failed\");\n\t\t\t\treturn(FALSE);\n\t\t\t}\n\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_sec_init_sec_context__gssapi: SPNEGO failed. Falling back to NTLM\");\n\t\t\tdrop_gssapi_context(context);\n\n\t\t\tcontext->flags |= SIP_SEC_FLAG_GSSAPI_NEGOTIATE_FALLBACK;\n\t\t}\n\n\t\tif (context->flags & SIP_SEC_FLAG_GSSAPI_NEGOTIATE_FALLBACK) {\n\t\t\tmech_oid = (gss_OID) &gss_mech_ntlmssp;\n\t\t} else {\n\t\t\tmech_oid = (gss_OID) &gss_mech_spnego;\n\t\t\tif (spnego_mutual_flag)\n\t\t\t\tflags |= GSS_C_MUTUAL_FLAG;\n\t\t}\n\t\tbreak;\n\n\tdefault:\n\t\tSIPE_DEBUG_ERROR(\"sip_sec_init_sec_context__gssapi: invoked for invalid type %u\",\n\t\t\t\t context->type);\n\t\treturn(FALSE);\n\t}\n#endif\n\n\t/* Create context */\n\tinput_token.length = in_buff.length;\n\tinput_token.value = in_buff.value;\n\n\toutput_token.length = 0;\n\toutput_token.value = NULL;\n\n\tret = gss_init_sec_context(&minor,\n\t\t\t\t   ctx->cred_gssapi,\n\t\t\t\t   &(ctx->ctx_gssapi),\n\t\t\t\t   ctx->target_name,\n#ifdef HAVE_GSSAPI_ONLY\n\t\t\t\t   mech_oid,\n\t\t\t\t   flags,\n#else\n\t\t\t\t   (gss_OID) gss_mech_krb5,\n\t\t\t\t   GSS_C_INTEG_FLAG,\n#endif\n\t\t\t\t   GSS_C_INDEFINITE,\n\t\t\t\t   GSS_C_NO_CHANNEL_BINDINGS,\n\t\t\t\t   &input_token,\n\t\t\t\t   NULL,\n\t\t\t\t   &output_token,\n\t\t\t\t   NULL,\n\t\t\t\t   &expiry);\n\n\tif (GSS_ERROR(ret)) {\n\t\tgss_release_buffer(&minor_ignore, &output_token);\n\t\tsip_sec_gssapi_print_gss_error(\"gss_init_sec_context\", ret, minor);\n\t\tSIPE_DEBUG_ERROR(\"sip_sec_init_sec_context__gssapi: failed to initialize context (ret=%u)\", ret);\n\n#ifdef HAVE_GSSAPI_ONLY\n\t\t/* Enable workaround for SPNEGO (see above) */\n\t\tif (ret == GSS_S_DEFECTIVE_TOKEN) {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sip_sec_init_sec_context__gssapi: enabling workaround for SPNEGO\");\n\t\t\tspnego_mutual_flag = TRUE;\n\t\t}\n#endif\n\n\t\treturn(FALSE);\n\t}\n\n\tout_buff->length = output_token.length;\n\tif (out_buff->length)\n\t\tout_buff->value = g_memdup(output_token.value, output_token.length);\n\telse\n\t\t/* Special case: empty token */\n\t\tout_buff->value = (guint8 *) g_strdup(\"\");\n\n\tgss_release_buffer(&minor_ignore, &output_token);\n\n\tcontext->expires = (int)expiry;\n\n\tif (ret == GSS_S_COMPLETE) {\n\t\t/* Authentication is completed */\n\t\tcontext->flags |= SIP_SEC_FLAG_COMMON_READY;\n\n#ifdef HAVE_GSSAPI_ONLY\n\t\tif ((context->flags & SIP_SEC_FLAG_GSSAPI_SIP_NTLM) &&\n\t\t    !gssntlm_reset_mic_sequence(ctx))\n\t\t\treturn(FALSE);\n#endif\n\t}\n\n\treturn(TRUE);\n}\n\n/**\n * @param message a NULL terminated string to sign\n */\nstatic gboolean\nsip_sec_make_signature__gssapi(SipSecContext context,\n\t\t\t       const gchar *message,\n\t\t\t       SipSecBuffer *signature)\n{\n\tOM_uint32 ret;\n\tOM_uint32 minor;\n\tgss_buffer_desc input_message;\n\tgss_buffer_desc output_token;\n\n\tinput_message.value = (void *)message;\n\tinput_message.length = strlen(input_message.value);\n\n\tret = gss_get_mic(&minor,\n\t\t\t  ((context_gssapi)context)->ctx_gssapi,\n\t\t\t  GSS_C_QOP_DEFAULT,\n\t\t\t  &input_message,\n\t\t\t  &output_token);\n\n\tif (GSS_ERROR(ret)) {\n\t\tsip_sec_gssapi_print_gss_error(\"gss_get_mic\", ret, minor);\n\t\tSIPE_DEBUG_ERROR(\"sip_sec_make_signature__gssapi: failed to make signature (ret=%u)\", ret);\n\t\treturn FALSE;\n\t} else {\n\t\tsignature->length = output_token.length;\n\t\tsignature->value  = g_memdup(output_token.value,\n\t\t\t\t\t     output_token.length);\n\t\tgss_release_buffer(&minor, &output_token);\n\t\treturn TRUE;\n\t}\n}\n\n/**\n * @param message a NULL terminated string to check signature of\n */\nstatic gboolean\nsip_sec_verify_signature__gssapi(SipSecContext context,\n\t\t\t\t const gchar *message,\n\t\t\t\t SipSecBuffer signature)\n{\n\tOM_uint32 ret;\n\tOM_uint32 minor;\n\tgss_buffer_desc input_message;\n\tgss_buffer_desc input_token;\n\n\tinput_message.value = (void *)message;\n\tinput_message.length = strlen(input_message.value);\n\n\tinput_token.value = signature.value;\n\tinput_token.length = signature.length;\n\n\tret = gss_verify_mic(&minor,\n\t\t\t     ((context_gssapi)context)->ctx_gssapi,\n\t\t\t     &input_message,\n\t\t\t     &input_token,\n\t\t\t     NULL);\n\n\tif (GSS_ERROR(ret)) {\n\t\tsip_sec_gssapi_print_gss_error(\"gss_verify_mic\", ret, minor);\n\t\tSIPE_DEBUG_ERROR(\"sip_sec_verify_signature__gssapi: failed to verify signature (ret=%u)\", ret);\n\t\treturn FALSE;\n\t} else {\n\t\treturn TRUE;\n\t}\n}\n\nstatic void\nsip_sec_destroy_sec_context__gssapi(SipSecContext context)\n{\n\tcontext_gssapi ctx = (context_gssapi) context;\n\tOM_uint32 ret;\n\tOM_uint32 minor;\n\n\tif (ctx->ctx_gssapi != GSS_C_NO_CONTEXT)\n\t\tdrop_gssapi_context(context);\n\n\tif (ctx->cred_gssapi != GSS_C_NO_CREDENTIAL) {\n\t\tret = gss_release_cred(&minor, &(ctx->cred_gssapi));\n\t\tif (GSS_ERROR(ret)) {\n\t\t\tsip_sec_gssapi_print_gss_error(\"gss_release_cred\", ret, minor);\n\t\t\tSIPE_DEBUG_ERROR(\"sip_sec_destroy_sec_context__gssapi: failed to release credentials (ret=%u)\", ret);\n\t\t}\n\t\tctx->cred_gssapi = GSS_C_NO_CREDENTIAL;\n\t}\n\n\tif (ctx->target_name != GSS_C_NO_NAME) {\n\t\tret = gss_release_name(&minor, &(ctx->target_name));\n\t\tif (GSS_ERROR(ret)) {\n\t\t\tsip_sec_gssapi_print_gss_error(\"gss_release_name\", ret, minor);\n\t\t\tSIPE_DEBUG_ERROR(\"sip_sec_destroy_sec_context__gssapi: failed to release name (ret=%u)\", ret);\n\t\t}\n\t\tctx->target_name = GSS_C_NO_NAME;\n\t}\n\n\tg_free(context);\n}\n\nstatic const gchar *\nsip_sec_context_name__gssapi(SipSecContext context)\n{\n#ifdef HAVE_GSSAPI_ONLY\n\tconst gchar *name;\n\n\tswitch(context->type) {\n\tcase SIPE_AUTHENTICATION_TYPE_NTLM:\n\t\tname = \"NTLM\";\n\t\tbreak;\n\n\tcase SIPE_AUTHENTICATION_TYPE_KERBEROS:\n\t\tname = \"Kerberos\";\n\t\tbreak;\n\n\tcase SIPE_AUTHENTICATION_TYPE_NEGOTIATE:\n\t\tif (context->flags & SIP_SEC_FLAG_GSSAPI_NEGOTIATE_FALLBACK)\n\t\t\tname = \"NTLM\";\n\t\telse\n\t\t\tname = \"Negotiate\";\n\t\tbreak;\n\n\tdefault:\n\t\tSIPE_DEBUG_ERROR(\"sip_sec_context_name__gssapi: invoked for invalid type %u\",\n\t\t\t\t context->type);\n\t\tname = \"\";\n\t\tbreak;\n\t}\n\n\treturn(name);\n\n#else\n\t(void) context; /* keep compiler happy */\n\treturn(\"Kerberos\");\n#endif\n}\n\nSipSecContext\nsip_sec_create_context__gssapi(SIPE_UNUSED_PARAMETER guint type)\n{\n\tcontext_gssapi context = g_malloc0(sizeof(struct _context_gssapi));\n\tif (!context) return(NULL);\n\n\tcontext->common.acquire_cred_func     = sip_sec_acquire_cred__gssapi;\n\tcontext->common.init_context_func     = sip_sec_init_sec_context__gssapi;\n\tcontext->common.destroy_context_func  = sip_sec_destroy_sec_context__gssapi;\n\tcontext->common.make_signature_func   = sip_sec_make_signature__gssapi;\n\tcontext->common.verify_signature_func = sip_sec_verify_signature__gssapi;\n\tcontext->common.context_name_func     = sip_sec_context_name__gssapi;\n\n\tcontext->cred_gssapi = GSS_C_NO_CREDENTIAL;\n\tcontext->ctx_gssapi  = GSS_C_NO_CONTEXT;\n\tcontext->target_name = GSS_C_NO_NAME;\n\n\treturn((SipSecContext) context);\n}\n\ngboolean sip_sec_password__gssapi(void)\n{\n\t/* GSSAPI supports Single-Sign On */\n\treturn(FALSE);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sip-sec-gssapi.h",
    "content": "/**\n * @file sip-sec-gssapi.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010,2012 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2009 pier11 <pier11@operamail.com>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\nSipSecContext\nsip_sec_create_context__gssapi(guint type);\n\ngboolean sip_sec_password__gssapi(void);\n"
  },
  {
    "path": "src/core/sip-sec-mech.h",
    "content": "/**\n * @file sip-sec-mech.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2015 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2009 pier11 <pier11@operamail.com>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Mechanism wrappers API  (Inspired by GSS-API)\n * All mechanisms should implement this API\n *\n * Current mechanisms are: Kerberos/GSS-API, sipe's NTLM and SSPI.\n */\n\ntypedef struct {\n\tgsize   length;\n\tguint8 *value;\n} SipSecBuffer;\n\ntypedef SipSecContext\n(*sip_sec_create_context_func)(guint type);\n\ntypedef gboolean\n(*sip_sec_acquire_cred_func)(SipSecContext context,\n\t\t\t     const gchar *username,\n\t\t\t     const gchar *password);\n\ntypedef gboolean\n(*sip_sec_init_context_func)(SipSecContext context,\n\t\t\t     SipSecBuffer in_buff,\n\t\t\t     SipSecBuffer *out_buff,\n\t\t\t     const gchar *service_name);\n\ntypedef void\n(*sip_sec_destroy_context_func)(SipSecContext context);\n\ntypedef gboolean\n(*sip_sec_make_signature_func)(SipSecContext context,\n\t\t\t       const gchar *message,\n\t\t\t       SipSecBuffer *signature);\n\ntypedef gboolean\n(*sip_sec_verify_signature_func)(SipSecContext context,\n\t\t\t\t const gchar *message,\n\t\t\t\t SipSecBuffer signature);\n\ntypedef const gchar *(*sip_sec_context_name_func)(SipSecContext context);\n\ntypedef gboolean (*sip_sec_password_func)(void);\n\n\nstruct sip_sec_context {\n\tsip_sec_acquire_cred_func     acquire_cred_func;\n\tsip_sec_init_context_func     init_context_func;\n\tsip_sec_destroy_context_func  destroy_context_func;\n\tsip_sec_make_signature_func   make_signature_func;\n\tsip_sec_verify_signature_func verify_signature_func;\n\tsip_sec_context_name_func     context_name_func;\n\tguint type;\n\t/** Security Context expiration interval in seconds */\n\tguint expires;\n\tguint flags;\n};\n\n/**\n * sip_sec_context.flags\n *\n * 0x00000001 - 0x00008000: common flags\n * 0x00010000 - 0x80000000: mechanism private flags\n *\n * NOTE: private flags must be set in acquire_cred_func()!\n */\n#define SIP_SEC_FLAG_COMMON_SSO   0x00000001\n#define SIP_SEC_FLAG_COMMON_HTTP  0x00000002\n#define SIP_SEC_FLAG_COMMON_READY 0x00000004\n\n/**\n * Helper macro for parsing username into domain & account parts\n */\n#define SIP_SEC_USERNAME_ENTERPRISE_STRING \"\\\\@\"\n#define SIP_SEC_USERNAME_IS_ENTERPRISE     (strstr(username, SIP_SEC_USERNAME_ENTERPRISE_STRING) != NULL)\n#define SIP_SEC_USERNAME_SPLIT_START       gchar **_domain_user = g_strsplit_set(username, \"/\\\\\", 2)\n#define SIP_SEC_USERNAME_SPLIT_END         g_strfreev(_domain_user)\n#define SIP_SEC_USERNAME_DOMAIN            _domain_user[0]\n#define SIP_SEC_USERNAME_ACCOUNT           _domain_user[1]\n#define SIP_SEC_USERNAME_HAS_DOMAIN        (SIP_SEC_USERNAME_ACCOUNT != NULL)\n"
  },
  {
    "path": "src/core/sip-sec-negotiate.c",
    "content": "/**\n * @file sip-sec-negotiate.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013-2015 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * Implementation for HTTP \"WWW-Authenticate: Negotiate\" scheme.\n * It is a wrapper that will always try Kerberos first and fall back to NTLM.\n */\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sip-sec.h\"\n#include \"sip-sec-mech.h\"\n#include \"sip-sec-gssapi.h\" /* for Kerberos */\n#include \"sip-sec-negotiate.h\"\n#include \"sip-sec-ntlm.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n\n/* Security context for Negotiate */\ntypedef struct _context_negotiate {\n\tstruct sip_sec_context common;\n\tconst gchar *username;\n\tconst gchar *password;\n\tSipSecContext krb5;\n\tSipSecContext ntlm;\n} *context_negotiate;\n\n#define SIP_SEC_FLAG_NEGOTIATE_DISABLE_FALLBACK 0x80000000\n\nstatic void sip_sec_negotiate_drop_krb5(context_negotiate context)\n{\n\tif (context->krb5)\n\t\tcontext->krb5->destroy_context_func(context->krb5);\n\tcontext->krb5 = NULL;\n}\n\nstatic void sip_sec_negotiate_copy_flags(context_negotiate ctx,\n\t\t\t\t\t SipSecContext context)\n{\n\tcontext->flags = ctx->common.flags;\n}\n\nstatic void sip_sec_negotiate_copy_settings(context_negotiate ctx,\n\t\t\t\t\t    SipSecContext context)\n{\n\tif (context->flags & SIP_SEC_FLAG_COMMON_READY)\n\t\tctx->common.flags |= SIP_SEC_FLAG_COMMON_READY;\n\telse\n\t\tctx->common.flags &= ~SIP_SEC_FLAG_COMMON_READY;\n\tctx->common.expires = context->expires;\n}\n\nstatic gboolean sip_sec_negotiate_ntlm_fallback(context_negotiate context)\n{\n\tif (context->common.flags & SIP_SEC_FLAG_NEGOTIATE_DISABLE_FALLBACK) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sip_sec_negotiate_ntlm_fallback: forbidden\");\n\t\treturn(FALSE);\n\t}\n\n\tsip_sec_negotiate_drop_krb5(context);\n\tsip_sec_negotiate_copy_flags(context, context->ntlm);\n\n\treturn(context->ntlm->acquire_cred_func(context->ntlm,\n\t\t\t\t\t\tcontext->username,\n\t\t\t\t\t\tcontext->password));\n}\n\n/* sip-sec-mech.h API implementation for Negotiate */\n\nstatic gboolean\nsip_sec_acquire_cred__negotiate(SipSecContext context,\n\t\t\t\tconst gchar *username,\n\t\t\t\tconst gchar *password)\n{\n\tcontext_negotiate ctx = (context_negotiate) context;\n\tgboolean ret;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_sec_acquire_cred__negotiate: entering\");\n\n\tctx->username = username;\n\tctx->password = password;\n\n\tcontext = ctx->krb5;\n\tsip_sec_negotiate_copy_flags(ctx, context);\n\tret = context->acquire_cred_func(context,\n\t\t\t\t\t username,\n\t\t\t\t\t password);\n\tif (!ret) {\n\t\t/* Kerberos failed -> fall back to NTLM immediately */\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_sec_acquire_cred__negotiate: fallback to NTLM\");\n\t\tret = sip_sec_negotiate_ntlm_fallback(ctx);\n\t}\n\n\treturn(ret);\n}\n\nstatic gboolean\nsip_sec_init_sec_context__negotiate(SipSecContext context,\n\t\t\t\t    SipSecBuffer in_buff,\n\t\t\t\t    SipSecBuffer *out_buff,\n\t\t\t\t    const gchar *service_name)\n{\n\tcontext_negotiate ctx = (context_negotiate) context;\n\tgboolean ret;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_sec_init_sec_context__negotiate: entering\");\n\n\t/* Kerberos available? */\n\tcontext = ctx->krb5;\n\tif (context) {\n\t\tret = context->init_context_func(context,\n\t\t\t\t\t\t in_buff,\n\t\t\t\t\t\t out_buff,\n\t\t\t\t\t\t service_name);\n\n\t\tif (!ret) {\n\t\t\t/* Kerberos failed -> fall back to NTLM */\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_sec_init_sec_context__negotiate: fallback to NTLM\");\n\t\t\tret = sip_sec_negotiate_ntlm_fallback(ctx);\n\n\t\t\tif (ret) {\n\t\t\t\tcontext = ctx->ntlm;\n\t\t\t\tret = context->init_context_func(context,\n\t\t\t\t\t\t\t\t in_buff,\n\t\t\t\t\t\t\t\t out_buff,\n\t\t\t\t\t\t\t\t service_name);\n\t\t\t}\n\t\t} else {\n\t\t\t/* Kerberos succeeded -> disable fallback to NTLM */\n\t\t\tctx->common.flags |= SIP_SEC_FLAG_NEGOTIATE_DISABLE_FALLBACK;\n\t\t}\n\n\t/* No Kerberos available -> use NTLM */\n\t} else {\n\t\tcontext = ctx->ntlm;\n\t\tret = context->init_context_func(context,\n\t\t\t\t\t\t in_buff,\n\t\t\t\t\t\t out_buff,\n\t\t\t\t\t\t service_name);\n\t}\n\n\t/* context points to the last used child context */\n\tif (ret)\n\t\tsip_sec_negotiate_copy_settings(ctx, context);\n\n\treturn(ret);\n}\n\nstatic gboolean\nsip_sec_make_signature__negotiate(SIPE_UNUSED_PARAMETER SipSecContext context,\n\t\t\t\t  SIPE_UNUSED_PARAMETER const gchar *message,\n\t\t\t\t  SIPE_UNUSED_PARAMETER SipSecBuffer *signature)\n{\n\t/* No implementation needed, as Negotiate is not used for SIP */\n\treturn(FALSE);\n}\n\nstatic gboolean\nsip_sec_verify_signature__negotiate(SIPE_UNUSED_PARAMETER SipSecContext context,\n\t\t\t\t    SIPE_UNUSED_PARAMETER const gchar *message,\n\t\t\t\t    SIPE_UNUSED_PARAMETER SipSecBuffer signature)\n{\n\t/* No implementation needed, as Negotiate is not used for SIP */\n\treturn(FALSE);\n}\n\nstatic void\nsip_sec_destroy_sec_context__negotiate(SipSecContext context)\n{\n\tcontext_negotiate ctx = (context_negotiate) context;\n\n\tif (ctx->ntlm)\n\t\tctx->ntlm->destroy_context_func(ctx->ntlm);\n\tsip_sec_negotiate_drop_krb5(ctx);\n\tg_free(ctx);\n}\n\n/*\n * This module doesn't implement SPNEGO (RFC 4559) but instead returns raw\n * NTLM. Therefore we should not use \"Authorization: Negotiate\" for NTLM\n * although Microsoft servers *do* accept them.\n */\nstatic const gchar *\nsip_sec_context_name__negotiate(SipSecContext context)\n{\n\tcontext_negotiate ctx = (context_negotiate) context;\n\tif (ctx->krb5)\n\t\treturn(\"Negotiate\");\n\telse\n\t\treturn(\"NTLM\");\n}\n\nSipSecContext\nsip_sec_create_context__negotiate(SIPE_UNUSED_PARAMETER guint type)\n{\n\tcontext_negotiate context = NULL;\n\tSipSecContext krb5 = sip_sec_create_context__gssapi(SIPE_AUTHENTICATION_TYPE_KERBEROS);\n\n\tif (krb5) {\n\t\tSipSecContext ntlm = sip_sec_create_context__ntlm(SIPE_AUTHENTICATION_TYPE_NTLM);\n\n\t\tif (ntlm) {\n\t\t\tcontext = g_malloc0(sizeof(struct _context_negotiate));\n\n\t\t\tif (context) {\n\t\t\t\tcontext->common.acquire_cred_func     = sip_sec_acquire_cred__negotiate;\n\t\t\t\tcontext->common.init_context_func     = sip_sec_init_sec_context__negotiate;\n\t\t\t\tcontext->common.destroy_context_func  = sip_sec_destroy_sec_context__negotiate;\n\t\t\t\tcontext->common.make_signature_func   = sip_sec_make_signature__negotiate;\n\t\t\t\tcontext->common.verify_signature_func = sip_sec_verify_signature__negotiate;\n\t\t\t\tcontext->common.context_name_func     = sip_sec_context_name__negotiate;\n\t\t\t\tcontext->krb5 = krb5;\n\t\t\t\tcontext->ntlm = ntlm;\n\n\t\t\t\tkrb5->type = SIPE_AUTHENTICATION_TYPE_KERBEROS;\n\t\t\t\tntlm->type = SIPE_AUTHENTICATION_TYPE_NTLM;\n\n\t\t\t} else {\n\t\t\t\tntlm->destroy_context_func(ntlm);\n\t\t\t}\n\t\t}\n\n\t\tif (!context) {\n\t\t\tkrb5->destroy_context_func(krb5);\n\t\t}\n\t}\n\n\treturn((SipSecContext) context);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sip-sec-negotiate.h",
    "content": "/**\n * @file sip-sec-negotiate.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\nSipSecContext\nsip_sec_create_context__negotiate(guint type);\n"
  },
  {
    "path": "src/core/sip-sec-ntlm-analyzer.c",
    "content": "/**\n * @file sip-sec-ntlm-analyzer.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013-2017 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * Takes Base64-encoded gssapi-data= values from NTLM authentication attempt\n * on the command line and prints out the NTLM message contents in human readable\n * format.\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <stdarg.h>\n\n#include <glib.h>\n#include <glib/gprintf.h>\n\n#include \"sipe-common.h\"\n#define _SIPE_COMPILING_ANALYZER\n#include \"sip-sec-ntlm.c\"\n\n/* stub functions */\nvoid sipe_backend_debug(SIPE_UNUSED_PARAMETER sipe_debug_level level,\n\t\t\tconst gchar *format,\n\t\t\t...)\n{\n\tva_list ap;\n\tva_start(ap, format);\n\tvprintf(format, ap);\n\tva_end(ap);\n}\n\ngboolean sipe_strequal(const gchar *left, const gchar *right)\n{\n\treturn (g_strcmp0(left, right) == 0);\n}\n\n/* copied from sipe-utils.c */\nchar *buff_to_hex_str(const guint8 *buff, const size_t buff_len)\n{\n\tchar *res;\n\tsize_t i, j;\n\n\tif (!buff) return NULL;\n\n        res = g_malloc(buff_len * 2 + 1);\n\tfor (i = 0, j = 0; i < buff_len; i++, j+=2) {\n\t\tsprintf(&res[j], \"%02X\", buff[i]);\n\t}\n\tres[j] = '\\0';\n\treturn res;\n}\n\nint main(int argc, char *argv[])\n{\n\tif (argc < 2) {\n\t\tfprintf(stderr, \"Usage: %s <gssapi-data> ...\\n\", argv[0]);\n\t\treturn(1);\n\t}\n\n\tsip_sec_init__ntlm();\n\n\twhile (--argc > 0) {\n\t\tconst gchar *base64 = *++argv;\n\t\tSipSecBuffer buffer;\n\n\t\tprintf(\"Base64: %s\\n\", base64);\n\t\tbuffer.value = g_base64_decode(base64, &buffer.length);\n\t\tif (buffer.value && buffer.length) {\n\t\t\tprintf(\"Decoded %\" G_GSIZE_FORMAT \" bytes\\n\", buffer.length);\n\t\t\tsip_sec_ntlm_message_describe(&buffer, \"analyzed\");\n\t\t\tprintf(\"-------------------------------------------------------------------------------\\n\");\n\t\t\tg_free(buffer.value);\n\t\t} else {\n\t\t\tprintf(\"Corrupted Base64 - skipping\\n\");\n\t\t}\n\t}\n\n\tsip_sec_destroy__ntlm();\n\n\treturn(0);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sip-sec-ntlm-tests.c",
    "content": "/**\n * @file sipe-sec-ntlm-tests.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2019 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2010 pier11 <pier11@operamail.com>\n * Copyright (C) 2008 Novell, Inc.\n *\n * Implemented with reference to the follow documentation:\n *   - http://davenport.sourceforge.net/ntlm.html\n *   - MS-NLMP: http://msdn.microsoft.com/en-us/library/cc207842.aspx\n *   - MS-SIP : http://msdn.microsoft.com/en-us/library/cc246115.aspx\n *\n * Please use \"make tests\" to build & run them!\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n\n#include <glib.h>\n#include <glib/gprintf.h>\n\n#include \"sipmsg.h\"\n#include \"sip-transport.h\"\n#include \"sipe-common.h\"\n#include \"sipe-sign.h\"\n#define _SIPE_COMPILING_TESTS\n#include \"sip-sec-ntlm.c\"\n\n/* stub for sipe-utils.c */\nconst gchar *sip_transport_epid(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private)\n{\n\treturn(NULL);\n}\n\nstatic int successes = 0;\nstatic int failures = 0;\n\ngboolean sip_sec_ntlm_tests(void);\n\nstatic void assert_equal(const char * expected, gpointer got, int len, gboolean stringify)\n{\n\tconst gchar * res = (gchar *) got;\n\tgchar to_str[len*2 + 1];\n\n\tif (stringify) {\n\t\tconst guint8 *bin = got;\n\t\tint i, j;\n\t\tfor (i = 0, j = 0; i < len; i++, j+=2) {\n\t\t\tg_sprintf(&to_str[j], \"%02X\", (bin[i]&0xff));\n\t\t}\n\t\tlen *= 2;\n\t\tres = to_str;\n\t}\n\n\tprintf(\"expected: %s\\n\", expected);\n\tprintf(\"received: %s\\n\", res);\n\n\tif (g_ascii_strncasecmp(expected, res, len) == 0) {\n\t\tsuccesses++;\n\t\tprintf(\"PASSED\\n\");\n\t} else {\n\t\tfailures++;\n\t\tprintf(\"FAILED\\n\");\n\t}\n}\n\n/* NOTE: both values are expected to be in host byte order! */\nstatic void assert_equal_guint32(guint32 expected, guint32 got)\n{\n\tprintf(\"expected: %08X\\n\", expected);\n\tprintf(\"received: %08X\\n\", got);\n\n\tif (expected == got) {\n\t\tsuccesses++;\n\t\tprintf(\"PASSED\\n\");\n\t} else {\n\t\tfailures++;\n\t\tprintf(\"FAILED\\n\");\n\t}\n}\n\ngboolean sip_sec_ntlm_tests(void)\n{\n\tconst char *password;\n\tconst char *user;\n\tconst char *domain;\n\tconst guchar *client_challenge;\n\tconst guchar *nonce;\n\tconst guchar *exported_session_key;\n\tconst guchar *text;\n\tguchar md4 [16];\n\tguchar md5 [16];\n\tguchar hmac_md5 [16];\n\tguint32 flags;\n\tguchar response_key_lm [16];\n\tguchar response_key_nt [16];\n\tguchar nt_challenge_response [24];\n\tguchar lm_challenge_response [24];\n\tguchar session_base_key [16];\n\tguchar key_exchange_key [16];\n\tguchar encrypted_random_session_key [16];\n\tguint32 crc;\n\tguchar client_seal_key [16];\n\tguchar client_sign_key [16];\n\tguchar server_sign_key [16];\n\tguchar server_seal_key [16];\n\tguint32 mac [4];\n\tguchar text_enc [18 + 12];\n\tstruct sipmsg *msg;\n\tstruct sipmsg_breakdown msgbd;\n\tgchar *msg_str;\n\tconst char *password2;\n\tconst char *user2;\n\tconst char *domain2;\n\tconst char *host2;\n\tconst char *type2_hex;\n\tconst char *type3_hex;\n\tconst char *request;\n\tconst char *response;\n\tconst gchar *request_sig;\n\tconst gchar *response_sig;\n\n\tprintf (\"Starting Tests\\n\");\n\n\t/* Initialization for crypto backend (test mode) */\n\tsipe_crypto_init(FALSE);\n\n\t/* Initialization for NTLM */\n\tsip_sec_init__ntlm();\n\n\t/* These tests are from the MS-SIPE document */\n\n\tpassword = \"Password\";\n\tuser = \"User\";\n\tdomain = \"Domain\";\n\tclient_challenge = (guchar *)\"\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\";\n\t/* server challenge */\n\tnonce = (guchar *)\"\\x01\\x23\\x45\\x67\\x89\\xab\\xcd\\xef\";\n\t/* 16 bytes */\n\texported_session_key = (guchar *)\"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\";\n\ttext = (guchar *)\"\\x50\\x00\\x6c\\x00\\x61\\x00\\x69\\x00\\x6e\\x00\\x74\\x00\\x65\\x00\\x78\\x00\\x74\\x00\"; //P·l·a·i·n·t·e·x·t·\n\n\n////// internal Cyphers tests ///////\n\tprintf (\"\\nTesting MD4()\\n\");\n\tMD4 ((const unsigned char *)\"message digest\", 14, md4);\n\tassert_equal(\"D9130A8164549FE818874806E1C7014B\", md4, 16, TRUE);\n\n\tprintf (\"\\nTesting MD5()\\n\");\n\tMD5 ((const unsigned char *)\"message digest\", 14, md5);\n\tassert_equal(\"F96B697D7CB7938D525A2F31AAF161D0\", md5, 16, TRUE);\n\n\tprintf (\"\\nTesting HMAC_MD5()\\n\");\n\tHMAC_MD5 ((const unsigned char *)\"\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\", 16, (const unsigned char *)\"Hi There\", 8, hmac_md5);\n\tassert_equal(\"9294727A3638BB1C13F48EF8158BFC9D\", hmac_md5, 16, TRUE);\n\n\n////// NTLMv1 (without Extended Session Security) ///////\n\tuse_ntlm_v2 = FALSE;\n\n\tflags = 0\n\t\t| NTLMSSP_NEGOTIATE_KEY_EXCH\n\t\t| NTLMSSP_NEGOTIATE_56\n\t\t| NTLMSSP_NEGOTIATE_128\n\t\t| NTLMSSP_NEGOTIATE_VERSION\n\t\t| NTLMSSP_TARGET_TYPE_SERVER\n\t\t| NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n\t\t| NTLMSSP_NEGOTIATE_NTLM\n\t\t| NTLMSSP_NEGOTIATE_SEAL\n\t\t| NTLMSSP_NEGOTIATE_SIGN\n\t\t| NTLMSSP_NEGOTIATE_OEM\n\t\t| NTLMSSP_NEGOTIATE_UNICODE;\n\n\tprintf (\"\\n\\nTesting Negotiation Flags\\n\");\n\tassert_equal_guint32(0xE2028233, flags);\n\n\tprintf (\"\\n\\nTesting LMOWFv1()\\n\");\n\tLMOWFv1 (password, user, domain, response_key_lm);\n\tassert_equal(\"E52CAC67419A9A224A3B108F3FA6CB6D\", response_key_lm, 16, TRUE);\n\n\tprintf (\"\\n\\nTesting NTOWFv1()\\n\");\n\tNTOWFv1 (password, user, domain, response_key_nt);\n\tassert_equal(\"A4F49C406510BDCAB6824EE7C30FD852\", response_key_nt, 16, TRUE);\n\n\tprintf (\"\\n\\nTesting LM Response Generation\\n\");\n\tprintf (\"Testing NT Response Generation\\n\");\n\tprintf (\"Testing Session Base Key\\n\");\n\n\tcompute_response(flags,\n\t\t\t response_key_nt,\n\t\t\t response_key_lm,\n\t\t\t nonce,\n\t\t\t client_challenge,\n\t\t\t 0,\n\t\t\t NULL, /* target_info */\n\t\t\t 0,  /* target_info_len */\n\t\t\t lm_challenge_response,\t/* out */\n\t\t\t nt_challenge_response,\t/* out */\n\t\t\t session_base_key);\t/* out */\n\n\tassert_equal(\"98DEF7B87F88AA5DAFE2DF779688A172DEF11C7D5CCDEF13\", lm_challenge_response, 24, TRUE);\n\tassert_equal(\"67C43011F30298A2AD35ECE64F16331C44BDBED927841F94\", nt_challenge_response, 24, TRUE);\n\tassert_equal(\"D87262B0CDE4B1CB7499BECCCDF10784\", session_base_key, 16, TRUE);\n\n\tprintf (\"\\n\\nTesting Key Exchange Key\\n\");\n\tKXKEY(flags, session_base_key, lm_challenge_response, nonce, key_exchange_key);\n\tassert_equal(\"D87262B0CDE4B1CB7499BECCCDF10784\", key_exchange_key, 16, TRUE);\n\n\tprintf (\"\\n\\nTesting Encrypted Session Key Generation\\n\");\n\tRC4K (key_exchange_key, 16, exported_session_key, 16, encrypted_random_session_key);\n\tassert_equal(\"518822B1B3F350C8958682ECBB3E3CB7\", encrypted_random_session_key, 16, TRUE);\n\n\tprintf (\"\\n\\nTesting CRC32\\n\");\n\tcrc = CRC32((char*)text, 18);\n\tassert_equal_guint32(0x93AA847D, crc);\n\n\tprintf (\"\\n\\nTesting Encryption\\n\");\n\t{\n\t//SEALKEY (flags, exported_session_key, TRUE, client_seal_key);\n\tguchar buff [18 + 12];\n\tguint32 to_enc [3];\n\n\tmemcpy(buff, text, 18);\n\tto_enc[0] = GUINT32_TO_LE(0); // random pad\n\tto_enc[1] = GUINT32_TO_LE(crc);\n\tto_enc[2] = GUINT32_TO_LE(0); // zero\n\tmemcpy(buff+18, (gchar *)to_enc, 12);\n\tRC4K (exported_session_key, 16, buff, 18 + 12, text_enc);\n\t//The point is to not reinitialize rc4 cypher\n\t//                                                   0          crc        0 (zero)\n\tassert_equal(\"56FE04D861F9319AF0D7238A2E3B4D457FB8\" \"45C844E5\" \"09DCD1DF\" \"2E459D36\", text_enc, 18 + 12, TRUE);\n\t}\n\n\tprintf (\"\\n\\nTesting MAC\\n\");\n\t{\n\t// won't work in the case with sealing because RC4 is re-initialized inside.\n\t// MAC (flags, (gchar*)text, 18, (guchar*)exported_session_key, 16, (guchar*)exported_session_key,16,  0x00000000,  0, mac);\n\tguint32 enc [3];\n\tguint32 mac2 [4];\n\n\tmemcpy((gchar *)enc, text_enc+18, 12);\n\tmac2 [0] = GUINT32_TO_LE(1); // version\n\tmac2 [1] = enc [0];\n\tmac2 [2] = enc [1];\n\tmac2 [3] = enc [2] ^ (GUINT32_TO_LE(0)); // ^ seq\n\tassert_equal(\"0100000045C844E509DCD1DF2E459D36\", (guchar*)mac2, 16, TRUE);\n\t}\n\n\n////// EXTENDED_SESSIONSECURITY ///////\n\tuse_ntlm_v2 = FALSE;\n\tflags = 0\n\t\t| NTLMSSP_NEGOTIATE_56\n\t\t| NTLMSSP_NEGOTIATE_VERSION\n\t\t| NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY\n\t\t| NTLMSSP_TARGET_TYPE_SERVER\n\t\t| NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n\t\t| NTLMSSP_NEGOTIATE_NTLM\n\t\t| NTLMSSP_NEGOTIATE_SEAL\n\t\t| NTLMSSP_NEGOTIATE_SIGN\n\t\t| NTLMSSP_NEGOTIATE_OEM\n\t\t| NTLMSSP_NEGOTIATE_UNICODE;\n\n\tprintf (\"\\n\\n(Extended session security) Testing Negotiation Flags\\n\");\n\tassert_equal_guint32(0x820A8233, flags);\n\n\t/* NTOWFv1() is not different from the above test for the same */\n\n\tprintf (\"\\n\\n(Extended session security) Testing LM Response\\n\");\n\tprintf (\"(Extended session security) Testing NT Response\\n\");\n\tprintf (\"(Extended session security) Testing Session Base Key\\n\");\n\tcompute_response(flags,\n\t\t\t response_key_nt,\n\t\t\t response_key_lm,\n\t\t\t nonce,\n\t\t\t client_challenge,\n\t\t\t 0,\n\t\t\t NULL, /* target_info */\n\t\t\t 0,  /* target_info_len */\n\t\t\t lm_challenge_response,\t/* out */\n\t\t\t nt_challenge_response,\t/* out */\n\t\t\t session_base_key);\t/* out */\n\n\tassert_equal(\"AAAAAAAAAAAAAAAA00000000000000000000000000000000\", lm_challenge_response, 24, TRUE);\n\tassert_equal(\"7537F803AE367128CA458204BDE7CAF81E97ED2683267232\", nt_challenge_response, 24, TRUE);\n\tassert_equal(\"D87262B0CDE4B1CB7499BECCCDF10784\", session_base_key, 16, TRUE);\n\n\tprintf (\"\\n\\n(Extended session security) Testing Key Exchange Key\\n\");\n\tKXKEY(flags, session_base_key, lm_challenge_response, nonce, key_exchange_key);\n\tassert_equal(\"EB93429A8BD952F8B89C55B87F475EDC\", key_exchange_key, 16, TRUE);\n\n\tprintf (\"\\n\\n(Extended session security) SIGNKEY\\n\");\n\tSIGNKEY (key_exchange_key, TRUE, client_sign_key);\n\tassert_equal(\"60E799BE5C72FC92922AE8EBE961FB8D\", client_sign_key, 16, TRUE);\n\n\tprintf (\"\\n\\n(Extended session security) SEALKEY\\n\");\n\tSEALKEY (flags, key_exchange_key, TRUE, client_seal_key);\n\tassert_equal(\"04DD7F014D8504D265A25CC86A3A7C06\", client_seal_key, 16, TRUE);\n\n\tprintf (\"\\n\\n(Extended session security) Testing Encryption\\n\");\n\tRC4K (client_seal_key, 16, text, 18, text_enc);\n\tassert_equal(\"A02372F6530273F3AA1EB90190CE5200C99D\", text_enc, 18, TRUE);\n\n\tprintf (\"\\n\\n(Extended session security) Testing MAC\\n\");\n\tMAC (flags,   (gchar*)text,18,   client_sign_key,16,   client_seal_key,16,   0,  0, mac);\n\tassert_equal(\"01000000FF2AEB52F681793A00000000\", mac, 16, TRUE);\n\n\n////// NTLMv2 ///////\n\tuse_ntlm_v2 = TRUE;\n\tflags = 0\n\t\t| NTLMSSP_NEGOTIATE_KEY_EXCH\n\t\t| NTLMSSP_NEGOTIATE_56\n\t\t| NTLMSSP_NEGOTIATE_128\n\t\t| NTLMSSP_NEGOTIATE_VERSION\n\t\t| NTLMSSP_NEGOTIATE_TARGET_INFO\n\t\t| NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY\n\t\t| NTLMSSP_TARGET_TYPE_SERVER\n\t\t| NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n\t\t| NTLMSSP_NEGOTIATE_NTLM\n\t\t| NTLMSSP_NEGOTIATE_SEAL\n\t\t| NTLMSSP_NEGOTIATE_SIGN\n\t\t| NTLMSSP_NEGOTIATE_OEM\n\t\t| NTLMSSP_NEGOTIATE_UNICODE;\n\n\tprintf (\"\\n\\nTesting (NTLMv2) Negotiation Flags\\n\");\n\tassert_equal_guint32(0xE28A8233, flags);\n\n\tprintf (\"\\n\\nTesting NTOWFv2()\\n\");\n\tNTOWFv2 (password, user, domain, response_key_nt);\n\tNTOWFv2 (password, user, domain, response_key_lm);\n\tassert_equal(\"0C868A403BFD7A93A3001EF22EF02E3F\", response_key_nt, 16, TRUE);\n\n\n\tprintf (\"\\n\\nTesting (NTLMv2) LM Response Generation\\n\");\n\tprintf (\"Testing (NTLMv2) NT Response Generation and Session Base Key\\n\");\n/*\nChallenge:\n4e544c4d53535000020000000c000c003800000033828ae20123456789abcdef00000000000000002400240044000000060070170000000f53006500720076006500720002000c0044006f006d00610069006e0001000c0053006500720076006500720000000000\n\n        NTLMSSP_NEGOTIATE_UNICODE\n        NTLMSSP_NEGOTIATE_OEM\n        NTLMSSP_NEGOTIATE_SIGN\n        NTLMSSP_NEGOTIATE_SEAL\n        NTLMSSP_NEGOTIATE_NTLM\n        NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n        NTLMSSP_TARGET_TYPE_SERVER\n        NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY\n        NTLMSSP_NEGOTIATE_TARGET_INFO\n        NTLMSSP_NEGOTIATE_VERSION\n        NTLMSSP_NEGOTIATE_128\n        NTLMSSP_NEGOTIATE_KEY_EXCH\n        NTLMSSP_NEGOTIATE_56\n        target_name.len   : 12\n        target_name.maxlen: 12\n        target_name.offset: 56\n        target_info.len   : 36\n        target_info.maxlen: 36\n        target_info.offset: 68\n        product: 6.0.6000 (Windows Vista, Windows Server 2008, Windows 7 or Windows Server 2008 R2)\n        ntlm_revision_current: 0x0F (NTLMSSP_REVISION_W2K3)\n        target_name: Server\n        MsvAvNbDomainName: Domain\n        MsvAvNbComputerName: Server\n\ntarget_name:\n530065007200760065007200\ntarget_info:\n02000c0044006f006d00610069006e0001000c0053006500720076006500720000000000\n\nResponse:\n4e544c4d5353500003000000180018006c00000054005400840000000c000c00480000000800080054000000100010005c00000010001000d8000000358288e20501280a0000000f44006f006d00610069006e00550073006500720043004f004d005000550054004500520086c35097ac9cec102554764a57cccc19aaaaaaaaaaaaaaaa68cd0ab851e51c96aabc927bebef6a1c01010000000000000000000000000000aaaaaaaaaaaaaaaa0000000002000c0044006f006d00610069006e0001000c005300650072007600650072000000000000000000c5dad2544fc9799094ce1ce90bc9d03e\n\n\n*/\n\t{\n\tconst guint64 time_val = 0;\n\tconst guint8 target_info [] = {\n\t\t0x02, 0x00, 0x0C, 0x00, //NetBIOS Domain name, 4 bytes\n\t\t0x44, 0x00, 0x6F, 0x00, 0x6D, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6E, 0x00, //D.o.m.a.i.n.  12bytes\n\t\t0x01, 0x00, 0x0C, 0x00, //NetBIOS Server name, 4 bytes\n\t\t0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, //S.e.r.v.e.r.  12bytes\n\t\t0x00, 0x00, 0x00, 0x00, //Av End, 4 bytes\n\t\t};\n\tconst int target_info_len = 32+4;\n\tint ntlmssp_nt_resp_len = (16 + (32+target_info_len));\n\tguchar nt_challenge_response_v2 [ntlmssp_nt_resp_len];\n\n\tcompute_response(flags,\n\t\t\t response_key_nt,\n\t\t\t response_key_lm,\n\t\t\t nonce,\n\t\t\t client_challenge,\n\t\t\t time_val,\n\t\t\t target_info, /* target_info */\n\t\t\t target_info_len,  /* target_info_len */\n\t\t\t lm_challenge_response,\t/* out */\n\t\t\t nt_challenge_response_v2,\t/* out */\n\t\t\t session_base_key);\t/* out */\n\n\tassert_equal(\"86C35097AC9CEC102554764A57CCCC19AAAAAAAAAAAAAAAA\", lm_challenge_response, 24, TRUE);\n\tassert_equal(\"68CD0AB851E51C96AABC927BEBEF6A1C\", nt_challenge_response_v2, 16, TRUE);\n\t/* the ref string is taken from binary dump of AUTHENTICATE_MESSAGE */\n\tassert_equal(\"68CD0AB851E51C96AABC927BEBEF6A1C01010000000000000000000000000000AAAAAAAAAAAAAAAA0000000002000C0044006F006D00610069006E0001000C005300650072007600650072000000000000000000\", nt_challenge_response_v2, ntlmssp_nt_resp_len, TRUE);\n\tassert_equal(\"8DE40CCADBC14A82F15CB0AD0DE95CA3\", session_base_key, 16, TRUE);\n\t}\n\n\tprintf (\"\\n\\nTesting (NTLMv2) Encrypted Session Key\\n\");\n\t// key_exchange_key = session_base_key for NTLMv2\n\tKXKEY(flags, session_base_key, lm_challenge_response, nonce, key_exchange_key);\n\t//RC4 encryption of the RandomSessionKey with the KeyExchangeKey:\n\tRC4K (key_exchange_key, 16, exported_session_key, 16, encrypted_random_session_key);\n\tassert_equal(\"C5DAD2544FC9799094CE1CE90BC9D03E\", encrypted_random_session_key, 16, TRUE);\n\n\tprintf (\"\\n\\nTesting (NTLMv2) SIGNKEY\\n\");\n\tSIGNKEY (exported_session_key, TRUE, client_sign_key);\n\tassert_equal(\"4788DC861B4782F35D43FD98FE1A2D39\", client_sign_key, 16, TRUE);\n\n\tprintf (\"\\n\\nTesting (NTLMv2) SEALKEY\\n\");\n\tSEALKEY (flags, exported_session_key, TRUE, client_seal_key);\n\tassert_equal(\"59F600973CC4960A25480A7C196E4C58\", client_seal_key, 16, TRUE);\n\n\tprintf (\"\\n\\nTesting (NTLMv2) Encryption\\n\");\n\tRC4K (client_seal_key, 16, text, 18, text_enc);\n\tassert_equal(\"54E50165BF1936DC996020C1811B0F06FB5F\", text_enc, 18, TRUE);\n\n//\tprintf (\"\\n\\nTesting (NTLMv2) Encryption\\n\");\n//const guchar text2 [] = {0x50, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x78, 0x00, 0x74, 0x00\n//\t\t\t, 0x70, 0x35, 0x28, 0x51, 0xf2, 0x56, 0x43, 0x09}; //P·l·a·i·n·t·e·x·t·\n//guchar text_enc2 [18+8];\n//\tRC4K (client_seal_key, 16, text2, 18+8, text_enc2);\n//\tassert_equal(\"54E50165BF1936DC996020C1811B0F06FB5F\", text_enc2, 18+8, TRUE);\n\n\tprintf (\"\\n\\nTesting (NTLMv2) MAC (without RC4, as we don't keep its handle yet)\\n\");\n\tMAC (flags & ~NTLMSSP_NEGOTIATE_KEY_EXCH,   (gchar*)text,18,   client_sign_key,16,   client_seal_key,16,   0,  0, mac);\n\tassert_equal(\"0100000070352851F256430900000000\", mac, 16, TRUE);\n\n\n\t/* End tests from the MS-SIPE document */\n\n\n////// davenport tests ///////\n\t// Test from http://davenport.sourceforge.net/ntlm.html#ntlm1Signing\n\t{\n\tconst gchar *text_j = \"jCIFS\";\n\tprintf (\"\\n\\n(davenport) Testing Signature Algorithm\\n\");\n\t{\n\tguchar sk [] = {0x01, 0x02, 0x03, 0x04, 0x05, 0xe5, 0x38, 0xb0};\n\tMAC (NEGOTIATE_FLAGS_CONNLESS & ~NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY, text_j, strlen(text_j), sk, 8,  sk,8,  0x00090178, 0, mac);\n\tassert_equal(\"0100000078010900397420FE0E5A0F89\", mac, 16, TRUE);\n\t}\n\n\t// Tests from http://davenport.sourceforge.net/ntlm.html#ntlm2Signing\n\tprintf (\"\\n\\n(davenport) SIGNKEY\\n\");\n\t{\n\tconst guchar master_key [] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00};\n\tSIGNKEY (master_key, TRUE, client_sign_key);\n\tassert_equal(\"F7F97A82EC390F9C903DAC4F6ACEB132\", client_sign_key, 16, TRUE);\n\n\tprintf (\"\\n\\n(davenport) Testing MAC - no Key Exchange flag\\n\");\n\tMAC (flags & ~NTLMSSP_NEGOTIATE_KEY_EXCH, text_j, strlen(text_j), client_sign_key, 16,  client_sign_key,16,  0,  0, mac);\n\tassert_equal(\"010000000A003602317A759A00000000\", mac, 16, TRUE);\n\t}\n\t}\n\n\n////// SIPE internal tests ///////\n\t// Verify signature of SIPE message received from OCS 2007 after authenticating with pidgin-sipe\n\tprintf (\"\\n\\nTesting MS-SIPE Example Message Signing\\n\");\n\t{\n\tconst char * msg2;\n\tconst char * msg1 = \"<NTLM><0878F41B><1><SIP Communications Service><ocs1.ocs.provo.novell.com><8592g5DCBa1694i5887m0D0Bt2247b3F38xAE9Fx><3><REGISTER><sip:gabriel@ocs.provo.novell.com><2947328781><B816D65C2300A32CFA6D371F2AF537FD><900><200>\";\n\tguchar exported_session_key2 [] = { 0x5F, 0x02, 0x91, 0x53, 0xBC, 0x02, 0x50, 0x58, 0x96, 0x95, 0x48, 0x61, 0x5E, 0x70, 0x99, 0xBA };\n\n\tMAC (NEGOTIATE_FLAGS_CONNLESS & ~NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY,\n\t\tmsg1, strlen(msg1), exported_session_key2, 16,  exported_session_key2,16,  0, 100, mac);\n\tassert_equal(\"0100000000000000BF2E52667DDF6DED\", mac, 16, TRUE);\n\n\t// Verify parsing of message and signature verification\n\tprintf (\"\\n\\nTesting MS-SIPE Example Message Parsing, Signing, and Verification\\n(Authentication Protocol Version 2)\\n\");\n\tmsg2 = \"SIP/2.0 200 OK\\r\\nms-keep-alive: UAS; tcp=no; hop-hop=yes; end-end=no; timeout=300\\r\\nAuthentication-Info: NTLM rspauth=\\\"0100000000000000BF2E52667DDF6DED\\\", srand=\\\"0878F41B\\\", snum=\\\"1\\\", opaque=\\\"4452DFB0\\\", qop=\\\"auth\\\", targetname=\\\"ocs1.ocs.provo.novell.com\\\", realm=\\\"SIP Communications Service\\\"\\r\\nFrom: \\\"Gabriel Burt\\\"<sip:gabriel@ocs.provo.novell.com>;tag=2947328781;epid=1234567890\\r\\nTo: <sip:gabriel@ocs.provo.novell.com>;tag=B816D65C2300A32CFA6D371F2AF537FD\\r\\nCall-ID: 8592g5DCBa1694i5887m0D0Bt2247b3F38xAE9Fx\\r\\nCSeq: 3 REGISTER\\r\\nVia: SIP/2.0/TLS 164.99.194.49:10409;branch=z9hG4bKE0E37DBAF252C3255BAD;received=164.99.195.20;ms-received-port=10409;ms-received-cid=1E00\\r\\nContact: <sip:164.99.195.20:10409;transport=tls;ms-received-cid=1E00>;expires=900\\r\\nExpires: 900\\r\\nAllow-Events: vnd-microsoft-provisioning,vnd-microsoft-roaming-contacts,vnd-microsoft-roaming-ACL,presence,presence.wpending,vnd-microsoft-roaming-self,vnd-microsoft-provisioning-v2\\r\\nSupported: adhoclist\\r\\nServer: RTC/3.0\\r\\nSupported: com.microsoft.msrtc.presence\\r\\nContent-Length: 0\\r\\n\\r\\n\";\n\tmsg = sipmsg_parse_msg(msg2);\n\n\tmemset(&msgbd, 0, sizeof(struct sipmsg_breakdown));\n\tmsgbd.msg = msg;\n\tsipmsg_breakdown_parse(&msgbd, \"SIP Communications Service\", \"ocs1.ocs.provo.novell.com\", NULL);\n\tmsg_str = sipmsg_breakdown_get_string(2, &msgbd);\n\tsip_sec_ntlm_sipe_signature_make (NEGOTIATE_FLAGS_CONNLESS & ~NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY,\n\t\tmsg_str, 0, exported_session_key2, exported_session_key2, mac);\n\tsipmsg_breakdown_free(&msgbd);\n\tassert_equal (\"0100000000000000BF2E52667DDF6DED\", mac, 16, TRUE);\n\t/* sig = buff_to_hex_str((guint8 *)mac, 16); */\n\t}\n\n\n////// real Communicator 2007 R2 tests //////\n////// Recreated/verifyed real authentication communication between\n////// Communicator 2007 R2 and Office Communications Server 2007 R2\n////// with SIPE NTLMv2 implementation.\n\n\tpassword2 = \"Pa$$word\";\n\tuser2 = \"User\";\n\tdomain2 = \"COSMO\";\n\thost2 = \"COSMO-OCS-R2\";\n\n//Challenge:\n//const char *type2 = \"TlRMTVNTUAACAAAAAAAAADgAAADzgpji3Ruq9OfiGNEAAAAAAAAAAJYAlgA4AAAABQLODgAAAA8CAAoAQwBPAFMATQBPAAEAGABDAE8AUwBNAE8ALQBPAEMAUwAtAFIAMgAEABYAYwBvAHMAbQBvAC4AbABvAGMAYQBsAAMAMABjAG8AcwBtAG8ALQBvAGMAcwAtAHIAMgAuAGMAbwBzAG0AbwAuAGwAbwBjAGEAbAAFABYAYwBvAHMAbQBvAC4AbABvAGMAYQBsAAAAAAA=\";\n//in hex (base64 decoded):\ntype2_hex = \"4E544C4D53535000020000000000000038000000F38298E2DD1BAAF4E7E218D1000000000000000096009600380000000502CE0E0000000F02000A0043004F0053004D004F000100180043004F0053004D004F002D004F00430053002D00520032000400160063006F0073006D006F002E006C006F00630061006C000300300063006F0073006D006F002D006F00630073002D00720032002E0063006F0073006D006F002E006C006F00630061006C000500160063006F0073006D006F002E006C006F00630061006C0000000000\";\n/*\nMessage (length 206):\n        NTLMSSP_NEGOTIATE_UNICODE\n        NTLMSSP_NEGOTIATE_OEM\n        NTLMSSP_NEGOTIATE_SIGN\n        NTLMSSP_NEGOTIATE_SEAL\n        NTLMSSP_NEGOTIATE_DATAGRAM\n        NTLMSSP_NEGOTIATE_LM_KEY\n        NTLMSSP_NEGOTIATE_NTLM\n        NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n        NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY\n        NTLMSSP_NEGOTIATE_IDENTIFY\n        NTLMSSP_NEGOTIATE_TARGET_INFO\n        NTLMSSP_NEGOTIATE_VERSION\n        NTLMSSP_NEGOTIATE_128\n        NTLMSSP_NEGOTIATE_KEY_EXCH\n        NTLMSSP_NEGOTIATE_56\n        server_challenge: DD1BAAF4E7E218D1\n        target_name.len   : 0\n        target_name.maxlen: 0\n        target_name.offset: 56\n        target_info.len   : 150\n        target_info.maxlen: 150\n        target_info.offset: 56\n        product: 5.2.3790 (Windows Server 2003)\n        ntlm_revision_current: 0x0F (NTLMSSP_REVISION_W2K3)\n        target_info raw: 02000A0043004F0053004D004F000100180043004F0053004D004F002D004F00430053002D00520032000400160063006F0073006D006F002E006C006F00630061006C000300300063006F0073006D006F002D006F00630073002D00720032002E0063006F0073006D006F002E006C006F00630061006C000500160063006F0073006D006F002E006C006F00630061006C0000000000\n        MsvAvNbDomainName: COSMO\n        MsvAvNbComputerName: COSMO-OCS-R2\n        MsvAvDnsDomainName: cosmo.local\n        MsvAvDnsComputerName: cosmo-ocs-r2.cosmo.local\n        MsvAvDnsTreeName: cosmo.local\n*/\n\n\n//Response:\n//const char *type3 = \"TlRMTVNTUAADAAAAGAAYAHIAAADGAMYAigAAAAoACgBIAAAACAAIAFIAAAAYABgAWgAAABAAEABQAQAAVYKYYgUCzg4AAAAPQwBPAFMATQBPAFUAcwBlAHIAQwBPAFMATQBPAC0ATwBDAFMALQBSADIAoeku/k4Hi/fFwASazGFmwtauh1yw/apBjcDIAK527KYG0rn769BHMQEBAAAAAAAAWVGaFye5ygHWrodcsP2qQQAAAAACAAoAQwBPAFMATQBPAAEAGABDAE8AUwBNAE8ALQBPAEMAUwAtAFIAMgAEABYAYwBvAHMAbQBvAC4AbABvAGMAYQBsAAMAMABjAG8AcwBtAG8ALQBvAGMAcwAtAHIAMgAuAGMAbwBzAG0AbwAuAGwAbwBjAGEAbAAFABYAYwBvAHMAbQBvAC4AbABvAGMAYQBsAAAAAAAAAAAAMctznhyoCkmFkeiueXEV5A==\";\n//in hex (base64 decoded):\ntype3_hex = \"4E544C4D53535000030000001800180072000000C600C6008A0000000A000A00480000000800080052000000180018005A0000001000100050010000558298620502CE0E0000000F43004F0053004D004F00550073006500720043004F0053004D004F002D004F00430053002D0052003200A1E92EFE4E078BF7C5C0049ACC6166C2D6AE875CB0FDAA418DC0C800AE76ECA606D2B9FBEBD04731010100000000000059519A1727B9CA01D6AE875CB0FDAA410000000002000A0043004F0053004D004F000100180043004F0053004D004F002D004F00430053002D00520032000400160063006F0073006D006F002E006C006F00630061006C000300300063006F0073006D006F002D006F00630073002D00720032002E0063006F0073006D006F002E006C006F00630061006C000500160063006F0073006D006F002E006C006F00630061006C00000000000000000031CB739E1CA80A498591E8AE797115E4\";\n/*\nMessage (length 352):\n        NTLMSSP_NEGOTIATE_UNICODE\n        NTLMSSP_REQUEST_TARGET\n        NTLMSSP_NEGOTIATE_SIGN\n        NTLMSSP_NEGOTIATE_DATAGRAM\n        NTLMSSP_NEGOTIATE_NTLM\n        NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n        NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY\n        NTLMSSP_NEGOTIATE_IDENTIFY\n        NTLMSSP_NEGOTIATE_TARGET_INFO\n        NTLMSSP_NEGOTIATE_VERSION\n        NTLMSSP_NEGOTIATE_128\n        NTLMSSP_NEGOTIATE_KEY_EXCH\n        lm_resp.len   : 24\n        lm_resp.maxlen: 24\n        lm_resp.offset: 114\n        nt_resp.len   : 198\n        nt_resp.maxlen: 198\n        nt_resp.offset: 138\n        domain.len   : 10\n        domain.maxlen: 10\n        domain.offset: 72\n        user.len   : 8\n        user.maxlen: 8\n        user.offset: 82\n        host.len   : 24\n        host.maxlen: 24\n        host.offset: 90\n        session_key.len   : 16\n        session_key.maxlen: 16\n        session_key.offset: 336\n        product: 5.2.3790 (Windows Server 2003)\n        ntlm_revision_current: 0x0F (NTLMSSP_REVISION_W2K3)\n        lm_resp: A1E92EFE4E078BF7C5C0049ACC6166C2D6AE875CB0FDAA41\n        nt_resp raw: 8DC0C800AE76ECA606D2B9FBEBD04731010100000000000059519A1727B9CA01D6AE875CB0FDAA410000000002000A0043004F0053004D004F000100180043004F0053004D004F002D004F00430053002D00520032000400160063006F0073006D006F002E006C006F00630061006C000300300063006F0073006D006F002D006F00630073002D00720032002E0063006F0073006D006F002E006C006F00630061006C000500160063006F0073006D006F002E006C006F00630061006C000000000000000000\n        nt_resp: 8DC0C800AE76ECA606D2B9FBEBD04731\n        target_info raw: 02000A0043004F0053004D004F000100180043004F0053004D004F002D004F00430053002D00520032000400160063006F0073006D006F002E006C006F00630061006C000300300063006F0073006D006F002D006F00630073002D00720032002E0063006F0073006D006F002E006C006F00630061006C000500160063006F0073006D006F002E006C006F00630061006C0000000000\n        response_version: 1\n        hi_response_version: 1\n        time: 59519A1727B9CA01 - Mon Mar 01 10:08:08 2010\n        client_challenge: D6AE875CB0FDAA41\n        MsvAvNbDomainName: COSMO\n        MsvAvNbComputerName: COSMO-OCS-R2\n        MsvAvDnsDomainName: cosmo.local\n        MsvAvDnsComputerName: cosmo-ocs-r2.cosmo.local\n        MsvAvDnsTreeName: cosmo.local\n        ----------- end of nt_resp v2 -----------\n        domain: COSMO\n        user: User\n        host: COSMO-OCS-R2\n        session_key: 31CB739E1CA80A498591E8AE797115E4\n*/\n\n\trequest =\n\t\"REGISTER sip:cosmo.local SIP/2.0\\r\\n\"\n\t\"Via: SIP/2.0/TLS 192.168.172.6:12723\\r\\n\"\n\t\"Max-Forwards: 70\\r\\n\"\n\t\"From: <sip:user@cosmo.local>;tag=3e49177a52;epid=c8ca638a15\\r\\n\"\n\t\"To: <sip:user@cosmo.local>\\r\\n\"\n\t\"Call-ID: 4037df9284354df39065195bd57a4b14\\r\\n\"\n\t\"CSeq: 3 REGISTER\\r\\n\"\n\t\"Contact: <sip:192.168.172.6:12723;transport=tls;ms-opaque=fad3dfab32>;methods=\\\"INVITE, MESSAGE, INFO, OPTIONS, BYE, CANCEL, NOTIFY, ACK, REFER, BENOTIFY\\\";proxy=replace;+sip.instance=\\\"<urn:uuid:34D859DB-6585-5F91-A3B4-DE853C15347D>\\\"\\r\\n\"\n\t\"User-Agent: UCCAPI/3.5.6907.0 OC/3.5.6907.0 (Microsoft Office Communicator 2007 R2)\\r\\n\"\n\t\"Supported: gruu-10, adhoclist, msrtc-event-categories\\r\\n\"\n\t\"Supported: ms-forking\\r\\n\"\n\t\"ms-keep-alive: UAC;hop-hop=yes\\r\\n\"\n\t\"Event: registration\\r\\n\"\n\t\"Proxy-Authorization: NTLM qop=\\\"auth\\\", realm=\\\"SIP Communications Service\\\", opaque=\\\"2BDBAC9D\\\", targetname=\\\"cosmo-ocs-r2.cosmo.local\\\", version=4, gssapi-data=\\\"TlRMTVNTUAADAAAAGAAYAHIAAADGAMYAigAAAAoACgBIAAAACAAIAFIAAAAYABgAWgAAABAAEABQAQAAVYKYYgUCzg4AAAAPQwBPAFMATQBPAFUAcwBlAHIAQwBPAFMATQBPAC0ATwBDAFMALQBSADIAoeku/k4Hi/fFwASazGFmwtauh1yw/apBjcDIAK527KYG0rn769BHMQEBAAAAAAAAWVGaFye5ygHWrodcsP2qQQAAAAACAAoAQwBPAFMATQBPAAEAGABDAE8AUwBNAE8ALQBPAEMAUwAtAFIAMgAEABYAYwBvAHMAbQBvAC4AbABvAGMAYQBsAAMAMABjAG8AcwBtAG8ALQBvAGMAcwAtAHIAMgAuAGMAbwBzAG0AbwAuAGwAbwBjAGEAbAAFABYAYwBvAHMAbQBvAC4AbABvAGMAYQBsAAAAAAAAAAAAMctznhyoCkmFkeiueXEV5A==\\\", crand=\\\"13317733\\\", cnum=\\\"1\\\", response=\\\"0100000029618e9651b65a7764000000\\\"\\r\\n\"\n\t\"Content-Length: 0\\r\\n\"\n\t\"\\r\\n\";\n\n\trequest_sig = \"<NTLM><13317733><1><SIP Communications Service><cosmo-ocs-r2.cosmo.local><4037df9284354df39065195bd57a4b14><3><REGISTER><sip:user@cosmo.local><3e49177a52><sip:user@cosmo.local><><><><>\";\n//Signature:\n//0100000029618e9651b65a7764000000\n\n\tresponse =\n\t\"SIP/2.0 200 OK\\r\\n\"\n\t\"ms-keep-alive: UAS; tcp=no; hop-hop=yes; end-end=no; timeout=300\\r\\n\"\n\t\"Authentication-Info: NTLM rspauth=\\\"01000000E615438A917661BE64000000\\\", srand=\\\"9616454F\\\", snum=\\\"1\\\", opaque=\\\"2BDBAC9D\\\", qop=\\\"auth\\\", targetname=\\\"cosmo-ocs-r2.cosmo.local\\\", realm=\\\"SIP Communications Service\\\"\\r\\n\"\n\t\"From: \\\"User\\\"<sip:user@cosmo.local>;tag=3e49177a52;epid=c8ca638a15\\r\\n\"\n\t\"To: <sip:user@cosmo.local>;tag=5E61CCD925D17E043D9A74835A88F664\\r\\n\"\n\t\"Call-ID: 4037df9284354df39065195bd57a4b14\\r\\n\"\n\t\"CSeq: 3 REGISTER\\r\\n\"\n\t\"Via: SIP/2.0/TLS 192.168.172.6:12723;ms-received-port=12723;ms-received-cid=2600\\r\\n\"\n\t\"Contact: <sip:192.168.172.6:12723;transport=tls;ms-opaque=fad3dfab32;ms-received-cid=2600>;expires=7200;+sip.instance=\\\"<urn:uuid:34d859db-6585-5f91-a3b4-de853c15347d>\\\";gruu=\\\"sip:user@cosmo.local;opaque=user:epid:21nYNIVlkV-jtN6FPBU0fQAA;gruu\\\"\\r\\n\"\n\t\"Expires: 7200\\r\\n\"\n\t\"presence-state: register-action=\\\"added\\\"\\r\\n\"\n\t\"Allow-Events: vnd-microsoft-provisioning,vnd-microsoft-roaming-contacts,vnd-microsoft-roaming-ACL,presence,presence.wpending,vnd-microsoft-roaming-self,vnd-microsoft-provisioning-v2\\r\\n\"\n\t\"Supported: adhoclist\\r\\n\"\n\t\"Server: RTC/3.5\\r\\n\"\n\t\"Supported: msrtc-event-categories\\r\\n\"\n\t\"Content-Length: 0\\r\\n\"\n\t\"\\r\\n\";\n\n\tresponse_sig = \"<NTLM><9616454F><1><SIP Communications Service><cosmo-ocs-r2.cosmo.local><4037df9284354df39065195bd57a4b14><3><REGISTER><sip:user@cosmo.local><3e49177a52><sip:user@cosmo.local><5E61CCD925D17E043D9A74835A88F664><><><7200><200>\";\n//Signature:\n//01000000E615438A917661BE64000000\n\n\tuse_ntlm_v2 = TRUE;\n\tflags = 0\n\t\t| NTLMSSP_NEGOTIATE_UNICODE\n\t\t| NTLMSSP_REQUEST_TARGET\n\t\t| NTLMSSP_NEGOTIATE_SIGN\n\t\t| NTLMSSP_NEGOTIATE_DATAGRAM\n\t\t| NTLMSSP_NEGOTIATE_NTLM\n\t\t| NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n\t\t| NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY\n\t\t| NTLMSSP_NEGOTIATE_IDENTIFY\n\t\t| NTLMSSP_NEGOTIATE_TARGET_INFO\n\t\t| NTLMSSP_NEGOTIATE_VERSION\n\t\t| NTLMSSP_NEGOTIATE_128\n\t\t| NTLMSSP_NEGOTIATE_KEY_EXCH;\n\n\t/* global struct */\n\ttest_version.product_major_version = 5;\n\ttest_version.product_minor_version = 2;\n\ttest_version.product_build = GUINT16_FROM_LE(3790);\n\ttest_version.ntlm_revision_current = 0x0F;\n\n\tNTOWFv2 (password2, user2, domain2, response_key_nt);\n\tNTOWFv2 (password2, user2, domain2, response_key_lm);\n\n\t{\n\tint ntlmssp_nt_resp_len;\n\tint target_info2_len;\n\tguint8 *nonce2;\n\tguint8 *target_info2;\n\tguint64 *buff2;\n\t/* buff2 points to correctly aligned memory. Disable alignment check */\n\thex_str_to_buff(\"59519A1727B9CA01\", (void *)&buff2);\n\t/* global var */\n\ttest_time_val = GUINT64_FROM_LE(*buff2);\n\tg_free(buff2);\n\tbuff2 = NULL;\n\n\ttarget_info2_len = hex_str_to_buff(\"02000A0043004F0053004D004F000100180043004F0053004D004F002D004F00430053002D00520032000400160063006F0073006D006F002E006C006F00630061006C000300300063006F0073006D006F002D006F00630073002D00720032002E0063006F0073006D006F002E006C006F00630061006C000500160063006F0073006D006F002E006C006F00630061006C0000000000\", &target_info2);\n\n\thex_str_to_buff(\"DD1BAAF4E7E218D1\", &nonce2);\n\n\t/* buff2 points to correctly aligned memory. Disable alignment check */\n\thex_str_to_buff(\"D6AE875CB0FDAA41\", (void *)&buff2);\n\t/* global buff */\n\tmemcpy(test_client_challenge, buff2, 8);\n\tg_free(buff2);\n\n\tntlmssp_nt_resp_len = (16 + (32+target_info2_len));\n\t{\n\tguchar nt_challenge_response_v2_2 [ntlmssp_nt_resp_len];\n\n\tprintf (\"\\n\\nTesting (NTLMv2 / OC 2007 R2) LM Response Generation\\n\");\n\tprintf (    \"Testing (NTLMv2 / OC 2007 R2) NT Response Generation\\n\");\n\tcompute_response(flags,\n\t\t\t response_key_nt,\n\t\t\t response_key_lm,\n\t\t\t nonce2,\n\t\t\t test_client_challenge,\n\t\t\t test_time_val,\n\t\t\t target_info2, /* target_info */\n\t\t\t target_info2_len,  /* target_info_len */\n\t\t\t lm_challenge_response,\t/* out */\n\t\t\t nt_challenge_response_v2_2,\t/* out */\n\t\t\t session_base_key);\t/* out */\n\tg_free(target_info2);\n\n\tassert_equal(\"A1E92EFE4E078BF7C5C0049ACC6166C2D6AE875CB0FDAA41\", lm_challenge_response, 24, TRUE);\n\tassert_equal(\"8DC0C800AE76ECA606D2B9FBEBD04731\", nt_challenge_response_v2_2, 16, TRUE);\n\t/* the ref string is taken from binary dump of AUTHENTICATE_MESSAGE */\n\tassert_equal(\"8DC0C800AE76ECA606D2B9FBEBD04731010100000000000059519A1727B9CA01D6AE875CB0FDAA410000000002000A0043004F0053004D004F000100180043004F0053004D004F002D004F00430053002D00520032000400160063006F0073006D006F002E006C006F00630061006C000300300063006F0073006D006F002D006F00630073002D00720032002E0063006F0073006D006F002E006C006F00630061006C000500160063006F0073006D006F002E006C006F00630061006C000000000000000000\", nt_challenge_response_v2_2, ntlmssp_nt_resp_len, TRUE);\n\t}\n\n\tKXKEY(flags, session_base_key, lm_challenge_response, nonce2, key_exchange_key);\n\tg_free(nonce2);\n\n\t}\n\n\t//as in the Type3 message\n\t{\n\tguint8 *encrypted_random_session_key2;\n\thex_str_to_buff(\"31CB739E1CA80A498591E8AE797115E4\", &encrypted_random_session_key2);\n\t/* global buff - test_random_session_key */\n\t//decoding exported_session_key\n\tRC4K (key_exchange_key, 16, encrypted_random_session_key2, 16, test_random_session_key);\n\tg_free(encrypted_random_session_key2);\n\t}\n\n\tSIGNKEY (test_random_session_key, TRUE, client_sign_key);\n\tSEALKEY (flags, test_random_session_key, TRUE, client_seal_key);\n\tSIGNKEY (test_random_session_key, FALSE, server_sign_key);\n\tSEALKEY (flags, test_random_session_key, FALSE, server_seal_key);\n\n\tprintf (\"\\n\\nTesting (NTLMv2 / OC 2007 R2) Message Parsing, Signing, and Verification\\nClient request\\n(Authentication Protocol version 4)\\n\");\n\tmsg = sipmsg_parse_msg(request);\n\tmemset(&msgbd, 0, sizeof(struct sipmsg_breakdown));\n\tmsgbd.msg = msg;\n\tsipmsg_breakdown_parse(&msgbd, \"SIP Communications Service\", \"cosmo-ocs-r2.cosmo.local\", NULL);\n\tmsg_str = sipmsg_breakdown_get_string(4, &msgbd);\n\tassert_equal (request_sig, (guchar *)msg_str, strlen(request_sig), FALSE);\n\tsip_sec_ntlm_sipe_signature_make (flags, msg_str, 0, client_sign_key, client_seal_key, mac);\n\tsipmsg_breakdown_free(&msgbd);\n\tassert_equal (\"0100000029618e9651b65a7764000000\", mac, 16, TRUE);\n\t/* sig = buff_to_hex_str((guint8 *)mac, 16); */\n\n\tprintf (\"\\n\\nTesting (NTLMv2 / OC 2007 R2) Message Parsing, Signing, and Verification\\nServer response\\n(Authentication Protocol version 4)\\n\");\n\tmsg = sipmsg_parse_msg(response);\n\tmemset(&msgbd, 0, sizeof(struct sipmsg_breakdown));\n\tmsgbd.msg = msg;\n\tsipmsg_breakdown_parse(&msgbd, \"SIP Communications Service\", \"cosmo-ocs-r2.cosmo.local\", NULL);\n\tmsg_str = sipmsg_breakdown_get_string(4, &msgbd);\n\tassert_equal (response_sig, (guchar *)msg_str, strlen(response_sig), FALSE);\n\t// server keys here\n\tsip_sec_ntlm_sipe_signature_make (flags, msg_str, 0, server_sign_key, server_seal_key, mac);\n\tsipmsg_breakdown_free(&msgbd);\n\tassert_equal (\"01000000E615438A917661BE64000000\", mac, 16, TRUE);\n\t/* sig = buff_to_hex_str((guint8 *)mac, 16); */\n\n\tprintf (\"\\n\\nTesting (NTLMv2 / OC 2007 R2) MAC - client signing\\n\");\n\tMAC (flags,   (gchar*)request_sig,strlen(request_sig),   client_sign_key,16,   client_seal_key,16,   0,  100, mac);\n\tassert_equal(\"0100000029618e9651b65a7764000000\", mac, 16, TRUE);\n\n\tprintf (\"\\n\\nTesting (NTLMv2 / OC 2007 R2) MAC - server's verifying\\n\");\n\tMAC (flags,   (gchar*)response_sig,strlen(response_sig),   server_sign_key,16,   server_seal_key,16,   0,  100, mac);\n\tassert_equal(\"01000000E615438A917661BE64000000\", mac, 16, TRUE);\n\n\tprintf (\"\\n\\nTesting (NTLMv2 / OC 2007 R2) Type3 generation test\\n\");\n\t{\n\tguchar *client_sign_key2;\n\tguchar *server_sign_key2;\n\tguchar *client_seal_key2;\n\tguchar *server_seal_key2;\n\n\tguchar *server_challenge = NULL;\n\tguint64 time_val2 = 0;\n\tguchar *target_info3 = NULL;\n\tint target_info3_len = 0;\n\tguint32 flags2;\n\tSipSecBuffer in_buff;\n\tSipSecBuffer out_buff;\n\n\tmemset(&in_buff,  0, sizeof(in_buff));\n\tmemset(&out_buff, 0, sizeof(out_buff));\n\n\tin_buff.length = hex_str_to_buff(type2_hex, (guint8 **)&(in_buff.value));\n\n\tsip_sec_ntlm_parse_challenge(in_buff,\n\t\t\t\t     &flags2, /* out */\n\t\t\t\t     &server_challenge,\n\t\t\t\t     &time_val2,\n\t\t\t\t     &target_info3,\n\t\t\t\t     &target_info3_len);\n\n\tsip_sec_ntlm_gen_authenticate(&client_sign_key2,\n\t\t\t\t      &server_sign_key2,\n\t\t\t\t      &client_seal_key2,\n\t\t\t\t      &server_seal_key2,\n\t\t\t\t      user2,\n\t\t\t\t      password2,\n\t\t\t\t      host2,\n\t\t\t\t      domain2,\n\t\t\t\t      server_challenge,\n\t\t\t\t      test_time_val,\n\t\t\t\t      target_info3,\n\t\t\t\t      target_info3_len,\n\t\t\t\t      0,\n\t\t\t\t      &out_buff,\n\t\t\t\t      &flags2);\n\n\tg_free(server_challenge);\n\tg_free(target_info3);\n\n\tassert_equal(type3_hex, out_buff.value, out_buff.length, TRUE);\n\t}\n\n\tprintf (\"\\nFinished With Tests; %d successs %d failures\\n\", successes, failures);\n\n\tsip_sec_destroy__ntlm();\n\n\treturn(failures == 0);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sip-sec-ntlm.c",
    "content": "/**\n * @file sip-sec-ntlm.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2009, 2010 pier11 <pier11@operamail.com>\n * Copyright (C) 2008 Novell, Inc.\n * Modify        2007, Anibal Avelar <avelar@gmail.com>\n * Copyright (C) 2005, Thomas Butter <butter@uni-mannheim.de>\n *\n * Implemented with reference to the follow documentation:\n *   - http://davenport.sourceforge.net/ntlm.html\n *   - MS-NLMP: http://msdn.microsoft.com/en-us/library/cc207842.aspx\n *   - MS-SIP : http://msdn.microsoft.com/en-us/library/cc246115.aspx\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/*\n * Byte order policy:\n *\n *  - NTLM messages (byte streams) should be in LE (Little-Endian) byte order.\n *  - internal int16, int32, int64 should contain proper values.\n *     For example: 01 00 00 00 LE should be translated to (int32)1\n *  - When reading/writing from/to NTLM message appropriate conversion should\n *    be taken to properly present integer values. glib's \"Byte Order Macros\"\n *    should be used for that, for example GUINT32_FROM_LE\n *\n *    NOTE: The Byte Order Macros can have side effects!\n *          Do *NOT* make any calculations inside the macros!\n *\n *  - All calculations should be made in dedicated local variables (system-endian),\n *    not in NTLM (LE) structures.\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#include <glib.h>\n\n#ifdef HAVE_LANGINFO_CODESET\n#include <langinfo.h>\n#endif /* HAVE_LANGINFO_CODESET */\n\n#include \"sipe-common.h\"\n#include \"sip-sec.h\"\n#include \"sip-sec-mech.h\"\n#include \"sip-sec-ntlm.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-crypt.h\"\n#include \"sipe-digest.h\"\n#include \"sipe-utils.h\"\n\n#include \"md4.h\"\n\n/* [MS-NLMP] */\n#define NTLMSSP_NEGOTIATE_UNICODE\t\t\t0x00000001\t/* A  */\n#define NTLMSSP_NEGOTIATE_OEM\t\t\t\t0x00000002\t/* B  */\n#define NTLMSSP_REQUEST_TARGET\t\t\t\t0x00000004\t/* C  */\n#define r9\t\t\t\t\t\t0x00000008\t/* r9 */\n#define NTLMSSP_NEGOTIATE_SIGN\t\t\t\t0x00000010\t/* D  */\n#define NTLMSSP_NEGOTIATE_SEAL\t\t\t\t0x00000020\t/* E  */\n#define NTLMSSP_NEGOTIATE_DATAGRAM\t\t\t0x00000040\t/* F  */\n#define NTLMSSP_NEGOTIATE_LM_KEY\t\t\t0x00000080\t/* G  */\n#define r8\t\t\t\t\t\t0x00000100\t/* r8 */\n#define NTLMSSP_NEGOTIATE_NTLM\t\t\t\t0x00000200\t/* H  */\n#define NTLMSSP_NEGOTIATE_NT_ONLY\t\t\t0x00000400\t/* I  */\n#define anonymous\t\t\t\t\t0x00000800\t/* J  */\n#define NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED\t\t0x00001000\t/* K  */\n#define NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED\t0x00002000\t/* L  */\n#define r7\t\t\t\t\t\t0x00004000\t/* r7 */\n#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN\t\t\t0x00008000\t/* M  */\n#define NTLMSSP_TARGET_TYPE_DOMAIN\t\t\t0x00010000\t/* N  */\n#define NTLMSSP_TARGET_TYPE_SERVER\t\t\t0x00020000\t/* O  */\n#define r6\t\t\t\t\t\t0x00040000\t/* r6 */\n#define NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY\t0x00080000\t/* P  */\n#define NTLMSSP_NEGOTIATE_IDENTIFY\t\t\t0x00100000\t/* Q  */\n#define r5\t\t\t\t\t\t0x00200000\t/* r5 */\n#define NTLMSSP_REQUEST_NON_NT_SESSION_KEY\t\t0x00400000\t/* R  */\n#define NTLMSSP_NEGOTIATE_TARGET_INFO\t\t\t0x00800000\t/* S  */\n#define r4\t\t\t\t\t\t0x01000000\t/* r4 */\n#define NTLMSSP_NEGOTIATE_VERSION\t\t\t0x02000000\t/* T  */\n#define r3\t\t\t\t\t\t0x04000000\t/* r3 */\n#define r2\t\t\t\t\t\t0x08000000\t/* r2 */\n#define r1\t\t\t\t\t\t0x10000000\t/* r1 */\n#define NTLMSSP_NEGOTIATE_128\t\t\t\t0x20000000\t/* U  */\n#define NTLMSSP_NEGOTIATE_KEY_EXCH\t\t\t0x40000000\t/* V  */\n#define NTLMSSP_NEGOTIATE_56\t\t\t\t0x80000000\t/* W  */\n\n/* AvId */\n#define MsvAvEOL\t\t0\n#define MsvAvNbComputerName\t1\n#define MsvAvNbDomainName\t2\n#define MsvAvDnsComputerName\t3\n#define MsvAvDnsDomainName\t4\n/** @since Windows XP */\n#define MsvAvDnsTreeName\t5\n/** @since Windows XP */\n#define MsvAvFlags\t\t6\n/** @since Windows Vista */\n#define MsvAvTimestamp\t\t7\n/** @since Windows Vista */\n#define MsAvRestrictions\t8\n/** @since Windows 7 */\n#define MsvAvTargetName\t\t9\n/** @since Windows 7 */\n#define MsvChannelBindings\t10\n\n/* time_t <-> (guint64) time_val conversion */\n#define TIME_VAL_FACTOR 10000000\n#define TIME_VAL_OFFSET 116444736000000000LL\n#define TIME_T_TO_VAL(time_t)   (((guint64)(time_t)) * TIME_VAL_FACTOR + TIME_VAL_OFFSET)\n#define TIME_VAL_TO_T(time_val) ((time_t)((GUINT64_FROM_LE((time_val)) - TIME_VAL_OFFSET) / TIME_VAL_FACTOR))\n\n/* 8 bytes */\n/* LE (Little Endian) byte order */\nstruct version {\n\tguint8  product_major_version;\n\tguint8  product_minor_version;\n\tguint16 product_build;\n\tguint8  zero2[3];\n\tguint8  ntlm_revision_current;\n};\n\n/*\n * NTLMv1 is no longer used except in tests. R.I.P.\n *\n * It remains in this file only for documentary purposes\n */\n#ifdef _SIPE_COMPILING_TESTS\nstatic gboolean use_ntlm_v2 = FALSE;\n\nguint64 test_time_val = 0;\t\t/* actual time in implementation */\nguchar test_client_challenge [8];\t/* random in implementation */\nguchar test_random_session_key[16];\t/* random in implementation */\nstruct version test_version;\t\t/* hard-coded in implementation */\n#endif\n\n/* Minimum set of common features we need to work. */\n/* we operate in NTLMv2 mode */\n#define NEGOTIATE_FLAGS_COMMON_MIN \\\n\t( NTLMSSP_NEGOTIATE_UNICODE | \\\n\t  NTLMSSP_NEGOTIATE_NTLM | \\\n\t  NTLMSSP_NEGOTIATE_ALWAYS_SIGN | \\\n\t  NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY | \\\n\t  NTLMSSP_NEGOTIATE_TARGET_INFO \\\n\t)\n\n/* Negotiate flags for connection-based mode. Nice to have but optional. */\n#define NEGOTIATE_FLAGS_CONN \\\n\t( NEGOTIATE_FLAGS_COMMON_MIN | \\\n\t  NTLMSSP_NEGOTIATE_VERSION | \\\n\t  NTLMSSP_NEGOTIATE_128 | \\\n\t  NTLMSSP_NEGOTIATE_56 | \\\n\t  NTLMSSP_REQUEST_TARGET \\\n\t)\n\n/* Extra negotiate flags required in connectionless NTLM */\n#define NEGOTIATE_FLAGS_CONNLESS_EXTRA \\\n\t( NTLMSSP_NEGOTIATE_SIGN | \\\n\t  NTLMSSP_NEGOTIATE_DATAGRAM | \\\n\t  NTLMSSP_NEGOTIATE_IDENTIFY | \\\n\t  NTLMSSP_NEGOTIATE_KEY_EXCH \\\n\t)\n\n/* Negotiate flags required in connectionless NTLM */\n#define NEGOTIATE_FLAGS_CONNLESS \\\n\t( NEGOTIATE_FLAGS_CONN | \\\n\t  NEGOTIATE_FLAGS_CONNLESS_EXTRA \\\n\t)\n\n#define NTLMSSP_LN_OR_NT_KEY_LEN  16\n#define NTLMSSP_LM_RESP_LEN 24\n#define NTLMSSP_SESSION_KEY_LEN  16\n\n#define IS_FLAG(flags, flag) (((flags) & (flag)) == (flag))\n\n/* 4 bytes */\n/* LE (Little Endian) byte order */\nstruct av_pair {\n\tguint16 av_id;\n\tguint16 av_len;\n\t/* value */\n};\n\n/* to meet sparc's alignment requirement */\n#define ALIGN_AV                                     \\\n\tmemcpy(&av_aligned, av, sizeof(av_aligned)); \\\n\tav_id  = GUINT16_FROM_LE(av_aligned.av_id);  \\\n\tav_len = GUINT16_FROM_LE(av_aligned.av_len)\n#define ALIGN_AV_LOOP_START                          \\\n\tstruct av_pair av_aligned;                   \\\n\tguint16 av_id;                               \\\n\tguint16 av_len;                              \\\n\tALIGN_AV;\t\t\t\t     \\\n\twhile (av_id != MsvAvEOL) {                  \\\n\t\tgchar *av_value = ((gchar *)av) +    \\\n\t\t\tsizeof(struct av_pair);      \\\n\t\tswitch (av_id)\n#define ALIGN_AV_LOOP_END               \\\n\t\tav = av_value + av_len; \\\n\t\tALIGN_AV;               \\\n\t}\n\n/* 8 bytes */\n/* LE (Little Endian) byte order */\nstruct smb_header {\n\tguint16 len;\n\tguint16 maxlen;\n\tguint32 offset;\n};\n\n/* LE (Little Endian) byte order */\nstruct ntlm_message {\n\tguint8  protocol[8];     /* 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\\0'*/\n\tguint32 type;            /* 0x00000003 */\n};\n\n/* LE (Little Endian) byte order */\nstruct negotiate_message {\n\tguint8  protocol[8];\t\t/* 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\\0' */\n\tguint32 type;\t\t\t/* 0x00000001 */\n\tguint32 flags;\t\t\t/* 0xb203 */\n\tstruct smb_header domain;\n\tstruct smb_header host;\n\tstruct version ver;\n\t/* payload\n\t * - DomainName\t\t(always ASCII)\n\t * - WorkstationName\t(always ASCII)\n\t */\n};\n\n/* LE (Little Endian) byte order */\nstruct challenge_message {\n\tguint8  protocol[8];\t\t/* 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\\0'*/\n\tguint32 type;\t\t\t/* 0x00000002 */\n\tstruct smb_header target_name;\n\tguint32 flags;\t\t\t/* 0x8201 */\n\tguint8  nonce[8];\n\tguint8  zero1[8];\n\tstruct smb_header target_info;\n\tstruct version ver;\n\t/* payload\n\t * - TargetName\t\t\t\t\t\t(negotiated encoding)\n\t * - TargetInfo (a sequence of AV_PAIR structures)\t(always Unicode)\n\t */\n};\n\n/* LE (Little Endian) byte order */\nstruct authenticate_message {\n\tguint8  protocol[8];     /* 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\\0'*/\n\tguint32 type;            /* 0x00000003 */\n\t/** LmChallengeResponseFields */\n\tstruct smb_header lm_resp;\n\t/** NtChallengeResponseFields */\n\tstruct smb_header nt_resp;\n\t/** DomainNameFields */\n\tstruct smb_header domain;\n\t/** UserNameFields */\n\tstruct smb_header user;\n\t/** WorkstationFields */\n\tstruct smb_header host;\n\t/** EncryptedRandomSessionKeyFields */\n\tstruct smb_header session_key;\n\tguint32 flags;\n\tstruct version ver;\n\t//guint8  mic[16];\n\t/* payload\n\t * - LmChallengeResponse\n\t * - NtChallengeResponse\n\t * - DomainName\t\t\t(negotiated encoding)\n\t * - UserName\t\t\t(negotiated encoding)\n\t * - Workstation\t\t(negotiated encoding)\n\t * - EncryptedRandomSessionKey\n\t */\n};\n\n#ifndef HAVE_LANGINFO_CODESET\n#ifdef __sun__\nstatic char SIPE_DEFAULT_CODESET[] = \"US-ASCII\";\n#else\nstatic char SIPE_DEFAULT_CODESET[] = \"ANSI_X3.4-1968\";\n#endif\n#endif\n\n/* Private Methods */\n\n/* Utility Functions */\nstatic GIConv convert_from_utf16le = (GIConv)-1;\nstatic GIConv convert_to_utf16le   = (GIConv)-1;\n\n/* Analyzer only needs the _describe() functions */\n#ifndef _SIPE_COMPILING_ANALYZER\n\nstatic gsize\nunicode_strconvcopy(gchar *dest, const gchar *source, gsize remlen)\n{\n\tgsize inbytes  = strlen(source);\n\tgsize outbytes = remlen;\n\tif (remlen)\n\t\tg_iconv(convert_to_utf16le, (gchar **)&source, &inbytes, &dest, &outbytes);\n\treturn(remlen - outbytes);\n}\n\n#endif /* !_SIPE_COMPILING_ANALYZER */\n\n/* UTF-16LE to native encoding\n * Must be g_free'd after use */\nstatic gchar *\nunicode_strconvcopy_back(const gchar *source, gsize len)\n{\n\tgsize outbytes = 2 * len;\n\tgchar *dest    = g_new0(gchar, outbytes + 1);\n\tgchar *outbuf  = dest;\n\tg_iconv(convert_from_utf16le, (gchar **)&source, &len, &outbuf, &outbytes);\n\treturn dest;\n}\n\n/* Analyzer only needs the _describe() functions */\n#ifndef _SIPE_COMPILING_ANALYZER\n\n/* crc32 source copy from gg's common.c */\nstatic guint32 crc32_table[256];\nstatic int crc32_initialized = 0;\n\nstatic void crc32_make_table()\n{\n\tguint32 h = 1;\n\tunsigned int i, j;\n\n\tmemset(crc32_table, 0, sizeof(crc32_table));\n\n\tfor (i = 128; i; i >>= 1) {\n\t\th = (h >> 1) ^ ((h & 1) ? 0xedb88320L : 0);\n\n\t\tfor (j = 0; j < 256; j += 2 * i)\n\t\t\tcrc32_table[i + j] = crc32_table[j] ^ h;\n\t}\n\n\tcrc32_initialized = 1;\n}\n\nstatic guint32 crc32(guint32 crc, const guint8 *buf, int len)\n{\n\tif (!crc32_initialized)\n\t\tcrc32_make_table();\n\n\tif (!buf || len < 0)\n\t\treturn crc;\n\n\tcrc ^= 0xffffffffL;\n\n\twhile (len--)\n\t\tcrc = (crc >> 8) ^ crc32_table[(crc ^ *buf++) & 0xff];\n\n\treturn crc ^ 0xffffffffL;\n}\n\nstatic guint32\nCRC32 (const char *msg, int len)\n{\n\tguint32 crc = 0L;\n\tcrc = crc32(crc, (guint8 *) msg, len);\n\treturn crc;\n}\n\n/* Cyphers */\n\n#ifdef _SIPE_COMPILING_TESTS\nstatic void setup_des_key(const unsigned char key_56[], unsigned char *key)\n{\n\tkey[0] = key_56[0];\n\tkey[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);\n\tkey[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);\n\tkey[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);\n\tkey[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);\n\tkey[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);\n\tkey[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);\n\tkey[7] =  (key_56[6] << 1) & 0xFF;\n}\n\n/* (k = 7 byte key, d = 8 byte data) returns 8 bytes in results */\nstatic void\nDES (const unsigned char *k, const unsigned char *d, unsigned char * results)\n{\n\tunsigned char key[8];\n\tsetup_des_key(k, key);\n\tsipe_crypt_des(key, d, 8, results);\n}\n\n/* (K = 21 byte key, D = 8 bytes of data) returns 24 bytes in results: */\nstatic void\nDESL (const unsigned char *k, const unsigned char *d, unsigned char * results)\n{\n\tunsigned char keys[21];\n\n\t/* Copy the first 16 bytes */\n\tmemcpy(keys, k, 16);\n\n\t/* Zero out the last 5 bytes of the key */\n\tmemset(keys + 16, 0, 5);\n\n\tDES(keys,      d, results);\n\tDES(keys + 7,  d, results + 8);\n\tDES(keys + 14, d, results + 16);\n}\n#endif\n\n#define RC4K(key, key_len, plain, plain_len, encrypted) \\\n\tsipe_crypt_rc4((key), (key_len), (plain), (plain_len), (encrypted))\n\n/* out 16 bytes */\n#define MD4(d, len, result) sipe_digest_md4((d), (len), (result))\n\n/* out 16 bytes */\n#define MD5(d, len, result) sipe_digest_md5((d), (len), (result))\n\n/* out 16 bytes */\n/*\nstatic void\nHMACT64 (const unsigned char *key, int key_len, const unsigned char *data, int data_len, unsigned char *result)\n{\n\tint i;\n\tunsigned char ibuff[64 + data_len];\n\tunsigned char obuff[64 + 16];\n\n\tif (key_len > 64)\n\t\tkey_len = 64;\n\n        for (i = 0; i < key_len; i++) {\n            ibuff[i] = key[i] ^ 0x36;\n            obuff[i] = key[i] ^ 0x5c;\n        }\n        for (i = key_len; i < 64; i++) {\n            ibuff[i] = 0x36;\n            obuff[i] = 0x5c;\n        }\n\n\tmemcpy(ibuff+64, data, data_len);\n\n\tMD5 (ibuff, 64 + data_len, obuff+64);\n\tMD5 (obuff, 64 + 16, result);\n}\n#define HMAC_MD5 HMACT64\n*/\n\n/* out 16 bytes */\n#define HMAC_MD5(key, key_len, data, data_len, result) \\\n\tsipe_digest_hmac_md5((key), (key_len), (data), (data_len), (result))\n\n/* NTLM Core Methods */\n\nstatic void\nNONCE(unsigned char *buffer, int num)\n{\n\tint i;\n\tfor (i = 0; i < num; i++) {\n\t\tbuffer[i] = (rand() & 0xff);\n\t}\n}\n\n#ifdef _SIPE_COMPILING_TESTS\nstatic void\nZ(unsigned char *buffer, int num)\n{\n\tmemset(buffer, 0, num);\n}\n\nstatic void\nLMOWFv1 (const char *password, SIPE_UNUSED_PARAMETER const char *user, SIPE_UNUSED_PARAMETER const char *domain, unsigned char *result)\n{\n\t/* \"KGS!@#$%\" */\n\tunsigned char magic[] = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };\n\tunsigned char uppercase_password[14];\n\tint i;\n\n\tint len = strlen(password);\n\tif (len > 14) {\n\t\tlen = 14;\n\t}\n\n\t// Uppercase password\n\tfor (i = 0; i < len; i++) {\n\t\tuppercase_password[i] = g_ascii_toupper(password[i]);\n\t}\n\n\t// Zero the rest\n\tfor (; i < 14; i++) {\n\t\tuppercase_password[i] = 0;\n\t}\n\n\tDES (uppercase_password, magic, result);\n\tDES (uppercase_password + 7, magic, result + 8);\n}\n#endif\n\n/*\nDefine NTOWFv1(Passwd, User, UserDom) as\n  MD4(UNICODE(Passwd))\nEndDefine\n*/\n/* out 16 bytes */\nstatic void\nNTOWFv1 (const char* password, SIPE_UNUSED_PARAMETER const char *user, SIPE_UNUSED_PARAMETER const char *domain, unsigned char *result)\n{\n\tint len_u = 2 * strlen(password); // utf16 should not be more\n\tunsigned char *unicode_password = g_malloc(len_u);\n\n\t/* well, if allocation failed the rest will crash & burn soon anyway... */\n\tif (unicode_password) {\n\t\tlen_u = unicode_strconvcopy((gchar *)unicode_password, password, len_u);\n\t\tMD4 (unicode_password, len_u, result);\n\t\tg_free(unicode_password);\n\t}\n}\n\n/*\nDefine NTOWFv2(Passwd, User, UserDom) as\n  HMAC_MD5( MD4(UNICODE(Passwd)), ConcatenationOf( Uppercase(User), UserDom ) )\nEndDefine\n*/\n/* out 16 bytes */\nstatic void\nNTOWFv2 (const char* password, const char *user, const char *domain, unsigned char *result)\n{\n\tunsigned char response_key_nt_v1 [16];\n\tint len_user = user ? strlen(user) : 0;\n\tint len_domain = strlen(domain);\n\tint len_user_u = 2 * len_user; // utf16 should not be more\n\tint len_domain_u = 2 * len_domain; // utf16 should not be more\n\tunsigned char *user_upper = g_malloc(len_user + 1);\n\tunsigned char *buff = g_malloc((len_user + len_domain)*2);\n\tint i;\n\n\t/* Uppercase user */\n\tfor (i = 0; i < len_user; i++) {\n\t\tuser_upper[i] = g_ascii_toupper(user[i]);\n\t}\n\tuser_upper[len_user] = 0;\n\n\tlen_user_u = unicode_strconvcopy((gchar *)buff, (gchar *)user_upper, len_user_u);\n\tlen_domain_u = unicode_strconvcopy((gchar *)(buff+len_user_u), (gchar *)domain, len_domain_u);\n\n\tNTOWFv1(password, user, domain, response_key_nt_v1);\n\n\tHMAC_MD5(response_key_nt_v1, 16, buff, len_user_u + len_domain_u, result);\n\n\tg_free(buff);\n\tg_free(user_upper);\n}\n\nstatic void\ncompute_response(const guint32 neg_flags,\n\t\t const unsigned char *response_key_nt,\n\t\t const unsigned char *response_key_lm,\n\t\t const guint8 *server_challenge,\n\t\t const guint8 *client_challenge,\n\t\t const guint64 time_val,\n\t\t const guint8 *target_info,\n\t\t int target_info_len,\n\t\t unsigned char *lm_challenge_response,\n\t\t unsigned char *nt_challenge_response,\n\t\t unsigned char *session_base_key)\n{\n#ifdef _SIPE_COMPILING_TESTS\n\tif (use_ntlm_v2)\n\t{\n#endif\n/*\nResponserversion - The 1-byte response version. Currently set to 1.\nHiResponserversion - The 1-byte highest response version understood by the client. Currently set to 1.\nTime - The 8-byte little-endian time in GMT.\nServerName - The TargetInfo field structure of the CHALLENGE_MESSAGE payload.\nClientChallenge - The 8-byte challenge message generated by the client.\nCHALLENGE_MESSAGE.ServerChallenge - The 8-byte challenge message generated by the server.\n\nDefine ComputeResponse(NegFlg, ResponseKeyNT, ResponseKeyLM, CHALLENGE_MESSAGE.ServerChallenge, ClientChallenge, Time, ServerName) as\n\tSet temp to ConcatenationOf(Responserversion, HiResponserversion, Z(6),\t\t//8bytes -    0\n\t\t\t\t    Time,\t\t\t\t\t\t//8bytes -    8\n\t\t\t\t    ClientChallenge,\t\t\t\t\t//8bytes -   16\n\t\t\t\t    Z(4),\t\t\t\t\t\t//4bytes -   24\n\t\t\t\t    ServerName,\t\t\t\t\t\t//variable - 28\n\t\t\t\t    Z(4))\t\t\t\t\t\t//4bytes -   28+target_info_len\n\tSet NTProofStr to HMAC_MD5(ResponseKeyNT, ConcatenationOf(CHALLENGE_MESSAGE.ServerChallenge,temp))\n\tSet NtChallengeResponse to ConcatenationOf(NTProofStr, temp)\n\tSet LmChallengeResponse to ConcatenationOf(\n\t\tHMAC_MD5(ResponseKeyLM, ConcatenationOf(CHALLENGE_MESSAGE.ServerChallenge, ClientChallenge)),\n\t\tClientChallenge )\n\tSet SessionBaseKey to HMAC_MD5(ResponseKeyNT, NTProofStr)\nEndDefine\n*/\n\t\tguint8 tmp [16];\n\t\tguint8 nt_proof_str [16];\n\n\t\t/* client_challenge (8) & temp (temp_len) buff */\n\t\tunsigned int temp_len = 8+8+8+4+target_info_len+4;\n\t\tguint64 *temp2 = g_malloc0(8 + temp_len);\n\t\t((guint8 *) temp2)[8+0] = 1;\n\t\t((guint8 *) temp2)[8+1] = 1;\n\t\ttemp2[2] = GUINT64_TO_LE(time_val); /* should be int64 aligned: OK for sparc */\n\t\tmemcpy(((guint8 *) temp2)+8+16, client_challenge, 8);\n\t\tmemcpy(((guint8 *) temp2)+8+28, target_info, target_info_len);\n\n\t\t/* NTProofStr */\n\t\t//Set NTProofStr to HMAC_MD5(ResponseKeyNT, ConcatenationOf(CHALLENGE_MESSAGE.ServerChallenge,temp))\n\t\tmemcpy(temp2, server_challenge, 8);\n\t\tHMAC_MD5(response_key_nt, 16, (guint8*)temp2, 8+temp_len, nt_proof_str);\n\n\t\t/* NtChallengeResponse */\n\t\t//Set NtChallengeResponse to ConcatenationOf(NTProofStr, temp)\n\t\tmemcpy(nt_challenge_response, nt_proof_str, 16);\n\t\tmemcpy(nt_challenge_response+16, temp2+1, temp_len);\n\t\tg_free(temp2);\n\n\t\t/* SessionBaseKey */\n\t\t//SessionBaseKey to HMAC_MD5(ResponseKeyNT, NTProofStr)\n\t\tHMAC_MD5(response_key_nt, 16, nt_proof_str, 16, session_base_key);\n\n\t\t/* lm_challenge_response */\n\t\tmemcpy(tmp, server_challenge, 8);\n\t\tmemcpy(tmp+8, client_challenge, 8);\n\t\tHMAC_MD5(response_key_lm, 16, tmp, 16, lm_challenge_response);\n\t\tmemcpy(lm_challenge_response+16, client_challenge, 8);\n\n#ifndef _SIPE_COMPILING_TESTS\n\t\t/* Not used in NTLMv2 */\n\t\t(void)neg_flags;\n#else\n\t}\n\telse\n\t{\n\t\tif (IS_FLAG(neg_flags, NTLMSSP_NEGOTIATE_LM_KEY)) {\n\t\t\t// @TODO do not even reference nt_challenge_response\n\t\t\tZ (nt_challenge_response, NTLMSSP_LM_RESP_LEN);\n\t\t\tDESL (response_key_lm, server_challenge, lm_challenge_response);\n\t\t} else if (IS_FLAG(neg_flags, NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY)) {\n\t\t\tunsigned char prehash [16];\n\t\t\tunsigned char hash [16];\n\n\t\t\t/* nt_challenge_response */\n\t\t\tmemcpy(prehash, server_challenge, 8);\n\t\t\tmemcpy(prehash + 8, client_challenge, 8);\n\t\t\tMD5 (prehash, 16, hash);\n\t\t\tDESL (response_key_nt, hash, nt_challenge_response);\n\n\t\t\t/* lm_challenge_response */\n\t\t\tmemcpy(lm_challenge_response, client_challenge, 8);\n\t\t\tZ (lm_challenge_response+8, 16);\n\t\t} else {\n\t\t\tDESL (response_key_nt, server_challenge, nt_challenge_response);\n\t\t\tif (IS_FLAG(neg_flags, NTLMSSP_NEGOTIATE_NT_ONLY)) {\n\t\t\t\tmemcpy(lm_challenge_response, nt_challenge_response, NTLMSSP_LM_RESP_LEN);\n\t\t\t} else {\n\t\t\t\tDESL (response_key_lm, server_challenge, lm_challenge_response);\n\t\t\t}\n\t\t}\n\n\t\t/* Session Key */\n\t\tMD4(response_key_nt, 16, session_base_key); // \"User Session Key\" -> \"master key\"\n\t}\n#endif\n}\n\nstatic void\nKXKEY ( guint32 flags,\n\tconst unsigned char * session_base_key,\n\tconst unsigned char * lm_challenge_resonse,\n\tconst guint8 * server_challenge, /* 8-bytes, nonce */\n\tunsigned char * key_exchange_key)\n{\n#ifdef _SIPE_COMPILING_TESTS\n\tif (use_ntlm_v2)\n\t{\n#else\n\t\t/* Not used in NTLMv2 */\n\t\t(void)flags;\n\t\t(void)lm_challenge_resonse;\n\t\t(void)server_challenge;\n#endif\n\t\tmemcpy(key_exchange_key, session_base_key, 16);\n#ifdef _SIPE_COMPILING_TESTS\n\t}\n\telse\n\t{\n\t\tif (IS_FLAG(flags, NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY)) {\n\t\t\t/*  Define KXKEY(SessionBaseKey, LmChallengeResponse, ServerChallenge) as\n\t\t\t        Set KeyExchangeKey to HMAC_MD5(SessionBaseKey, ConcatenationOf(ServerChallenge, LmChallengeResponse [0..7]))\n\t\t\t    EndDefine\n\t\t\t*/\n\t\t\tguint8 tmp[16];\n\t\t\tmemcpy(tmp, server_challenge, 8);\n\t\t\tmemcpy(tmp+8, lm_challenge_resonse, 8);\n\t\t\tHMAC_MD5(session_base_key, 16, tmp, 16, key_exchange_key);\n\t\t} else {\n\t\t\t/* Assume v1 and NTLMSSP_REQUEST_NON_NT_SESSION_KEY not set */\n\t\t\tmemcpy(key_exchange_key, session_base_key, 16);\n\t\t}\n\t}\n#endif\n}\n\n/*\n     If (Mode equals \"Client\")\n          Set SignKey to MD5(ConcatenationOf(RandomSessionKey,\n          \"session key to client-to-server signing key magic constant\"))\n     Else\n          Set SignKey to MD5(ConcatenationOf(RandomSessionKey,\n          \"session key to server-to-client signing key magic constant\"))\n     Endif\n*/\nstatic void\nSIGNKEY (const unsigned char * random_session_key, gboolean client, unsigned char * result)\n{\n\tconst char * magic = client\n\t\t? \"session key to client-to-server signing key magic constant\"\n\t\t: \"session key to server-to-client signing key magic constant\";\n\n\tint len = strlen(magic) + 1;\n\tunsigned char *md5_input = g_malloc(16 + len);\n\tmemcpy(md5_input, random_session_key, 16);\n\tmemcpy(md5_input + 16, magic, len);\n\n\tMD5 (md5_input, len + 16, result);\n\tg_free(md5_input);\n}\n\n/*\nDefine SEALKEY(NegotiateFlags, RandomSessionKey, Mode) as\nIf (NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY flag is set in NegFlg)\n     If ( NTLMSSP_NEGOTIATE_128 is set in NegFlg)\n          Set SealKey to RandomSessionKey\n     ElseIf ( NTLMSSP_NEGOTIATE_56 flag is set in NegFlg)\n         Set SealKey to RandomSessionKey[0..6]\n     Else\n         Set SealKey to RandomSessionKey[0..4]\n     Endif\n\n     If (Mode equals \"Client\")\n         Set SealKey to MD5(ConcatenationOf(SealKey, \"session key to client-to-server sealing key magic constant\"))\n     Else\n         Set SealKey to MD5(ConcatenationOf(SealKey, \"session key to server-to-client sealing key magic constant\"))\n     Endif\n\nElseIf (NTLMSSP_NEGOTIATE_56 flag is set in NegFlg)\n     Set SealKey to ConcatenationOf(RandomSessionKey[0..6], 0xA0)\nElse\n     Set SealKey to ConcatenationOf(RandomSessionKey[0..4], 0xE5, 0x38, 0xB0)\nEndif\nEndDefine\n*/\n/* out 16 bytes or 8 bytes depending if Ext.Sess.Sec is negotiated */\nstatic void\nSEALKEY (guint32 flags, const unsigned char * random_session_key, gboolean client, unsigned char * result)\n{\n\tif (IS_FLAG(flags, NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY))\n\t{\n\t\tconst char * magic = client\n\t\t\t? \"session key to client-to-server sealing key magic constant\"\n\t\t\t: \"session key to server-to-client sealing key magic constant\";\n\n\t\tint len = strlen(magic) + 1;\n\t\tunsigned char *md5_input = g_malloc(16 + len);\n\t\tint key_len;\n\n\t\tif (IS_FLAG(flags, NTLMSSP_NEGOTIATE_128)) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"NTLM SEALKEY(): 128-bit key (Extended session security)\");\n\t\t\tkey_len = 16;\n\t\t} else if (IS_FLAG(flags, NTLMSSP_NEGOTIATE_56)) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"NTLM SEALKEY(): 56-bit key (Extended session security)\");\n\t\t\tkey_len = 7;\n\t\t} else {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"NTLM SEALKEY(): 40-bit key (Extended session security)\");\n\t\t\tkey_len = 5;\n\t\t}\n\n\t\tmemcpy(md5_input, random_session_key, key_len);\n\t\tmemcpy(md5_input + key_len, magic, len);\n\n\t\tMD5 (md5_input, key_len + len, result);\n\t\tg_free(md5_input);\n\t}\n\telse if (IS_FLAG(flags, NTLMSSP_NEGOTIATE_LM_KEY)) /* http://davenport.sourceforge.net/ntlm.html#ntlm1KeyWeakening */\n\t{\n\t\tif (IS_FLAG(flags, NTLMSSP_NEGOTIATE_56)) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"NTLM SEALKEY(): 56-bit key\");\n\t\t\tmemcpy(result, random_session_key, 7);\n\t\t\tresult[7] = 0xA0;\n\t\t} else {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"NTLM SEALKEY(): 40-bit key\");\n\t\t\tmemcpy(result, random_session_key, 5);\n\t\t\tresult[5] = 0xE5;\n\t\t\tresult[6] = 0x38;\n\t\t\tresult[7] = 0xB0;\n\t\t}\n\t}\n\telse\n\t{\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"NTLM SEALKEY(): 128-bit key\");\n\t\tmemcpy(result, random_session_key, 16);\n\t}\n}\n\n/*\n= for Extended Session Security =\nVersion  (4 bytes): A 32-bit unsigned integer that contains the signature version. This field MUST be 0x00000001.\nChecksum (8 bytes): An 8-byte array that contains the checksum for the message.\nSeqNum   (4 bytes): A 32-bit unsigned integer that contains the NTLM sequence number for this application message.\n\n= if Extended Session Security is NOT negotiated =\nVersion   (4 bytes): A 32-bit unsigned integer that contains the signature version. This field MUST be 0x00000001.\nRandomPad (4 bytes): A 4-byte array that contains the random pad for the message.\nChecksum  (4 bytes):  A 4-byte array that contains the checksum for the message.\nSeqNum    (4 bytes): A 32-bit unsigned integer that contains the NTLM sequence number for this application message.\n---\n0x00000001, RC4K(RandomPad), RC4K(CRC32(Message)), RC4K(0x00000000) XOR (application supplied SeqNum)\t\t-- RC4(X) xor X xor Y = RC4(Y)\n\nVersion(4), Checksum(8),  SeqNum(4)\t\t\t-- for ext.sess.sec.\nVersion(4), RandomPad(4), Checksum(4), SeqNum(4)\n*/\n/** MAC(Handle, SigningKey, SeqNum, Message) */\n/* out 16 bytes */\nstatic void\nMAC (guint32 flags,\n     const char *buf,\n     unsigned int buf_len,\n     unsigned char *sign_key,\n     unsigned long sign_key_len,\n     unsigned char *seal_key,\n     unsigned long seal_key_len,\n     guint32 random_pad,\n     guint32 sequence,\n     guint32 *result)\n{\n\tguint32 *res_ptr;\n\n\tif (IS_FLAG(flags, NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY)) {\n\t\t/*\n\t\tDefine MAC(Handle, SigningKey, SeqNum, Message) as\n\t\t\tSet NTLMSSP_MESSAGE_SIGNATURE.Version to 0x00000001\n\t\t\tSet NTLMSSP_MESSAGE_SIGNATURE.Checksum to\n\t\t\t\tHMAC_MD5(SigningKey, ConcatenationOf(SeqNum, Message))[0..7]\n\t\t\tSet NTLMSSP_MESSAGE_SIGNATURE.SeqNum to SeqNum\n\t\t\tSet SeqNum to SeqNum + 1\n\t\tEndDefine\n\t\t*/\n\t\t/* If a key exchange key is negotiated\n\t\t   Define MAC(Handle, SigningKey, SeqNum, Message) as\n\t\t\tSet NTLMSSP_MESSAGE_SIGNATURE.Version to 0x00000001\n\t\t\tSet NTLMSSP_MESSAGE_SIGNATURE.Checksum to RC4(Handle,\n\t\t\t\tHMAC_MD5(SigningKey, ConcatenationOf(SeqNum, Message))[0..7])\n\t\t\tSet NTLMSSP_MESSAGE_SIGNATURE.SeqNum to SeqNum\n\t\t\tSet SeqNum to SeqNum + 1\n\t\t   EndDefine\n\t\t*/\n\n\t\tunsigned char seal_key_ [16];\n\t\tguchar hmac[16];\n\t\tguint32 *tmp = g_malloc(4 + buf_len);\n\n\t\t/* SealingKey' = MD5(ConcatenationOf(SealingKey, SequenceNumber))\n\t\t   RC4Init(Handle, SealingKey')\n\t\t */\n\t\tif (IS_FLAG(flags, NTLMSSP_NEGOTIATE_DATAGRAM)) {\n\t\t\tguint32 tmp2[4+1];\n\n\t\t\tmemcpy(tmp2, seal_key, seal_key_len);\n\t\t\ttmp2[4] = GUINT32_TO_LE(sequence);\n\t\t\tMD5 ((guchar *)tmp2, sizeof(tmp2), seal_key_);\n\t\t} else {\n\t\t\tmemcpy(seal_key_, seal_key, seal_key_len);\n\t\t}\n\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"NTLM MAC(): Extended Session Security\");\n\n\t\tres_ptr = result;\n\t\tres_ptr[0] = GUINT32_TO_LE(1); // 4 bytes\n\t\tres_ptr[3] = GUINT32_TO_LE(sequence);\n\n\t\tres_ptr = tmp;\n\t\tres_ptr[0] = GUINT32_TO_LE(sequence);\n\t\tmemcpy(tmp+1, buf, buf_len);\n\n\t\tHMAC_MD5(sign_key, sign_key_len, (guchar *)tmp, 4 + buf_len, hmac);\n\t\tg_free(tmp);\n\n\t\tif (IS_FLAG(flags, NTLMSSP_NEGOTIATE_KEY_EXCH)) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"NTLM MAC(): Key Exchange\");\n\t\t\tRC4K(seal_key_, seal_key_len, hmac, 8, (guchar *)(result+1));\n\t\t} else {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"NTLM MAC(): *NO* Key Exchange\");\n\t\t\tmemcpy(result+1, hmac, 8);\n\t\t}\n\t} else {\n\t\t/* The content of the first 4 bytes is irrelevant */\n\t\tguint32 crc = CRC32(buf, strlen(buf));\n\t\tguint32 plaintext [] = {\n\t\t\tGUINT32_TO_LE(0),\n\t\t\tGUINT32_TO_LE(crc),\n\t\t\tGUINT32_TO_LE(sequence)\n\t\t}; // 4, 4, 4 bytes\n\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"NTLM MAC(): *NO* Extended Session Security\");\n\n\t\tRC4K(seal_key, seal_key_len, (const guchar *)plaintext, 12, (guchar *)(result+1));\n\n\t\tres_ptr = result;\n\t\t// Highest four bytes are the Version\n\t\tres_ptr[0] = GUINT32_TO_LE(0x00000001); // 4 bytes\n\n\t\t// Replace the first four bytes of the ciphertext with the random_pad\n\t\tres_ptr[1] = GUINT32_TO_LE(random_pad); // 4 bytes\n\t}\n}\n\n/* End Core NTLM Methods */\n\n/**\n  * @param flags (out)\t\tflags received from server\n  * @param server_challenge\tmust be g_free()'d after use if requested\n  * @param target_info\t\tmust be g_free()'d after use if requested\n  */\nstatic void\nsip_sec_ntlm_parse_challenge(SipSecBuffer in_buff,\n\t\t\t     guint32 *flags,\n\t\t\t     guchar **server_challenge, /* 8 bytes */\n\t\t\t     guint64 *time_val,\n\t\t\t     guchar **target_info,\n\t\t\t     int *target_info_len)\n{\n\t/* SipSecBuffer.value is g_malloc()'d: use (void *) to remove guint8 alignment */\n\tstruct challenge_message *cmsg = (void *)in_buff.value;\n\tguint32 host_flags = GUINT32_FROM_LE(cmsg->flags);\n\n\t/* server challenge (nonce) */\n\tif (server_challenge) {\n\t\t*server_challenge = g_memdup(cmsg->nonce, 8);\n\t}\n\n\t/* flags */\n\tif (flags) {\n\t\t*flags = host_flags;\n\t}\n\n\t/* target_info */\n\tif (cmsg->target_info.len && cmsg->target_info.offset) {\n\t\tvoid *content = (gchar *)cmsg + GUINT32_FROM_LE(cmsg->target_info.offset);\n\t\tvoid *av      = content;\n\t\tguint16 len   = GUINT16_FROM_LE(cmsg->target_info.len);\n\n\t\tALIGN_AV_LOOP_START\n\t\t{\n\t\t\t/* @since Vista */\n\t\tcase MsvAvTimestamp:\n\t\t\tif (time_val) {\n\t\t\t\tguint64 tmp;\n\n\t\t\t\t/* to meet sparc's alignment requirement */\n\t\t\t\tmemcpy(&tmp, av_value, sizeof(tmp));\n\t\t\t\t*time_val = GUINT64_FROM_LE(tmp);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tALIGN_AV_LOOP_END;\n\n\t\tif (target_info_len) {\n\t\t\t*target_info_len = len;\n\t\t}\n\t\tif (target_info) {\n\t\t\t*target_info = g_memdup(content, len);\n\t\t}\n\t}\n}\n\n/**\n * @param client_sign_key (out)\t\tmust be g_free()'d after use\n * @param server_sign_key (out) \tmust be g_free()'d after use\n * @param client_seal_key (out) \tmust be g_free()'d after use\n * @param server_seal_key (out) \tmust be g_free()'d after use\n * @param flags (in, out)\t\tnegotiated flags\n */\nstatic gboolean\nsip_sec_ntlm_gen_authenticate(guchar **client_sign_key,\n\t\t\t      guchar **server_sign_key,\n\t\t\t      guchar **client_seal_key,\n\t\t\t      guchar **server_seal_key,\n\t\t\t      const gchar *user,\n\t\t\t      const gchar *password,\n\t\t\t      const gchar *hostname,\n\t\t\t      const gchar *domain,\n\t\t\t      const guint8 *server_challenge, /* nonce */\n\t\t\t      const guint64 time_val,\n\t\t\t      const guint8 *target_info,\n\t\t\t      int target_info_len,\n\t\t\t      gboolean http,\n\t\t\t      SipSecBuffer *out_buff,\n\t\t\t      guint32 *flags)\n{\n\tguint32 orig_flags = http ? NEGOTIATE_FLAGS_CONN : NEGOTIATE_FLAGS_CONNLESS;\n\tguint32 neg_flags = (*flags & orig_flags) | NTLMSSP_REQUEST_TARGET;\n\tint ntlmssp_nt_resp_len =\n#ifdef _SIPE_COMPILING_TESTS\n\t\tuse_ntlm_v2 ?\n#endif\n\t\t(16 + (32+target_info_len))\n#ifdef _SIPE_COMPILING_TESTS\n\t\t: NTLMSSP_LM_RESP_LEN\n#endif\n\t\t;\n\tgsize msglen = sizeof(struct authenticate_message)\n\t\t+ 2*(strlen(domain) + strlen(user)+ strlen(hostname))\n\t\t+ NTLMSSP_LM_RESP_LEN + ntlmssp_nt_resp_len\n\t\t+ (IS_FLAG(neg_flags, NTLMSSP_NEGOTIATE_KEY_EXCH) ? NTLMSSP_SESSION_KEY_LEN : 0);\n\tstruct authenticate_message *tmsg;\n\tchar *tmp;\n\tguint32 offset;\n\tguint16 len;\n\tunsigned char response_key_lm [NTLMSSP_LN_OR_NT_KEY_LEN]; /* 16 */\n\tunsigned char response_key_nt [NTLMSSP_LN_OR_NT_KEY_LEN]; /* 16 */\n\tunsigned char lm_challenge_response [NTLMSSP_LM_RESP_LEN]; /* 24 */\n\tunsigned char *nt_challenge_response = g_malloc(ntlmssp_nt_resp_len);  /* variable or 24 */\n\tunsigned char session_base_key [16];\n\tunsigned char key_exchange_key [16];\n\tunsigned char exported_session_key[16];\n\tunsigned char encrypted_random_session_key [16];\n\tunsigned char key [16];\n\tunsigned char client_challenge [8];\n\tguint64 time_vl = time_val ? time_val : TIME_T_TO_VAL(time(NULL));\n\n\tif (!IS_FLAG(*flags, NEGOTIATE_FLAGS_COMMON_MIN) ||\n\t    !(http || IS_FLAG(*flags, NEGOTIATE_FLAGS_CONNLESS_EXTRA)) ||\n\t    !nt_challenge_response) /* Coverity thinks ntlmssp_nt_resp_len could be 0 */\n\t{\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_sec_ntlm_gen_authenticate: received incompatible NTLM NegotiateFlags, exiting.\");\n\t\tg_free(nt_challenge_response);\n\t\treturn FALSE;\n\t}\n\n\tif (IS_FLAG(neg_flags, NTLMSSP_NEGOTIATE_128)) {\n\t\tneg_flags = neg_flags & ~NTLMSSP_NEGOTIATE_56;\n\t}\n\n\ttmsg = g_malloc0(msglen);\n\n\tNONCE (client_challenge, 8);\n\n#ifdef _SIPE_COMPILING_TESTS\n\tmemcpy(client_challenge, test_client_challenge, 8);\n\ttime_vl = test_time_val ? test_time_val : time_vl;\n\n\tif (use_ntlm_v2) {\n\n#endif\n\t\tNTOWFv2 (password, user, domain, response_key_nt);\n\t\tmemcpy(response_key_lm, response_key_nt, NTLMSSP_LN_OR_NT_KEY_LEN);\n#ifdef _SIPE_COMPILING_TESTS\n\t} else {\n\t\tNTOWFv1 (password, user, domain, response_key_nt);\n\t\tLMOWFv1 (password, user, domain, response_key_lm);\n\t}\n#endif\n\n\tcompute_response(neg_flags,\n\t\t\t response_key_nt,\n\t\t\t response_key_lm,\n\t\t\t server_challenge,\n\t\t\t client_challenge,\n\t\t\t time_vl,\n\t\t\t target_info,\n\t\t\t target_info_len,\n\t\t\t lm_challenge_response,\t/* out */\n\t\t\t nt_challenge_response,\t/* out */\n\t\t\t session_base_key);\t/* out */\n\n\t/* same as session_base_key for\n\t * - NTLNv1 w/o Ext.Sess.Sec and\n\t * - NTLMv2\n\t */\n\tKXKEY(neg_flags, session_base_key, lm_challenge_response, server_challenge, key_exchange_key);\n\n\tif (IS_FLAG(neg_flags, NTLMSSP_NEGOTIATE_KEY_EXCH)) {\n\t\tNONCE (exported_session_key, 16); // random master key\n#ifdef _SIPE_COMPILING_TESTS\n\t\tmemcpy(exported_session_key, test_random_session_key, 16);\n#endif\n\t\tRC4K (key_exchange_key, 16, exported_session_key, 16, encrypted_random_session_key);\n\t} else {\n\t\tmemcpy(exported_session_key, key_exchange_key, 16);\n\t}\n\n\ttmp = buff_to_hex_str(exported_session_key, 16);\n\tSIPE_DEBUG_INFO(\"NTLM AUTHENTICATE: exported session key (not encrypted): %s\", tmp);\n\tg_free(tmp);\n\n\tif (IS_FLAG(neg_flags, NTLMSSP_NEGOTIATE_SIGN) ||\n\t    IS_FLAG(neg_flags, NTLMSSP_NEGOTIATE_SEAL))\n\t{\n\t\t/* p.46\n\t\t   Set ClientSigningKey to SIGNKEY(ExportedSessionKey, \"Client\")\n\t\t   Set ServerSigningKey to SIGNKEY(ExportedSessionKey, \"Server\")\n\t\t*/\n\t\tSIGNKEY(exported_session_key, TRUE, key);\n\t\t*client_sign_key = g_memdup(key, 16);\n\t\tSIGNKEY(exported_session_key, FALSE, key);\n\t\t*server_sign_key = g_memdup(key, 16);\n\t\tSEALKEY(neg_flags, exported_session_key, TRUE, key);\n\t\t*client_seal_key = g_memdup(key, 16);\n\t\tSEALKEY(neg_flags, exported_session_key, FALSE, key);\n\t\t*server_seal_key = g_memdup(key, 16);\n\t}\n\n\t/* @TODO: */\n\t/* @since Vista\n\tIf the CHALLENGE_MESSAGE TargetInfo field (section 2.2.1.2) has an MsvAvTimestamp present,\n\tthe client SHOULD provide a MIC:\n\t- If there is an AV_PAIR structure (section 2.2.2.1) with the AvId field set to MsvAvFlags,\n\t\t- then in the Value field, set bit 0x2 to 1.\n\t\t- else add an AV_PAIR structure (section 2.2.2.1) and set the AvId field to MsvAvFlags\n\t\tand the Value field bit 0x2 to 1.\n\t- Populate the MIC field with the MIC.\n\t*/\n\n\t/* Connection-oriented:\n\tSet MIC to HMAC_MD5(ExportedSessionKey,\n\t\tConcatenationOf( NEGOTIATE_MESSAGE, CHALLENGE_MESSAGE, AUTHENTICATE_MESSAGE_MIC0));\n\t   Connectionless:\n\tSet MIC to HMAC_MD5(ExportedSessionKey,\n\t\tConcatenationOf( CHALLENGE_MESSAGE, AUTHENTICATE_MESSAGE))\n\t*/\n\n\t/* on the server-side:\n\tIf (NTLMSSP_NEGOTIATE_KEY_EXCH flag is set in NegFlg )\n\t\tSet ExportedSessionKey to RC4K(KeyExchangeKey, AUTHENTICATE_MESSAGE.EncryptedRandomSessionKey)\n\t\tSet MIC to HMAC_MD5(ExportedSessionKey,\n\t\t\tConcatenationOf( NEGOTIATE_MESSAGE, CHALLENGE_MESSAGE, AUTHENTICATE_MESSAGE_MIC0))\n\tElse\n\t\tSet ExportedSessionKey to KeyExchangeKey\n\t\tSet MIC to HMAC_MD5(KeyExchangeKey,\n\t\t\tConcatenationOf( NEGOTIATE_MESSAGE, CHALLENGE_MESSAGE, AUTHENTICATE_MESSAGE_MIC0)) EndIf\n\t=====\n\t@since Vista\n\tIf the AUTHENTICATE_MESSAGE indicates the presence of a MIC field,\n\tthen the MIC value computed earlier MUST be compared to the MIC field in the message,\n\tand if the two MIC values are not equal, then an authentication failure MUST be returned.\n\tAn AUTHENTICATE_MESSAGE indicates the presence of a MIC field if the TargetInfo field has\n\tan AV_PAIR structure whose two fields:\n\t\t- AvId == MsvAvFlags\n\t\t- Value bit 0x2 == 1\n\t@supported NT, 2000, XP\n\tIf NTLM v2 authentication is used and the AUTHENTICATE_MESSAGE.NtChallengeResponse.\n\tTimeStamp (section 2.2.2.7) is more than MaxLifetime (section 3.1.1.1) difference from\n\tthe server time, then the server SHOULD return a failure.\n\t===\n\tConnectionless:\n\tSet MIC to HMAC_MD5(ResponseKeyNT,\n\t\tConcatenationOf( CHALLENGE_MESSAGE, AUTHENTICATE_MESSAGE_MIC0))\n\t*/\n\n\t/* authenticate message initialization */\n\tmemcpy(tmsg->protocol, \"NTLMSSP\\0\", 8);\n\ttmsg->type = GUINT32_TO_LE(3);\n\n\t/* Initial offset */\n\toffset = sizeof(struct authenticate_message);\n\ttmp = ((char*) tmsg) + offset;\n\n#define _FILL_SMB_HEADER(header)\t\t\t\t     \\\n\ttmsg->header.offset = GUINT32_TO_LE(offset);\t\t     \\\n\ttmsg->header.len = tmsg->header.maxlen = GUINT16_TO_LE(len); \\\n\ttmp += len;\t\t\t\t\t\t     \\\n\toffset += len\n#define _APPEND_STRING(header, src)\t\t\t\t\\\n\tlen = unicode_strconvcopy(tmp, (src), msglen - offset); \\\n\t_FILL_SMB_HEADER(header)\n#define _APPEND_DATA(header, src, srclen) \\\n\tlen = (srclen);\t\t\t  \\\n\tmemcpy(tmp, (src), len);\t  \\\n\t_FILL_SMB_HEADER(header)\n\n\t/* Domain */\n\t_APPEND_STRING(domain, domain);\n\n\t/* User */\n\t_APPEND_STRING(user, user);\n\n\t/* Host */\n\t_APPEND_STRING(host, hostname);\n\n\t/* LM */\n\t/* @since Windows 7\n\t   If NTLM v2 authentication is used and the CHALLENGE_MESSAGE contains a TargetInfo field,\n\t   the client SHOULD NOT send the LmChallengeResponse and SHOULD set the LmChallengeResponseLen\n\t   and LmChallengeResponseMaxLen fields in the AUTHENTICATE_MESSAGE to zero.\n\t*/\n\t_APPEND_DATA(lm_resp, lm_challenge_response, NTLMSSP_LM_RESP_LEN);\n\n\t/* NT */\n\t_APPEND_DATA(nt_resp, nt_challenge_response, ntlmssp_nt_resp_len);\n\n\t/* Session Key */\n\tif (IS_FLAG(neg_flags, NTLMSSP_NEGOTIATE_KEY_EXCH))\n\t{\n\t\t_APPEND_DATA(session_key, encrypted_random_session_key, NTLMSSP_SESSION_KEY_LEN);\n\t}\n\telse\n\t{\n\t\ttmsg->session_key.offset = GUINT32_TO_LE(offset);\n\t\ttmsg->session_key.len = tmsg->session_key.maxlen = 0;\n\t}\n\n\t/* Version */\n#ifdef _SIPE_COMPILING_TESTS\n\tmemcpy(&(tmsg->ver), &test_version, sizeof(struct version));\n#else\n\tif (IS_FLAG(neg_flags, NTLMSSP_NEGOTIATE_VERSION)) {\n\t\ttmsg->ver.product_major_version = 5;\t\t/* 5.1.2600 (Windows XP SP2) */\n\t\ttmsg->ver.product_minor_version = 1;\n\t\ttmsg->ver.product_build = GUINT16_FROM_LE(2600);\n\t\ttmsg->ver.ntlm_revision_current = 0x0F;\t\t/* NTLMSSP_REVISION_W2K3 */\n\t}\n#endif\n\n\t/* Set Negotiate Flags */\n\ttmsg->flags = GUINT32_TO_LE(neg_flags);\n\t*flags = neg_flags;\n\n\tout_buff->value = (guint8 *)tmsg;\n\tout_buff->length = msglen;\n\n\tg_free(nt_challenge_response);\n\n\treturn TRUE;\n}\n\n/**\n * Generates Type 1 (Negotiate) message for connection-oriented cases (only)\n */\nstatic void\nsip_sec_ntlm_gen_negotiate(SipSecBuffer *out_buff)\n{\n\tguint32 offset;\n\tguint16 len;\n\tint msglen = sizeof(struct negotiate_message);\n\tstruct negotiate_message *tmsg = g_malloc0(msglen);\n\n\t/* negotiate message initialization */\n\tmemcpy(tmsg->protocol, \"NTLMSSP\\0\", 8);\n\ttmsg->type = GUINT32_TO_LE(1);\n\n\t/* Set Negotiate Flags */\n\ttmsg->flags = GUINT32_TO_LE(NEGOTIATE_FLAGS_CONN);\n\n\t/* Domain */\n\toffset = sizeof(struct negotiate_message);\n\ttmsg->domain.offset = GUINT32_TO_LE(offset);\n\ttmsg->domain.len = tmsg->domain.maxlen = len = 0;\n\n\t/* Host */\n\toffset += len;\n\ttmsg->host.offset = GUINT32_TO_LE(offset);\n\ttmsg->host.len = tmsg->host.maxlen = len = 0;\n\n\t/* Version */\n\ttmsg->ver.product_major_version = 5;\t\t/* 5.1.2600 (Windows XP SP2) */\n\ttmsg->ver.product_minor_version = 1;\n\ttmsg->ver.product_build = GUINT16_FROM_LE(2600);\n\ttmsg->ver.ntlm_revision_current = 0x0F;\t\t/* NTLMSSP_REVISION_W2K3 */\n\n\tout_buff->value = (guint8 *)tmsg;\n\tout_buff->length = msglen;\n}\n\nstatic void\nsip_sec_ntlm_sipe_signature_make(guint32 flags,\n\t\t\t\t const char *msg,\n\t\t\t\t guint32 random_pad,\n\t\t\t\t unsigned char *sign_key,\n\t\t\t\t unsigned char *seal_key,\n\t\t\t\t guint32 *result)\n{\n\tchar *res;\n\n\tMAC(flags, msg, strlen(msg), sign_key, 16, seal_key, 16, random_pad, 100, result);\n\n\tres = buff_to_hex_str((guint8 *)result, 16);\n\tSIPE_DEBUG_INFO(\"NTLM calculated MAC: %s\", res);\n\tg_free(res);\n}\n\n#endif /* !_SIPE_COMPILING_ANALYZER */\n\n/* Describe NTLM messages functions */\n\n#define APPEND_NEG_FLAG(str, flags, flag, desc)\t\\\n\tif ((flags & flag) == flag) g_string_append_printf(str, \"\\t%s\\n\", desc);\n\nstatic gchar *\nsip_sec_ntlm_negotiate_flags_describe(guint32 flags)\n{\n\tGString* str = g_string_new(NULL);\n\n\tflags = GUINT32_FROM_LE(flags);\n\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_NEGOTIATE_UNICODE, \"NTLMSSP_NEGOTIATE_UNICODE\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_NEGOTIATE_OEM, \"NTLMSSP_NEGOTIATE_OEM\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_REQUEST_TARGET, \"NTLMSSP_REQUEST_TARGET\");\n\tAPPEND_NEG_FLAG(str, flags, r9, \"r9\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_NEGOTIATE_SIGN, \"NTLMSSP_NEGOTIATE_SIGN\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_NEGOTIATE_SEAL, \"NTLMSSP_NEGOTIATE_SEAL\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_NEGOTIATE_DATAGRAM, \"NTLMSSP_NEGOTIATE_DATAGRAM\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_NEGOTIATE_LM_KEY, \"NTLMSSP_NEGOTIATE_LM_KEY\");\n\tAPPEND_NEG_FLAG(str, flags, r8, \"r8\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_NEGOTIATE_NTLM, \"NTLMSSP_NEGOTIATE_NTLM\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_NEGOTIATE_NT_ONLY, \"NTLMSSP_NEGOTIATE_NT_ONLY\");\n\tAPPEND_NEG_FLAG(str, flags, anonymous, \"anonymous\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED, \"NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED, \"NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED\");\n\tAPPEND_NEG_FLAG(str, flags, r7, \"r7\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_NEGOTIATE_ALWAYS_SIGN, \"NTLMSSP_NEGOTIATE_ALWAYS_SIGN\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_TARGET_TYPE_DOMAIN, \"NTLMSSP_TARGET_TYPE_DOMAIN\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_TARGET_TYPE_SERVER, \"NTLMSSP_TARGET_TYPE_SERVER\");\n\tAPPEND_NEG_FLAG(str, flags, r6, \"r6\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY, \"NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_NEGOTIATE_IDENTIFY, \"NTLMSSP_NEGOTIATE_IDENTIFY\");\n\tAPPEND_NEG_FLAG(str, flags, r5, \"r5\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_REQUEST_NON_NT_SESSION_KEY, \"NTLMSSP_REQUEST_NON_NT_SESSION_KEY\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_NEGOTIATE_TARGET_INFO, \"NTLMSSP_NEGOTIATE_TARGET_INFO\");\n\tAPPEND_NEG_FLAG(str, flags, r4, \"r4\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_NEGOTIATE_VERSION, \"NTLMSSP_NEGOTIATE_VERSION\");\n\tAPPEND_NEG_FLAG(str, flags, r3, \"r3\");\n\tAPPEND_NEG_FLAG(str, flags, r2, \"r2\");\n\tAPPEND_NEG_FLAG(str, flags, r1, \"r1\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_NEGOTIATE_128, \"NTLMSSP_NEGOTIATE_128\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_NEGOTIATE_KEY_EXCH, \"NTLMSSP_NEGOTIATE_KEY_EXCH\");\n\tAPPEND_NEG_FLAG(str, flags, NTLMSSP_NEGOTIATE_56, \"NTLMSSP_NEGOTIATE_56\");\n\n\treturn g_string_free(str, FALSE);\n}\n\nstatic gchar *\nsip_sec_ntlm_describe_version(struct version *ver) {\n\tGString* str = g_string_new(NULL);\n\tconst gchar *ver_desc = \"\";\n\tconst gchar *ntlm_revision_desc = \"\";\n\n\tif (ver->product_major_version == 6) {\n\t\tver_desc = \"Windows Vista, Windows Server 2008, Windows 7 or Windows Server 2008 R2\";\n\t} else if (ver->product_major_version == 5 && ver->product_minor_version == 2) {\n\t\tver_desc = \"Windows Server 2003\";\n\t} else if (ver->product_major_version == 5 && ver->product_minor_version == 1) {\n\t\tver_desc = \"Windows XP SP2\";\n\t}\n\n\tif (ver->ntlm_revision_current == 0x0F) {\n\t\tntlm_revision_desc = \"NTLMSSP_REVISION_W2K3\";\n\t} else if (ver->ntlm_revision_current == 0x0A) {\n\t\tntlm_revision_desc = \"NTLMSSP_REVISION_W2K3_RC1\";\n\t}\n\n\tg_string_append_printf(str, \"\\tproduct: %d.%d.%d (%s)\\n\",\n\t\tver->product_major_version, ver->product_minor_version, ver->product_build, ver_desc);\n\tg_string_append_printf(str, \"\\tntlm_revision_current: 0x%02X (%s)\\n\", ver->ntlm_revision_current, ntlm_revision_desc);\n\n\treturn g_string_free(str, FALSE);\n}\n\nstatic gchar *\nsip_sec_ntlm_describe_smb_header(struct smb_header *header,\n\t\t\t\t const char* name)\n{\n\tGString* str = g_string_new(NULL);\n\n\tg_string_append_printf(str, \"\\t%s.len   : %d\\n\", name, GUINT16_FROM_LE(header->len));\n\tg_string_append_printf(str, \"\\t%s.maxlen: %d\\n\", name, GUINT16_FROM_LE(header->maxlen));\n\tg_string_append_printf(str, \"\\t%s.offset: %d\\n\", name, GUINT32_FROM_LE(header->offset));\n\n\treturn g_string_free(str, FALSE);\n}\n\nstatic gchar *\nsip_sec_ntlm_negotiate_message_describe(struct negotiate_message *cmsg)\n{\n\tGString* str = g_string_new(NULL);\n\tchar *tmp;\n\n\tg_string_append(str, (tmp = sip_sec_ntlm_negotiate_flags_describe(cmsg->flags)));\n\tg_free(tmp);\n\n\tg_string_append(str, (tmp = sip_sec_ntlm_describe_smb_header(&(cmsg->domain), \"domain\")));\n\tg_free(tmp);\n\n\tg_string_append(str, (tmp = sip_sec_ntlm_describe_smb_header(&(cmsg->host), \"host\")));\n\tg_free(tmp);\n\n\ttmp = sip_sec_ntlm_describe_version(&(cmsg->ver));\n\tg_string_append(str, tmp);\n\tg_free(tmp);\n\n\tif (cmsg->domain.len && cmsg->domain.offset) {\n\t\tgchar *domain = g_strndup(((gchar *)cmsg + GUINT32_FROM_LE(cmsg->domain.offset)), GUINT16_FROM_LE(cmsg->domain.len));\n\t\tg_string_append_printf(str, \"\\tdomain: %s\\n\", domain);\n\t\tg_free(domain);\n\t}\n\n\tif (cmsg->host.len && cmsg->host.offset) {\n\t\tgchar *host = g_strndup(((gchar *)cmsg + GUINT32_FROM_LE(cmsg->host.offset)), GUINT16_FROM_LE(cmsg->host.len));\n\t\tg_string_append_printf(str, \"\\thost: %s\\n\", host);\n\t\tg_free(host);\n\t}\n\n\treturn g_string_free(str, FALSE);\n}\n\nstatic void\ndescribe_av_pairs(GString* str, const void *av)\n{\n#define AV_DESC(av_name) \\\n\t{ \\\n\t\tgchar *tmp = unicode_strconvcopy_back(av_value, av_len); \\\n\t\tg_string_append_printf(str, \"\\t%s: %s\\n\", av_name, tmp); \\\n\t\tg_free(tmp); \\\n\t}\n\n\tALIGN_AV_LOOP_START\n\t{\n\tcase MsvAvNbComputerName:\n\t\tAV_DESC(\"MsvAvNbComputerName\");\n\t\tbreak;\n\tcase MsvAvNbDomainName:\n\t\tAV_DESC(\"MsvAvNbDomainName\");\n\t\tbreak;\n\tcase MsvAvDnsComputerName:\n\t\tAV_DESC(\"MsvAvDnsComputerName\");\n\t\tbreak;\n\tcase MsvAvDnsDomainName:\n\t\tAV_DESC(\"MsvAvDnsDomainName\");\n\t\tbreak;\n\tcase MsvAvDnsTreeName:\n\t\tAV_DESC(\"MsvAvDnsTreeName\");\n\t\tbreak;\n\tcase MsvAvFlags:\n\t\t{\n\t\t\tguint32 flags;\n\n\t\t\t/* to meet sparc's alignment requirement */\n\t\t\tmemcpy(&flags, av_value, sizeof(guint32));\n\t\t\tg_string_append_printf(str, \"\\t%s: %d\\n\", \"MsvAvFlags\", GUINT32_FROM_LE(flags));\n\t\t}\n\t\tbreak;\n\tcase MsvAvTimestamp:\n\t\t{\n\t\t\tchar *tmp;\n\t\t\tguint64 time_val;\n\t\t\ttime_t time_t_val;\n\n\t\t\t/* to meet sparc's alignment requirement */\n\t\t\tmemcpy(&time_val, av_value, sizeof(time_val));\n\t\t\ttime_t_val = TIME_VAL_TO_T(time_val);\n\n\t\t\tg_string_append_printf(str, \"\\t%s: %s - %s\", \"MsvAvTimestamp\", (tmp = buff_to_hex_str((guint8 *) av_value, 8)),\n\t\t\t\t\t       asctime(gmtime(&time_t_val)));\n\t\t\tg_free(tmp);\n\t\t}\n\t\tbreak;\n\tcase MsAvRestrictions:\n\t\tg_string_append_printf(str, \"\\t%s\\n\", \"MsAvRestrictions\");\n\t\tbreak;\n\tcase MsvAvTargetName:\n\t\tAV_DESC(\"MsvAvTargetName\");\n\t\tbreak;\n\tcase MsvChannelBindings:\n\t\tg_string_append_printf(str, \"\\t%s\\n\", \"MsvChannelBindings\");\n\t\tbreak;\n\t}\n\tALIGN_AV_LOOP_END;\n}\n\nstatic gchar *\nsip_sec_ntlm_authenticate_message_describe(struct authenticate_message *cmsg)\n{\n\tGString* str = g_string_new(NULL);\n\tchar *tmp;\n\tgsize value_len;\n\tguint8 *value;\n\n\tg_string_append(str, (tmp = sip_sec_ntlm_negotiate_flags_describe(cmsg->flags)));\n\tg_free(tmp);\n\n\tg_string_append(str, (tmp = sip_sec_ntlm_describe_smb_header(&(cmsg->lm_resp), \"lm_resp\")));\n\tg_free(tmp);\n\n\tg_string_append(str, (tmp = sip_sec_ntlm_describe_smb_header(&(cmsg->nt_resp), \"nt_resp\")));\n\tg_free(tmp);\n\n\tg_string_append(str, (tmp = sip_sec_ntlm_describe_smb_header(&(cmsg->domain), \"domain\")));\n\tg_free(tmp);\n\n\tg_string_append(str, (tmp = sip_sec_ntlm_describe_smb_header(&(cmsg->user), \"user\")));\n\tg_free(tmp);\n\n\tg_string_append(str, (tmp = sip_sec_ntlm_describe_smb_header(&(cmsg->host), \"host\")));\n\tg_free(tmp);\n\n\tg_string_append(str, (tmp = sip_sec_ntlm_describe_smb_header(&(cmsg->session_key), \"session_key\")));\n\tg_free(tmp);\n\n\ttmp = sip_sec_ntlm_describe_version(&(cmsg->ver));\n\tg_string_append(str, tmp);\n\tg_free(tmp);\n\n\t/* mic */\n\t//g_string_append_printf(str, \"\\t%s: %s\\n\", \"mic\", (tmp = buff_to_hex_str(cmsg->mic, 16)));\n\t//g_free(tmp);\n\n\tif (cmsg->lm_resp.len && cmsg->lm_resp.offset) {\n\t\tvalue_len = GUINT16_FROM_LE(cmsg->lm_resp.len);\n\t\tvalue = (guint8 *)cmsg + GUINT32_FROM_LE(cmsg->lm_resp.offset);\n\t\tg_string_append_printf(str, \"\\t%s: %s\\n\", \"lm_resp\", (tmp = buff_to_hex_str(value, value_len)));\n\t\tg_free(tmp);\n\t}\n\n\tif (cmsg->nt_resp.len && cmsg->nt_resp.offset) {\n\t\tguint16 nt_resp_len_full = GUINT16_FROM_LE(cmsg->nt_resp.len);\n\t\tint nt_resp_len = nt_resp_len_full;\n\n\t\tvalue_len = nt_resp_len_full;\n\t\tvalue = (guint8 *)cmsg + GUINT32_FROM_LE(cmsg->nt_resp.offset);\n\t\tg_string_append_printf(str, \"\\t%s: %s\\n\", \"nt_resp raw\", (tmp = buff_to_hex_str(value, value_len)));\n\t\tg_free(tmp);\n\n\t\tif (nt_resp_len > 24) { /* NTLMv2 */\n\t\t\tnt_resp_len = 16;\n\t\t}\n\n\t\tvalue_len = nt_resp_len;\n\t\tvalue = (guint8 *)cmsg + GUINT32_FROM_LE(cmsg->nt_resp.offset);\n\t\tg_string_append_printf(str, \"\\t%s: %s\\n\", \"nt_resp\", (tmp = buff_to_hex_str(value, value_len)));\n\t\tg_free(tmp);\n\n\t\tif (nt_resp_len_full > 24) { /* NTLMv2 */\n\t\t\t/* Work around Debian/x86_64 compiler bug */\n\t\t\t/* const guint8 *temp = (guint8 *)cmsg + GUINT32_FROM_LE(cmsg->nt_resp.offset) + 16; */\n\t\t\tconst guint offset = GUINT32_FROM_LE(cmsg->nt_resp.offset) + 16;\n\t\t\tconst guint8 *temp = (guint8 *)cmsg + offset;\n\t\t\tconst guint response_version = temp[0];\n\t\t\tconst guint hi_response_version = temp[1];\n\t\t\tconst guint8 *client_challenge = temp + 16;\n\t\t\tconst guint8 *target_info = temp + 28;\n\t\t\tguint16 target_info_len = nt_resp_len_full - 16 - 32;\n\t\t\tguint64 time_val;\n\t\t\ttime_t time_t_val;\n\t\t\tchar *tmp;\n\n\t\t\tg_string_append_printf(str, \"\\t%s: %s\\n\", \"target_info raw\",\n\t\t\t\t(tmp = buff_to_hex_str((guint8 *)target_info, target_info_len)));\n\t\t\tg_free(tmp);\n\n\t\t\t/* This is not int64 aligned on sparc */\n\t\t\tmemcpy((gchar *)&time_val, temp+8, sizeof(time_val));\n\t\t\ttime_t_val = TIME_VAL_TO_T(time_val);\n\n\t\t\tg_string_append_printf(str, \"\\t%s: %d\\n\", \"response_version\", response_version);\n\t\t\tg_string_append_printf(str, \"\\t%s: %d\\n\", \"hi_response_version\", hi_response_version);\n\n\t\t\tg_string_append_printf(str, \"\\t%s: %s - %s\", \"time\", (tmp = buff_to_hex_str((guint8 *)&time_val, 8)),\n\t\t\t\t\t       asctime(gmtime(&time_t_val)));\n\t\t\tg_free(tmp);\n\n\t\t\tg_string_append_printf(str, \"\\t%s: %s\\n\", \"client_challenge\", (tmp = buff_to_hex_str((guint8 *)client_challenge, 8)));\n\t\t\tg_free(tmp);\n\n\t\t\tdescribe_av_pairs(str, target_info);\n\n\t\t\tg_string_append_printf(str, \"\\t%s\\n\", \"----------- end of nt_resp v2 -----------\");\n\t\t}\n\t}\n\n\tif (cmsg->domain.len && cmsg->domain.offset) {\n\t\tgchar *domain = unicode_strconvcopy_back(((gchar *)cmsg + GUINT32_FROM_LE(cmsg->domain.offset)), GUINT16_FROM_LE(cmsg->domain.len));\n\t\tg_string_append_printf(str, \"\\t%s: %s\\n\", \"domain\", domain);\n\t\tg_free(domain);\n\t}\n\n\tif (cmsg->user.len && cmsg->user.offset) {\n\t\tgchar *user = unicode_strconvcopy_back(((gchar *)cmsg + GUINT32_FROM_LE(cmsg->user.offset)), GUINT16_FROM_LE(cmsg->user.len));\n\t\tg_string_append_printf(str, \"\\t%s: %s\\n\", \"user\", user);\n\t\tg_free(user);\n\t}\n\n\tif (cmsg->host.len && cmsg->host.offset) {\n\t\tgchar *host = unicode_strconvcopy_back(((gchar *)cmsg + GUINT32_FROM_LE(cmsg->host.offset)), GUINT16_FROM_LE(cmsg->host.len));\n\t\tg_string_append_printf(str, \"\\t%s: %s\\n\", \"host\", host);\n\t\tg_free(host);\n\t}\n\n\tif (cmsg->session_key.len && cmsg->session_key.offset) {\n\t\tvalue_len = GUINT16_FROM_LE(cmsg->session_key.len);\n\t\tvalue = (guint8 *)cmsg + GUINT32_FROM_LE(cmsg->session_key.offset);\n\t\tg_string_append_printf(str, \"\\t%s: %s\\n\", \"session_key\", (tmp = buff_to_hex_str(value, value_len)));\n\t\tg_free(tmp);\n\t}\n\n\treturn g_string_free(str, FALSE);\n}\n\nstatic gchar *\nsip_sec_ntlm_challenge_message_describe(struct challenge_message *cmsg)\n{\n\tGString* str = g_string_new(NULL);\n\tchar *tmp;\n\n\tg_string_append(str, (tmp = sip_sec_ntlm_negotiate_flags_describe(cmsg->flags)));\n\tg_free(tmp);\n\n\t/* nonce (server_challenge) */\n\tg_string_append_printf(str, \"\\t%s: %s\\n\", \"server_challenge\", (tmp = buff_to_hex_str(cmsg->nonce, 8)));\n\tg_free(tmp);\n\n\tg_string_append(str, (tmp = sip_sec_ntlm_describe_smb_header(&(cmsg->target_name), \"target_name\")));\n\tg_free(tmp);\n\n\tg_string_append(str, (tmp = sip_sec_ntlm_describe_smb_header(&(cmsg->target_info), \"target_info\")));\n\tg_free(tmp);\n\n\tg_string_append(str, (tmp = sip_sec_ntlm_describe_version(&(cmsg->ver))));\n\tg_free(tmp);\n\n\tif (cmsg->target_name.len && cmsg->target_name.offset) {\n\t\tgchar *target_name = unicode_strconvcopy_back(((gchar *)cmsg + GUINT32_FROM_LE(cmsg->target_name.offset)), GUINT16_FROM_LE(cmsg->target_name.len));\n\t\tg_string_append_printf(str, \"\\ttarget_name: %s\\n\", target_name);\n\t\tg_free(target_name);\n\t}\n\n\tif (cmsg->target_info.len && cmsg->target_info.offset) {\n\t\tguint8 *target_info = (guint8 *)cmsg + GUINT32_FROM_LE(cmsg->target_info.offset);\n\t\tguint16 target_info_len = GUINT16_FROM_LE(cmsg->target_info.len);\n\n\t\tg_string_append_printf(str, \"\\t%s: %s\\n\", \"target_info raw\", (tmp = buff_to_hex_str(target_info, target_info_len)));\n\t\tg_free(tmp);\n\n\t\tdescribe_av_pairs(str, target_info);\n\t}\n\n\treturn g_string_free(str, FALSE);\n}\n\nstatic void\nsip_sec_ntlm_message_describe(SipSecBuffer *buff,\n\t\t\t      const gchar *type)\n{\n\tstruct ntlm_message *msg;\n\tgchar *res = NULL;\n\n\tif (buff->length == 0 || buff->value == NULL || buff->length < 12) return;\n\n\t/* SipSecBuffer.value is g_malloc()'d: use (void *) to remove guint8 alignment */\n\tmsg = (void *)buff->value;\n\tif(!sipe_strequal(\"NTLMSSP\", (char*)msg)) return;\n\n\tswitch (GUINT32_FROM_LE(msg->type)) {\n\tcase 1: res = sip_sec_ntlm_negotiate_message_describe((struct negotiate_message *)msg);\n\t\tbreak;\n\tcase 2: res = sip_sec_ntlm_challenge_message_describe((struct challenge_message *)msg);\n\t\tbreak;\n\tcase 3: res = sip_sec_ntlm_authenticate_message_describe((struct authenticate_message *)msg);\n\t\tbreak;\n\t}\n\n\tSIPE_DEBUG_INFO(\"sip_sec_ntlm_message_describe: %s message is:\\n%s\",\n\t\t\ttype, res);\n\tg_free(res);\n}\n\n/* Analyzer only needs the _describe() functions */\n#ifndef _SIPE_COMPILING_ANALYZER\n\n/* sip-sec-mech.h API implementation for NTLM */\n\n/* Security context for NTLM */\ntypedef struct _context_ntlm {\n\tstruct sip_sec_context common;\n\tgchar *domain;\n\tgchar *username;\n\tconst gchar *password;\n\tguchar *client_sign_key;\n\tguchar *server_sign_key;\n\tguchar *client_seal_key;\n\tguchar *server_seal_key;\n\tguint32 flags;\n} *context_ntlm;\n\n#define SIP_SEC_FLAG_NTLM_INITIAL  0x00010000\n\n\nstatic gboolean\nsip_sec_acquire_cred__ntlm(SipSecContext context,\n\t\t\t   const gchar *username,\n\t\t\t   const gchar *password)\n{\n\tcontext_ntlm ctx = (context_ntlm)context;\n\n\t/*\n\t * Our NTLM implementation does not support Single Sign-On.\n\t * Thus username & password are required.\n\t */\n\tif (is_empty(username) || is_empty(password)) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sip_sec_acquire_cred__ntlm: no valid authentication information provided\");\n\t\treturn FALSE;\n\t}\n\n\t/* this is the first time we are allowed to set private flags */\n\tcontext->flags |= SIP_SEC_FLAG_NTLM_INITIAL;\n\n\tif (SIP_SEC_USERNAME_IS_ENTERPRISE) {\n\t\t/* use username as-is, just replace enterprise marker with @ */\n\t\tctx->username = sipe_utils_str_replace(username,\n\t\t\t\t\t\t       SIP_SEC_USERNAME_ENTERPRISE_STRING,\n\t\t\t\t\t\t       \"@\");\n\t} else {\n\t\tSIP_SEC_USERNAME_SPLIT_START;\n\t\tif (SIP_SEC_USERNAME_HAS_DOMAIN) {\n\t\t\tctx->domain   = g_strdup(SIP_SEC_USERNAME_DOMAIN);\n\t\t\tctx->username = g_strdup(SIP_SEC_USERNAME_ACCOUNT);\n\t\t} else {\n\t\t\tctx->username = g_strdup(username);\n\t\t}\n\t\tSIP_SEC_USERNAME_SPLIT_END;\n\t}\n\n\tctx->password = password;\n\n\treturn TRUE;\n}\n\nstatic gboolean\nsip_sec_init_sec_context__ntlm(SipSecContext context,\n\t\t\t       SipSecBuffer in_buff,\n\t\t\t       SipSecBuffer *out_buff,\n\t\t\t       SIPE_UNUSED_PARAMETER const gchar *service_name)\n{\n\tcontext_ntlm ctx = (context_ntlm) context;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_sec_init_sec_context__ntlm: in use\");\n\n\t/*\n\t * If authentication was already completed, then this mean a new\n\t * authentication handshake has started on the existing connection.\n\t * We must throw away the old context, because we need a new one.\n\t */\n\tif (context->flags & SIP_SEC_FLAG_COMMON_READY) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_sec_init_sec_context__ntlm: dropping old context\");\n\t\tcontext->flags &= ~SIP_SEC_FLAG_COMMON_READY;\n\t\tcontext->flags |=  SIP_SEC_FLAG_NTLM_INITIAL;\n\t}\n\n\tif (context->flags & SIP_SEC_FLAG_NTLM_INITIAL) {\n\t\tcontext->flags &= ~SIP_SEC_FLAG_NTLM_INITIAL;\n\n\t\t/* HTTP */\n\t\tif (context->flags & SIP_SEC_FLAG_COMMON_HTTP) {\n\t\t\tsip_sec_ntlm_gen_negotiate(out_buff);\n\t\t\tsip_sec_ntlm_message_describe(out_buff, \"Negotiate\");\n\t\t/* SIP */\n\t\t} else {\n\t\t\t/* empty initial message for connection-less NTLM */\n\t\t\tout_buff->length = 0;\n\t\t\tout_buff->value = (guint8 *) g_strdup(\"\");\n\t\t}\n\t} else \t{\n\t\tgboolean res;\n\t\tguchar *client_sign_key = NULL;\n\t\tguchar *server_sign_key = NULL;\n\t\tguchar *client_seal_key = NULL;\n\t\tguchar *server_seal_key = NULL;\n\t\tguchar *server_challenge = NULL;\n\t\tguint64 time_val = 0;\n\t\tguchar *target_info = NULL;\n\t\tint target_info_len = 0;\n\t\tguint32 flags;\n\t\tgchar *tmp;\n\n\t\tif (!in_buff.value || !in_buff.length) {\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tsip_sec_ntlm_message_describe(&in_buff, \"Challenge\");\n\n\t\tsip_sec_ntlm_parse_challenge(in_buff,\n\t\t\t\t\t     &flags,\n\t\t\t\t\t     &server_challenge, /* 8 bytes */\n\t\t\t\t\t     &time_val,\n\t\t\t\t\t     &target_info,\n\t\t\t\t\t     &target_info_len);\n\n\t\tres = sip_sec_ntlm_gen_authenticate(\n\t\t\t\t\t      &client_sign_key,\n\t\t\t\t\t      &server_sign_key,\n\t\t\t\t\t      &client_seal_key,\n\t\t\t\t\t      &server_seal_key,\n\t\t\t\t\t      ctx->username,\n\t\t\t\t\t      ctx->password,\n\t\t\t\t\t      (tmp = g_ascii_strup(g_get_host_name(), -1)),\n\t\t\t\t\t      ctx->domain ? ctx->domain : \"\",\n\t\t\t\t\t      server_challenge,\n\t\t\t\t\t      time_val,\n\t\t\t\t\t      target_info,\n\t\t\t\t\t      target_info_len,\n\t\t\t\t\t      context->flags & SIP_SEC_FLAG_COMMON_HTTP,\n\t\t\t\t\t      out_buff,\n\t\t\t\t\t      &flags);\n\t\tg_free(server_challenge);\n\t\tg_free(target_info);\n\t\tg_free(tmp);\n\n\t\tif (!res) {\n\t\t\tg_free(client_sign_key);\n\t\t\tg_free(server_sign_key);\n\t\t\tg_free(client_seal_key);\n\t\t\tg_free(server_seal_key);\n\t\t\treturn res;\n\t\t}\n\n\t\tsip_sec_ntlm_message_describe(out_buff, \"Authenticate\");\n\n\t\tg_free(ctx->client_sign_key);\n\t\tctx->client_sign_key = client_sign_key;\n\n\t\tg_free(ctx->server_sign_key);\n\t\tctx->server_sign_key = server_sign_key;\n\n\t\tg_free(ctx->client_seal_key);\n\t\tctx->client_seal_key = client_seal_key;\n\n\t\tg_free(ctx->server_seal_key);\n\t\tctx->server_seal_key = server_seal_key;\n\n\t\tctx->flags = flags;\n\n\t\t/* Authentication is completed */\n\t\tcontext->flags |= SIP_SEC_FLAG_COMMON_READY;\n\t}\n\n\treturn TRUE;\n}\n\n/**\n * @param message a NULL terminated string to sign\n *\n */\nstatic gboolean\nsip_sec_make_signature__ntlm(SipSecContext context,\n\t\t\t     const gchar *message,\n\t\t\t     SipSecBuffer *signature)\n{\n\tsignature->length = 16;\n\tsignature->value = g_malloc0(16);\n\n\t/* FIXME? We always use a random_pad of 0 */\n\tsip_sec_ntlm_sipe_signature_make(((context_ntlm) context)->flags,\n\t\t\t\t\t message,\n\t\t\t\t\t 0,\n\t\t\t\t\t ((context_ntlm) context)->client_sign_key,\n\t\t\t\t\t ((context_ntlm) context)->client_seal_key,\n\t\t\t\t\t /* SipSecBuffer.value is g_malloc()'d:\n\t\t\t\t\t  * use (void *) to remove guint8 alignment\n\t\t\t\t\t  */\n\t\t\t\t\t (void *)signature->value);\n\treturn TRUE;\n}\n\n/**\n * @param message a NULL terminated string to check signature of\n * @return TRUE on success\n */\nstatic gboolean\nsip_sec_verify_signature__ntlm(SipSecContext context,\n\t\t\t       const gchar *message,\n\t\t\t       SipSecBuffer signature)\n{\n\tcontext_ntlm ctx = (context_ntlm) context;\n\tguint32 mac[4];\n\t/* SipSecBuffer.value is g_malloc()'d: use (void *) to remove guint8 alignment */\n\tguint32 random_pad = GUINT32_FROM_LE(((guint32 *)((void *)signature.value))[1]);\n\n\tsip_sec_ntlm_sipe_signature_make(ctx->flags,\n\t\t\t\t\t message,\n\t\t\t\t\t random_pad,\n\t\t\t\t\t ctx->server_sign_key,\n\t\t\t\t\t ctx->server_seal_key,\n\t\t\t\t\t mac);\n\treturn(memcmp(signature.value, mac, 16) == 0);\n}\n\nstatic void\nsip_sec_destroy_sec_context__ntlm(SipSecContext context)\n{\n\tcontext_ntlm ctx = (context_ntlm) context;\n\n\tg_free(ctx->client_sign_key);\n\tg_free(ctx->server_sign_key);\n\tg_free(ctx->client_seal_key);\n\tg_free(ctx->server_seal_key);\n\tg_free(ctx->domain);\n\tg_free(ctx->username);\n\tg_free(ctx);\n}\n\nstatic const gchar *\nsip_sec_context_name__ntlm(SIPE_UNUSED_PARAMETER SipSecContext context)\n{\n\treturn(\"NTLM\");\n}\n\nSipSecContext\nsip_sec_create_context__ntlm(SIPE_UNUSED_PARAMETER guint type)\n{\n\tcontext_ntlm context = g_malloc0(sizeof(struct _context_ntlm));\n\tif (!context) return(NULL);\n\n\tcontext->common.acquire_cred_func     = sip_sec_acquire_cred__ntlm;\n\tcontext->common.init_context_func     = sip_sec_init_sec_context__ntlm;\n\tcontext->common.destroy_context_func  = sip_sec_destroy_sec_context__ntlm;\n\tcontext->common.make_signature_func   = sip_sec_make_signature__ntlm;\n\tcontext->common.verify_signature_func = sip_sec_verify_signature__ntlm;\n\tcontext->common.context_name_func     = sip_sec_context_name__ntlm;\n\n\treturn((SipSecContext) context);\n}\n\ngboolean sip_sec_password__ntlm(void)\n{\n\treturn(TRUE);\n}\n\n#endif /* !_SIPE_COMPILING_ANALYZER */\n\nvoid sip_sec_init__ntlm(void)\n{\n#ifdef HAVE_LANGINFO_CODESET\n\tconst char *sys_cp = nl_langinfo(CODESET);\n#else\n        const char *sys_cp = SIPE_DEFAULT_CODESET;\n#endif /* HAVE_LANGINFO_CODESET */\n\n\t/* fall back to utf-8 */\n\tif (!sys_cp) sys_cp = \"UTF-8\";\n\n\tconvert_from_utf16le = g_iconv_open(sys_cp, \"UTF-16LE\");\n\tif (convert_from_utf16le == (GIConv)-1) {\n\t\tSIPE_DEBUG_ERROR(\"g_iconv_open from UTF-16LE to %s failed\",\n\t\t\t\t sys_cp);\n\t}\n\n\tconvert_to_utf16le = g_iconv_open(\"UTF-16LE\", sys_cp);\n\tif (convert_to_utf16le == (GIConv)-1) {\n\t\tSIPE_DEBUG_ERROR(\"g_iconv_open from %s to UTF-16LE failed\",\n\t\t\t\t sys_cp);\n\t}\n}\n\nvoid sip_sec_destroy__ntlm(void)\n{\n\tg_iconv_close(convert_to_utf16le);\n\tg_iconv_close(convert_from_utf16le);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sip-sec-ntlm.h",
    "content": "/**\n * @file sip-sec-ntlm.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-12 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2009 pier11 <pier11@operamail.com>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\nSipSecContext\nsip_sec_create_context__ntlm(guint type);\n\ngboolean sip_sec_password__ntlm(void);\n\nvoid sip_sec_init__ntlm(void);\nvoid sip_sec_destroy__ntlm(void);\n"
  },
  {
    "path": "src/core/sip-sec-sspi.c",
    "content": "/**\n * @file sip-sec-sspi.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2015 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2009 pier11 <pier11@operamail.com>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifndef _WIN32\n#error sip-sec-sspi.c can only be compiled for Windows builds\n#endif\n\n#include <windows.h>\n#include <rpc.h>\n#ifndef SECURITY_WIN32\n#define SECURITY_WIN32 1\n#endif\n#include <security.h>\n\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sip-sec.h\"\n#include \"sip-sec-mech.h\"\n#include \"sip-sec-sspi.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-utils.h\"\n\n/* Mechanism names */\nstatic const gchar * const mech_names[] = {\n\t\"\",          /* SIPE_AUTHENTICATION_TYPE_UNSET     */\n\t\"\",          /* SIPE_AUTHENTICATION_TYPE_BASIC     */\n\t\"NTLM\",      /* SIPE_AUTHENTICATION_TYPE_NTLM      */\n\t\"Kerberos\",  /* SIPE_AUTHENTICATION_TYPE_KERBEROS  */\n\t\"Negotiate\", /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */\n\t\"\",          /* SIPE_AUTHENTICATION_TYPE_TLS_DSK   */\n\t\"\",          /* SIPE_AUTHENTICATION_TYPE_AUTOMATIC */\n};\n\n#ifndef ISC_REQ_IDENTIFY\n#define ISC_REQ_IDENTIFY               0x00002000\n#endif\n\ntypedef struct _context_sspi {\n\tstruct sip_sec_context common;\n\tCredHandle* cred_sspi;\n\tCtxtHandle* ctx_sspi;\n} *context_sspi;\n\n#define SIP_SEC_FLAG_SSPI_SIP_NTLM 0x00010000\n\n/* Utility Functions */\n\nstatic void\nsip_sec_sspi_print_error(const gchar *func,\n\t\t\t SECURITY_STATUS ret)\n{\n\tgchar *error_message;\n\tstatic char *buff;\n\tguint buff_length;\n\n\tbuff_length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |\n\t\t\t\t    FORMAT_MESSAGE_ALLOCATE_BUFFER |\n\t\t\t\t    FORMAT_MESSAGE_IGNORE_INSERTS,\n\t\t\t\t    0,\n\t\t\t\t    ret,\n\t\t\t\t    0,\n\t\t\t\t    (LPTSTR)&buff,\n\t\t\t\t    16384,\n\t\t\t\t    0);\n\terror_message = g_strndup(buff, buff_length);\n\tLocalFree(buff);\n\n\tSIPE_DEBUG_ERROR(\"SSPI ERROR [%d] in %s: %s\", (int)ret, func, error_message);\n\tg_free(error_message);\n}\n\n/* Returns interval in seconds from now till provided value */\nstatic guint\nsip_sec_get_interval_from_now_sec(TimeStamp timestamp)\n{\n\tSYSTEMTIME stNow;\n\tFILETIME ftNow;\n\tULARGE_INTEGER uliNow, uliTo;\n\n\tGetLocalTime(&stNow);\n\tSystemTimeToFileTime(&stNow, &ftNow);\n\n\tuliNow.LowPart = ftNow.dwLowDateTime;\n\tuliNow.HighPart = ftNow.dwHighDateTime;\n\n\tuliTo.LowPart = timestamp.LowPart;\n\tuliTo.HighPart = timestamp.HighPart;\n\n\treturn((uliTo.QuadPart - uliNow.QuadPart)/10/1000/1000);\n}\n\nstatic void\nsip_sec_destroy_sspi_context(context_sspi context)\n{\n\tif (context->ctx_sspi) {\n\t\tDeleteSecurityContext(context->ctx_sspi);\n\t\tg_free(context->ctx_sspi);\n\t\tcontext->ctx_sspi = NULL;\n\t}\n\tif (context->cred_sspi) {\n\t\tFreeCredentialsHandle(context->cred_sspi);\n\t\tg_free(context->cred_sspi);\n\t\tcontext->cred_sspi = NULL;\n\t}\n}\n\n/* sip-sec-mech.h API implementation for SSPI - Kerberos, NTLM and Negotiate */\n\nstatic gboolean\nsip_sec_acquire_cred__sspi(SipSecContext context,\n\t\t\t   const gchar *username,\n\t\t\t   const gchar *password)\n{\n\tSECURITY_STATUS ret;\n\tTimeStamp expiry;\n\tSEC_WINNT_AUTH_IDENTITY auth_identity;\n\tcontext_sspi ctx = (context_sspi)context;\n\tgchar *domain_tmp = NULL;\n\tgchar *user_tmp = NULL;\n\n\t/* this is the first time we are allowed to set private flags */\n\tif (((context->flags & SIP_SEC_FLAG_COMMON_HTTP) == 0) &&\n\t    (context->type == SIPE_AUTHENTICATION_TYPE_NTLM))\n\t\tcontext->flags |= SIP_SEC_FLAG_SSPI_SIP_NTLM;\n\n\tif ((context->flags & SIP_SEC_FLAG_COMMON_SSO) == 0) {\n\t\tif (is_empty(username) || is_empty(password)) {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sip_sec_acquire_cred__sspi: no valid authentication information provided\");\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tmemset(&auth_identity, 0, sizeof(auth_identity));\n\t\tauth_identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;\n\n\t\tif (SIP_SEC_USERNAME_IS_ENTERPRISE) {\n\t\t\t/* use username as-is, just replace enterprise marker with @ */\n\t\t\tuser_tmp = sipe_utils_str_replace(username,\n\t\t\t\t\t\t\t  SIP_SEC_USERNAME_ENTERPRISE_STRING,\n\t\t\t\t\t\t\t  \"@\");\n\t\t} else {\n\t\t\tSIP_SEC_USERNAME_SPLIT_START;\n\t\t\tif (SIP_SEC_USERNAME_HAS_DOMAIN) {\n\t\t\t\tdomain_tmp                 = g_strdup(SIP_SEC_USERNAME_DOMAIN);\n\t\t\t\tuser_tmp                   = g_strdup(SIP_SEC_USERNAME_ACCOUNT);\n\t\t\t\tauth_identity.Domain       = (unsigned char *)domain_tmp;\n\t\t\t\tauth_identity.DomainLength = strlen(domain_tmp);\n\t\t\t}\n\t\t\tSIP_SEC_USERNAME_SPLIT_END;\n\t\t}\n\n\t\tauth_identity.User           = (unsigned char *)(user_tmp ? user_tmp : username);\n\t\tauth_identity.UserLength     = strlen((char *) auth_identity.User);\n\n\t\tauth_identity.Password       = (unsigned char *)password;\n\t\tauth_identity.PasswordLength = strlen(password);\n\t}\n\n\tctx->cred_sspi = g_malloc0(sizeof(CredHandle));\n\n\tret = AcquireCredentialsHandleA(NULL,\n\t\t\t\t\t(SEC_CHAR *)mech_names[context->type],\n\t\t\t\t\tSECPKG_CRED_OUTBOUND,\n\t\t\t\t\tNULL,\n\t\t\t\t\t(context->flags & SIP_SEC_FLAG_COMMON_SSO) ? NULL : &auth_identity,\n\t\t\t\t\tNULL,\n\t\t\t\t\tNULL,\n\t\t\t\t\tctx->cred_sspi,\n\t\t\t\t\t&expiry);\n\n\tg_free(user_tmp);\n\tg_free(domain_tmp);\n\n\tif (ret != SEC_E_OK) {\n\t\tsip_sec_sspi_print_error(\"sip_sec_acquire_cred__sspi: AcquireCredentialsHandleA\", ret);\n\t\tg_free(ctx->cred_sspi);\n\t\tctx->cred_sspi = NULL;\n\t\treturn FALSE;\n\t} else {\n\t\treturn TRUE;\n\t}\n}\n\nstatic gboolean\nsip_sec_init_sec_context__sspi(SipSecContext context,\n\t\t\t       SipSecBuffer in_buff,\n\t\t\t       SipSecBuffer *out_buff,\n\t\t\t       const gchar *service_name)\n{\n\tTimeStamp expiry;\n\tSecBufferDesc input_desc, output_desc;\n\tSecBuffer in_token, out_token;\n\tSECURITY_STATUS ret;\n\tULONG req_flags;\n\tULONG ret_flags;\n\tcontext_sspi ctx = (context_sspi)context;\n\tCtxtHandle* out_context;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_sec_init_sec_context__sspi: in use\");\n\n\t/*\n\t * If authentication was already completed, then this mean a new\n\t * authentication handshake has started on the existing connection.\n\t * We must throw away the old context, because we need a new one.\n\t */\n\tif ((context->flags & SIP_SEC_FLAG_COMMON_READY) &&\n\t    ctx->ctx_sspi) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_sec_init_sec_context__sspi: dropping old context\");\n\t\tDeleteSecurityContext(ctx->ctx_sspi);\n\t\tg_free(ctx->ctx_sspi);\n\t\tctx->ctx_sspi = NULL;\n\t\tcontext->flags &= ~SIP_SEC_FLAG_COMMON_READY;\n\t}\n\n\t/* reuse existing context on following calls */\n\tout_context = ctx->ctx_sspi ? ctx->ctx_sspi : g_malloc0(sizeof(CtxtHandle));\n\n\tinput_desc.cBuffers = 1;\n\tinput_desc.pBuffers = &in_token;\n\tinput_desc.ulVersion = SECBUFFER_VERSION;\n\n\t/* input token */\n\tin_token.BufferType = SECBUFFER_TOKEN;\n\tin_token.cbBuffer = in_buff.length;\n\tin_token.pvBuffer = in_buff.value;\n\n\toutput_desc.cBuffers = 1;\n\toutput_desc.pBuffers = &out_token;\n\toutput_desc.ulVersion = SECBUFFER_VERSION;\n\n\t/* to hold output token */\n\tout_token.BufferType = SECBUFFER_TOKEN;\n\tout_token.cbBuffer = 0;\n\tout_token.pvBuffer = NULL;\n\n\treq_flags = (ISC_REQ_ALLOCATE_MEMORY |\n\t\t     ISC_REQ_INTEGRITY |\n\t\t     ISC_REQ_IDENTIFY);\n\n\tif (context->flags & SIP_SEC_FLAG_SSPI_SIP_NTLM) {\n\t\treq_flags |= (ISC_REQ_DATAGRAM);\n\t}\n\n\tret = InitializeSecurityContextA(ctx->cred_sspi,\n\t\t\t\t\t ctx->ctx_sspi,\n\t\t\t\t\t (SEC_CHAR *)service_name,\n\t\t\t\t\t req_flags,\n\t\t\t\t\t 0,\n\t\t\t\t\t SECURITY_NATIVE_DREP,\n\t\t\t\t\t &input_desc,\n\t\t\t\t\t 0,\n\t\t\t\t\t out_context,\n\t\t\t\t\t &output_desc,\n\t\t\t\t\t &ret_flags,\n\t\t\t\t\t &expiry);\n\n\tif (ret != SEC_E_OK && ret != SEC_I_CONTINUE_NEEDED) {\n\t\tif (!ctx->ctx_sspi)\n\t\t\tg_free(out_context);\n\t\tsip_sec_destroy_sspi_context(ctx);\n\t\tsip_sec_sspi_print_error(\"sip_sec_init_sec_context__sspi: InitializeSecurityContextA\", ret);\n\t\treturn FALSE;\n\t}\n\n\tout_buff->length = out_token.cbBuffer;\n\tif (out_token.cbBuffer) {\n\t\tout_buff->value = g_malloc(out_token.cbBuffer);\n\t\tmemcpy(out_buff->value, out_token.pvBuffer, out_token.cbBuffer);\n\t} else {\n\t\t/* Special case: empty token */\n\t\tout_buff->value = (guint8 *) g_strdup(\"\");\n\t}\n\tFreeContextBuffer(out_token.pvBuffer);\n\n\tctx->ctx_sspi = out_context;\n\n\tif (context->type == SIPE_AUTHENTICATION_TYPE_KERBEROS) {\n\t\tcontext->expires = sip_sec_get_interval_from_now_sec(expiry);\n\t}\n\n\tif (ret != SEC_I_CONTINUE_NEEDED) {\n\t\t/* Authentication is completed */\n\t\tcontext->flags |= SIP_SEC_FLAG_COMMON_READY;\n\t}\n\n\treturn TRUE;\n}\n\nstatic void\nsip_sec_destroy_sec_context__sspi(SipSecContext context)\n{\n\tsip_sec_destroy_sspi_context((context_sspi)context);\n\tg_free(context);\n}\n\n/**\n * @param message a NULL terminated string to sign\n *\n */\nstatic gboolean\nsip_sec_make_signature__sspi(SipSecContext context,\n\t\t\t     const gchar *message,\n\t\t\t     SipSecBuffer *signature)\n{\n\tSecBufferDesc buffs_desc;\n\tSecBuffer buffs[2];\n\tSECURITY_STATUS ret;\n\tSecPkgContext_Sizes context_sizes;\n\tguchar *signature_buff;\n\tsize_t signature_buff_length;\n\tcontext_sspi ctx = (context_sspi) context;\n\n\tret = QueryContextAttributes(ctx->ctx_sspi,\n\t\t\t\t     SECPKG_ATTR_SIZES,\n\t\t\t\t     &context_sizes);\n\n\tif (ret != SEC_E_OK) {\n\t\tsip_sec_sspi_print_error(\"sip_sec_make_signature__sspi: QueryContextAttributes\", ret);\n\t\treturn FALSE;\n\t}\n\n\tsignature_buff_length = context_sizes.cbMaxSignature;\n\tsignature_buff = g_malloc(signature_buff_length);\n\n\tbuffs_desc.cBuffers = 2;\n\tbuffs_desc.pBuffers = buffs;\n\tbuffs_desc.ulVersion = SECBUFFER_VERSION;\n\n\t/* message to sign */\n\tbuffs[0].BufferType = SECBUFFER_DATA;\n\tbuffs[0].cbBuffer = strlen(message);\n\tbuffs[0].pvBuffer = (PVOID)message;\n\n\t/* to hold signature */\n\tbuffs[1].BufferType = SECBUFFER_TOKEN;\n\tbuffs[1].cbBuffer = signature_buff_length;\n\tbuffs[1].pvBuffer = signature_buff;\n\n\tret = MakeSignature(ctx->ctx_sspi,\n\t\t\t    (ULONG)0,\n\t\t\t    &buffs_desc,\n\t\t\t    100);\n\tif (ret != SEC_E_OK) {\n\t\tsip_sec_sspi_print_error(\"sip_sec_make_signature__sspi: MakeSignature\", ret);\n\t\tg_free(signature_buff);\n\t\treturn FALSE;\n\t}\n\n\tsignature->value = signature_buff;\n\tsignature->length = buffs[1].cbBuffer;\n\n\treturn TRUE;\n}\n\n/**\n * @param message a NULL terminated string to check signature of\n * @return TRUE on success\n */\nstatic gboolean\nsip_sec_verify_signature__sspi(SipSecContext context,\n\t\t\t       const gchar *message,\n\t\t\t       SipSecBuffer signature)\n{\n\tSecBufferDesc buffs_desc;\n\tSecBuffer buffs[2];\n\tSECURITY_STATUS ret;\n\n\tbuffs_desc.cBuffers = 2;\n\tbuffs_desc.pBuffers = buffs;\n\tbuffs_desc.ulVersion = SECBUFFER_VERSION;\n\n\t/* message to sign */\n\tbuffs[0].BufferType = SECBUFFER_DATA;\n\tbuffs[0].cbBuffer = strlen(message);\n\tbuffs[0].pvBuffer = (PVOID)message;\n\n\t/* signature to check */\n\tbuffs[1].BufferType = SECBUFFER_TOKEN;\n\tbuffs[1].cbBuffer = signature.length;\n\tbuffs[1].pvBuffer = signature.value;\n\n\tret = VerifySignature(((context_sspi)context)->ctx_sspi,\n\t\t\t      &buffs_desc,\n\t\t\t      0,\n\t\t\t      0);\n\n\tif (ret != SEC_E_OK) {\n\t\tsip_sec_sspi_print_error(\"sip_sec_verify_signature__sspi: VerifySignature\", ret);\n\t\treturn FALSE;\n\t}\n\n\treturn TRUE;\n}\n\n/* SSPI implements SPNEGO (RFC 4559) */\nstatic const gchar *\nsip_sec_context_name__sspi(SipSecContext context)\n{\n\treturn(mech_names[context->type]);\n}\n\nSipSecContext\nsip_sec_create_context__sspi(SIPE_UNUSED_PARAMETER guint type)\n{\n\tcontext_sspi context = g_malloc0(sizeof(struct _context_sspi));\n\tif (!context) return(NULL);\n\n\tcontext->common.acquire_cred_func     = sip_sec_acquire_cred__sspi;\n\tcontext->common.init_context_func     = sip_sec_init_sec_context__sspi;\n\tcontext->common.destroy_context_func  = sip_sec_destroy_sec_context__sspi;\n\tcontext->common.make_signature_func   = sip_sec_make_signature__sspi;\n\tcontext->common.verify_signature_func = sip_sec_verify_signature__sspi;\n\tcontext->common.context_name_func     = sip_sec_context_name__sspi;\n\n\treturn((SipSecContext) context);\n}\n\ngboolean sip_sec_password__sspi(void)\n{\n\t/* SSPI supports Single-Sign On */\n\treturn(FALSE);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sip-sec-sspi.h",
    "content": "/**\n * @file sip-sec-sspi.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2012 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2009 pier11 <pier11@operamail.com>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\nSipSecContext\nsip_sec_create_context__sspi(guint type);\n\ngboolean sip_sec_password__sspi(void);\n"
  },
  {
    "path": "src/core/sip-sec-tls-dsk.c",
    "content": "/**\n * @file sip-sec-tls-dsk.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2015 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * Specification references:\n *\n *   - [MS-SIPAE]:    http://msdn.microsoft.com/en-us/library/cc431510.aspx\n *   - [MS-OCAUTHWS]: http://msdn.microsoft.com/en-us/library/ff595592.aspx\n *   - MS Tech-Ed Europe 2010 \"UNC310: Microsoft Lync 2010 Technology Explained\"\n *     http://ecn.channel9.msdn.com/o9/te/Europe/2010/pptx/unc310.pptx\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sip-sec.h\"\n#include \"sip-sec-mech.h\"\n#include \"sip-sec-tls-dsk.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-digest.h\"\n#include \"sipe-tls.h\"\n\n/* Security context for TLS-DSK */\ntypedef struct _context_tls_dsk {\n\tstruct sip_sec_context common;\n\tstruct sipe_tls_state *state;\n\tenum sipe_tls_digest_algorithm algorithm;\n\tguchar *client_key;\n\tguchar *server_key;\n\tgsize key_length;\n} *context_tls_dsk;\n\n/* sip-sec-mech.h API implementation for TLS-DSK */\n\nstatic gboolean\nsip_sec_acquire_cred__tls_dsk(SipSecContext context,\n\t\t\t      SIPE_UNUSED_PARAMETER const gchar *username,\n\t\t\t      const gchar *password)\n{\n\tcontext_tls_dsk ctx = (context_tls_dsk) context;\n\n\treturn((ctx->state = sipe_tls_start((gpointer) password)) != NULL);\n}\n\nstatic gboolean\nsip_sec_init_sec_context__tls_dsk(SipSecContext context,\n\t\t\t\t  SipSecBuffer in_buff,\n\t\t\t\t  SipSecBuffer *out_buff,\n\t\t\t\t  SIPE_UNUSED_PARAMETER const gchar *service_name)\n{\n\tcontext_tls_dsk ctx = (context_tls_dsk) context;\n\tstruct sipe_tls_state *state = ctx->state;\n\n\tstate->in_buffer = in_buff.value;\n\tstate->in_length = in_buff.length;\n\n\tif (sipe_tls_next(state)) {\n\t\tif ((state->algorithm != SIPE_TLS_DIGEST_ALGORITHM_NONE) &&\n\t\t    state->client_key && state->server_key) {\n\t\t\t/* Authentication is completed */\n\t\t\tcontext->flags |= SIP_SEC_FLAG_COMMON_READY;\n\n\t\t\t/* copy key pair */\n\t\t\tctx->algorithm  = state->algorithm;\n\t\t\tctx->key_length = state->key_length;\n\t\t\tctx->client_key = g_memdup(state->client_key,\n\t\t\t\t\t\t   state->key_length);\n\t\t\tctx->server_key = g_memdup(state->server_key,\n\t\t\t\t\t\t   state->key_length);\n\n\t\t\t/* extract certicate expiration time */\n\t\t\tctx->common.expires = sipe_tls_expires(state);\n\n\t\t\tSIPE_DEBUG_INFO(\"sip_sec_init_sec_context__tls_dsk: handshake completed, algorithm %d, key length %\" G_GSIZE_FORMAT \", expires %d\",\n\t\t\t\t\tctx->algorithm, ctx->key_length, ctx->common.expires);\n\n\t\t\tsipe_tls_free(state);\n\t\t\tctx->state = NULL;\n\t\t} else {\n\t\t\tout_buff->value  = state->out_buffer;\n\t\t\tout_buff->length = state->out_length;\n\t\t\t/* we take ownership of the buffer */\n\t\t\tstate->out_buffer = NULL;\n\t\t}\n\t} else {\n\t\tsipe_tls_free(state);\n\t\tctx->state = NULL;\n\t}\n\n\treturn(((context->flags & SIP_SEC_FLAG_COMMON_READY) ||\n\t\tctx->state));\n}\n\nstatic gboolean\nsip_sec_make_signature__tls_dsk(SipSecContext context,\n\t\t\t\tconst gchar *message,\n\t\t\t\tSipSecBuffer *signature)\n{\n\tcontext_tls_dsk ctx = (context_tls_dsk) context;\n\tgboolean result = FALSE;\n\n\tswitch (ctx->algorithm) {\n\tcase SIPE_TLS_DIGEST_ALGORITHM_MD5:\n\t\tsignature->length = SIPE_DIGEST_HMAC_MD5_LENGTH;\n\t\tsignature->value  = g_malloc0(signature->length);\n\t\tsipe_digest_hmac_md5(ctx->client_key, ctx->key_length,\n\t\t\t\t     (guchar *) message, strlen(message),\n\t\t\t\t     signature->value);\n\t\tresult = TRUE;\n\t\tbreak;\n\n\tcase SIPE_TLS_DIGEST_ALGORITHM_SHA1:\n\t\tsignature->length = SIPE_DIGEST_HMAC_SHA1_LENGTH;\n\t\tsignature->value  = g_malloc0(signature->length);\n\t\tsipe_digest_hmac_sha1(ctx->client_key, ctx->key_length,\n\t\t\t\t      (guchar *) message, strlen(message),\n\t\t\t\t      signature->value);\n\t\tresult = TRUE;\n\t\tbreak;\n\n\tdefault:\n\t\t/* this should not happen */\n\t\tbreak;\n\t}\n\n\treturn(result);\n}\n\nstatic gboolean\nsip_sec_verify_signature__tls_dsk(SipSecContext context,\n\t\t\t\t  const gchar *message,\n\t\t\t\t  SipSecBuffer signature)\n{\n\tcontext_tls_dsk ctx = (context_tls_dsk) context;\n\tSipSecBuffer mac    = { 0, NULL };\n\tgboolean result     = FALSE;\n\n\tswitch (ctx->algorithm) {\n\tcase SIPE_TLS_DIGEST_ALGORITHM_MD5:\n\t\tmac.length = SIPE_DIGEST_HMAC_MD5_LENGTH;\n\t\tmac.value  = g_malloc0(mac.length);\n\t\tsipe_digest_hmac_md5(ctx->server_key, ctx->key_length,\n\t\t\t\t     (guchar *) message, strlen(message),\n\t\t\t\t     mac.value);\n\t\tbreak;\n\n\tcase SIPE_TLS_DIGEST_ALGORITHM_SHA1:\n\t\tmac.length = SIPE_DIGEST_HMAC_SHA1_LENGTH;\n\t\tmac.value  = g_malloc0(mac.length);\n\t\tsipe_digest_hmac_sha1(ctx->server_key, ctx->key_length,\n\t\t\t\t      (guchar *) message, strlen(message),\n\t\t\t\t      mac.value);\n\t\tbreak;\n\n\tdefault:\n\t\t/* this should not happen */\n\t\tbreak;\n\t}\n\n\tif (mac.value) {\n\t\tresult = memcmp(signature.value, mac.value, mac.length) == 0;\n\t\tg_free(mac.value);\n\t}\n\n\treturn(result);\n}\n\nstatic void\nsip_sec_destroy_sec_context__tls_dsk(SipSecContext context)\n{\n\tcontext_tls_dsk ctx = (context_tls_dsk) context;\n\n\tsipe_tls_free(ctx->state);\n\tg_free(ctx->client_key);\n\tg_free(ctx->server_key);\n\tg_free(ctx);\n}\n\nstatic const gchar *\nsip_sec_context_name__tls_dsk(SIPE_UNUSED_PARAMETER SipSecContext context)\n{\n\treturn(\"TLS-DSK\");\n}\n\nSipSecContext\nsip_sec_create_context__tls_dsk(SIPE_UNUSED_PARAMETER guint type)\n{\n\tcontext_tls_dsk context = g_malloc0(sizeof(struct _context_tls_dsk));\n\tif (!context) return(NULL);\n\n\tcontext->common.acquire_cred_func     = sip_sec_acquire_cred__tls_dsk;\n\tcontext->common.init_context_func     = sip_sec_init_sec_context__tls_dsk;\n\tcontext->common.destroy_context_func  = sip_sec_destroy_sec_context__tls_dsk;\n\tcontext->common.make_signature_func   = sip_sec_make_signature__tls_dsk;\n\tcontext->common.verify_signature_func = sip_sec_verify_signature__tls_dsk;\n\tcontext->common.context_name_func     = sip_sec_context_name__tls_dsk;\n\n\treturn((SipSecContext) context);\n}\n\ngboolean sip_sec_password__tls_dsk(void)\n{\n#if defined(HAVE_SSPI) || defined(HAVE_GSSAPI_GSSAPI_H)\n\t/*\n\t * TLS-DSK authenticates with a published client certificate. This\n\t * process uses Web Tickets and therefore goes through HTTP. If we\n\t * have authentication schemes compiled in which allow Single Sign-On\n\t * then we should allow password-less configurations.\n\t */\n\treturn(FALSE);\n#else\n\treturn(TRUE);\n#endif\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sip-sec-tls-dsk.h",
    "content": "/**\n * @file sip-sec-tls-dsk.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-12 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\nSipSecContext\nsip_sec_create_context__tls_dsk(guint type);\n\ngboolean sip_sec_password__tls_dsk(void);\n"
  },
  {
    "path": "src/core/sip-sec.c",
    "content": "/**\n * @file sip-sec.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2015 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2009 pier11 <pier11@operamail.com>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n#include <stdio.h>\n#include <time.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sip-sec.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-utils.h\"\n\n#include \"sip-sec-mech.h\"\n\n/* SSPI is only supported on Windows platform */\n#if defined(_WIN32) && defined(HAVE_SSPI)\n#include \"sip-sec-sspi.h\"\n#define SIP_SEC_WINDOWS_SSPI 1\n#else\n#define SIP_SEC_WINDOWS_SSPI 0\n#endif\n\n#ifdef HAVE_GSSAPI_GSSAPI_H\n#include \"sip-sec-gssapi.h\"\n#endif\n\n/* SIPE_AUTHENTICATION_TYPE_BASIC */\n#include \"sip-sec-basic.h\"\n#define sip_sec_create_context__Basic      sip_sec_create_context__basic\n/* Basic is only used for HTTP, not for SIP */\n#define sip_sec_password__Basic            sip_sec_password__NONE\n\n/* SIPE_AUTHENTICATION_TYPE_NTLM */\n#if SIP_SEC_WINDOWS_SSPI\n#define sip_sec_create_context__NTLM       sip_sec_create_context__sspi\n#define sip_sec_password__NTLM             sip_sec_password__sspi\n#elif defined(HAVE_GSSAPI_ONLY)\n#define sip_sec_create_context__NTLM       sip_sec_create_context__gssapi\n#define sip_sec_password__NTLM             sip_sec_password__gssapi\n#else\n#include \"sip-sec-ntlm.h\"\n#define sip_sec_create_context__NTLM       sip_sec_create_context__ntlm\n#define sip_sec_password__NTLM             sip_sec_password__ntlm\n#endif\n\n/* SIPE_AUTHENTICATION_TYPE_KERBEROS */\n#if SIP_SEC_WINDOWS_SSPI\n#define sip_sec_create_context__Kerberos   sip_sec_create_context__sspi\n#define sip_sec_password__Kerberos         sip_sec_password__sspi\n#elif defined(HAVE_GSSAPI_GSSAPI_H)\n#define sip_sec_create_context__Kerberos   sip_sec_create_context__gssapi\n#define sip_sec_password__Kerberos         sip_sec_password__gssapi\n#else\n#define sip_sec_create_context__Kerberos   sip_sec_create_context__NONE\n#define sip_sec_password__Kerberos         sip_sec_password__NONE\n#endif\n\n/* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */\n#if SIP_SEC_WINDOWS_SSPI\n#define sip_sec_create_context__Negotiate  sip_sec_create_context__sspi\n#elif defined(HAVE_GSSAPI_ONLY)\n#define sip_sec_create_context__Negotiate  sip_sec_create_context__gssapi\n#elif defined(HAVE_GSSAPI_GSSAPI_H)\n#include \"sip-sec-negotiate.h\"\n#define sip_sec_create_context__Negotiate  sip_sec_create_context__negotiate\n#else\n#define sip_sec_create_context__Negotiate  sip_sec_create_context__NONE\n#endif\n/* Negotiate is only used for HTTP, not for SIP */\n#define sip_sec_password__Negotiate        sip_sec_password__NONE\n\n/* SIPE_AUTHENTICATION_TYPE_TLS_DSK */\n#include \"sip-sec-tls-dsk.h\"\n#define sip_sec_create_context__TLS_DSK    sip_sec_create_context__tls_dsk\n#define sip_sec_password__TLS_DSK          sip_sec_password__tls_dsk\n\n/* Dummy initialization hook */\nstatic SipSecContext\nsip_sec_create_context__NONE(SIPE_UNUSED_PARAMETER guint type)\n{\n\treturn(NULL);\n}\n\n/* Dummy SIP password hooks */\nstatic gboolean sip_sec_password__NONE(void)\n{\n\t/* Don't ask for a password */\n\treturn(FALSE);\n}\n\n/* sip_sec API methods */\nSipSecContext\nsip_sec_create_context(guint type,\n\t\t       gboolean sso,\n\t\t       gboolean http,\n\t\t       const gchar *username,\n\t\t       const gchar *password)\n{\n\tSipSecContext context = NULL;\n\n\t/* Map authentication type to module initialization hook & name */\n\tstatic sip_sec_create_context_func const auth_to_hook[] = {\n\t\tsip_sec_create_context__NONE,      /* SIPE_AUTHENTICATION_TYPE_UNSET     */\n\t\tsip_sec_create_context__Basic,     /* SIPE_AUTHENTICATION_TYPE_BASIC     */\n\t\tsip_sec_create_context__NTLM,      /* SIPE_AUTHENTICATION_TYPE_NTLM      */\n\t\tsip_sec_create_context__Kerberos,  /* SIPE_AUTHENTICATION_TYPE_KERBEROS  */\n\t\tsip_sec_create_context__Negotiate, /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */\n\t\tsip_sec_create_context__TLS_DSK,   /* SIPE_AUTHENTICATION_TYPE_TLS_DSK   */\n\t\tsip_sec_create_context__NONE,      /* SIPE_AUTHENTICATION_TYPE_AUTOMATIC */\n\t};\n\n\tSIPE_DEBUG_INFO(\"sip_sec_create_context: type: %d, Single Sign-On: %s, protocol: %s\",\n\t\t\ttype, sso ? \"yes\" : \"no\", http ? \"HTTP\" : \"SIP\");\n\n\tcontext = (*(auth_to_hook[type]))(type);\n\tif (context) {\n\n\t\tcontext->type = type;\n\n\t\t/* NOTE: mechanism must set private flags acquire_cred_func()! */\n\t\tcontext->flags = 0;\n\n\t\t/* set common flags */\n\t\tif (sso)\n\t\t\tcontext->flags |= SIP_SEC_FLAG_COMMON_SSO;\n\t\tif (http)\n\t\t\tcontext->flags |= SIP_SEC_FLAG_COMMON_HTTP;\n\n\t\tif (!(*context->acquire_cred_func)(context, username, password)) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"ERROR: sip_sec_create_context: failed to acquire credentials.\");\n\t\t\t(*context->destroy_context_func)(context);\n\t\t\tcontext = NULL;\n\t\t}\n\t}\n\n\treturn(context);\n}\n\ngboolean\nsip_sec_init_context_step(SipSecContext context,\n\t\t\t  const gchar *target,\n\t\t\t  const gchar *input_toked_base64,\n\t\t\t  gchar **output_toked_base64,\n\t\t\t  guint *expires)\n{\n\tgboolean ret = FALSE;\n\n\tif (context) {\n\t\tSipSecBuffer in_buff  = {0, NULL};\n\t\tSipSecBuffer out_buff = {0, NULL};\n\n\t\t/* Not NULL for NTLM Type 2 or TLS-DSK */\n\t\tif (input_toked_base64)\n\t\t\tin_buff.value = g_base64_decode(input_toked_base64, &in_buff.length);\n\n\t\tret = (*context->init_context_func)(context, in_buff, &out_buff, target);\n\n\t\tif (input_toked_base64)\n\t\t\tg_free(in_buff.value);\n\n\t\tif (ret) {\n\n\t\t\tif (out_buff.value) {\n\t\t\t\tif (out_buff.length > 0) {\n\t\t\t\t\t*output_toked_base64 = g_base64_encode(out_buff.value, out_buff.length);\n\t\t\t\t} else {\n\t\t\t\t\t/* special string: caller takes ownership */\n\t\t\t\t\t*output_toked_base64 = (gchar *) out_buff.value;\n\t\t\t\t\tout_buff.value = NULL;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tg_free(out_buff.value);\n\t\t}\n\n\t\tif (expires) {\n\t\t\t*expires = context->expires;\n\t\t}\n\t}\n\n\treturn ret;\n}\n\ngboolean sip_sec_context_is_ready(SipSecContext context)\n{\n\treturn(context && (context->flags & SIP_SEC_FLAG_COMMON_READY));\n}\n\nconst gchar *sip_sec_context_name(SipSecContext context)\n{\n\tif (context)\n\t\treturn((*context->context_name_func)(context));\n\telse\n\t\treturn(NULL);\n}\n\nguint sip_sec_context_type(SipSecContext context)\n{\n\tif (context)\n\t\treturn(context->type);\n\telse\n\t\treturn(SIPE_AUTHENTICATION_TYPE_UNSET);\n}\n\nvoid sip_sec_destroy_context(SipSecContext context)\n{\n\tif (context) (*context->destroy_context_func)(context);\n}\n\ngchar *sip_sec_make_signature(SipSecContext context, const gchar *message)\n{\n\tSipSecBuffer signature;\n\tgchar *signature_hex;\n\n\tif (!(*context->make_signature_func)(context, message, &signature)) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"ERROR: sip_sec_make_signature failed. Unable to sign message!\");\n\t\treturn NULL;\n\t}\n\tsignature_hex = buff_to_hex_str(signature.value, signature.length);\n\tg_free(signature.value);\n\treturn signature_hex;\n}\n\ngboolean sip_sec_verify_signature(SipSecContext context,\n\t\t\t\t  const gchar *message,\n\t\t\t\t  const gchar *signature_hex)\n{\n\tSipSecBuffer signature;\n\tgboolean res;\n\n\tSIPE_DEBUG_INFO(\"sip_sec_verify_signature: message is:%s signature to verify is:%s\",\n\t\t\tmessage ? message : \"\", signature_hex ? signature_hex : \"\");\n\n\tif (!message || !signature_hex)\n\t\treturn FALSE;\n\n\tsignature.length = hex_str_to_buff(signature_hex, &signature.value);\n\tres = (*context->verify_signature_func)(context, message, signature);\n\tg_free(signature.value);\n\treturn res;\n}\n\n/* Does authentication type require a password? */\ngboolean sip_sec_requires_password(guint authentication,\n\t\t\t\t   gboolean sso)\n{\n\t/* Map authentication type to module initialization hook & name */\n\tstatic sip_sec_password_func const auth_to_hook[] = {\n\t\tsip_sec_password__NONE,      /* SIPE_AUTHENTICATION_TYPE_UNSET     */\n\t\tsip_sec_password__Basic,     /* SIPE_AUTHENTICATION_TYPE_BASIC     */\n\t\tsip_sec_password__NTLM,      /* SIPE_AUTHENTICATION_TYPE_NTLM      */\n\t\tsip_sec_password__Kerberos,  /* SIPE_AUTHENTICATION_TYPE_KERBEROS  */\n\t\tsip_sec_password__Negotiate, /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */\n\t\tsip_sec_password__TLS_DSK,   /* SIPE_AUTHENTICATION_TYPE_TLS_DSK   */\n\t\tsip_sec_password__NONE,      /* SIPE_AUTHENTICATION_TYPE_AUTOMATIC */\n\t};\n\n\t/* If Single-Sign On is disabled then a password is required */\n\tif (!sso)\n\t\treturn(TRUE);\n\n\t/* Check if authentation method supports Single-Sign On */\n\treturn((*(auth_to_hook[authentication]))());\n}\n\n/* Initialize & Destroy */\nvoid sip_sec_init(void)\n{\n#if !defined(HAVE_GSSAPI_ONLY) && !defined(HAVE_SSPI)\n\tsip_sec_init__ntlm();\n#endif\n}\n\nvoid sip_sec_destroy(void)\n{\n#if !defined(HAVE_GSSAPI_ONLY) && !defined(HAVE_SSPI)\n\tsip_sec_destroy__ntlm();\n#endif\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sip-sec.h",
    "content": "/**\n * @file sip-sec.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2015 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2009 pier11 <pier11@operamail.com>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Opaque type definition for security context */\ntypedef struct sip_sec_context *SipSecContext;\n\n/*** Sipe convenience methods ***/\n\n/**\n * Initializes Sipe security context.\n * Obtains cashed initial credentials (TGT for Kerberos) or requests new ones if required.\n * In former case domain/username/password information is unnecessary.\n *\n * @param type     (in) authentication type\n * @param sso      (in) @c TRUE if Single Sign-On should be used\n * @param http     (in) @c TRUE if HTTP, @c FALSE for SIP\n * @param username (in) user name (can be NULL)    (ignored for SSO)\n * @param password (in) password (can be NULL)     (ignored for SSO)\n *\n * @return context security context to store and pass between security method invocations\n */\nSipSecContext\nsip_sec_create_context(guint type,\n\t\t       gboolean sso,\n\t\t       gboolean http,\n\t\t       const gchar *username,\n\t\t       const gchar *password);\n\n/**\n * Obtains Service ticket (for Kerberos), base64 encodes it and provide as output.\n *\n * @param context (in) security context to pass between security method invocations\n * @param target (in) security target. Service principal name on case of Kerberos.\n * @param input_toked_base64 (in) base64 encoded input security token. This is Type2 NTLM message or NULL.\n * @param output_toked_base64 (out) base64 encoded output token to send to server.\n * @param expires (out) security context expiration time in seconds.\n *\n * @return @c TRUE if successful\n *\n */\ngboolean\nsip_sec_init_context_step(SipSecContext context,\n\t\t\t  const gchar *target,\n\t\t\t  const gchar *input_toked_base64,\n\t\t\t  gchar **output_toked_base64,\n\t\t\t  guint *expires);\n\n/**\n * Check if the authentication of a security context is completed and it is\n * ready to be used for message signing and signature verification\n *\n * @param context (in) security context. May be @c NULL.\n *\n * @return @c TRUE if authentication is completed\n */\ngboolean sip_sec_context_is_ready(SipSecContext context);\n\n/**\n * Return authentication name of a security context\n *\n * @param context (in) security context. May be @c NULL.\n *\n * @return string or @c NULL\n */\nconst gchar *sip_sec_context_name(SipSecContext context);\n\n/**\n * Return type of a security context\n *\n * @param context (in) security context. May be @c NULL.\n *\n * @return context type or @c SIPE_SIPE_AUTHENTICATION_TYPE_UNSET\n */\nguint sip_sec_context_type(SipSecContext context);\n\n/**\n * A convenience method for sipe.\n * Destroys security context.\n *\n * @param context (in,out) security context to destroy\n */\nvoid sip_sec_destroy_context(SipSecContext context);\n\n/**\n * A convenience method for sipe.\n * Signs incoming message.\n *\n * @param context (in) security context\n * @param message (in) a message to sign.\n *\n * @return signature for the message. Converted to Hex null terminated string;\n */\ngchar *sip_sec_make_signature(SipSecContext context,\n\t\t\t      const gchar *message);\n\n/**\n * A convenience method for sipe.\n * Verifies signature for the message.\n *\n * @param context (in) security context\n * @param message (in) which signature to verify. Null terminated string.\n * @param signature_hex (in) signature to test in Hex representation. Null terminated string. Example: \"602306092A864886F71201020201011100FFFFFFFF1A306ACB7BE311827BBF7208D80D15E3\"\n *\n * @return FALSE on error\n */\ngboolean sip_sec_verify_signature(SipSecContext context,\n\t\t\t\t  const gchar *message,\n\t\t\t\t  const gchar *signature_hex);\n\n/**\n * Check if authentication scheme requires a password\n *\n * @param type authentication type\n * @param sso  TRUE if user selected Single-Sign On\n *\n * @return @c TRUE if password is required\n */\ngboolean sip_sec_requires_password(guint authentication,\n\t\t\t\t   gboolean sso);\n\n/**\n * Initialize & destroy functions for sip-sec.\n * Should be called on loading and unloading of the core.\n */\nvoid sip_sec_init(void);\nvoid sip_sec_destroy(void);\n"
  },
  {
    "path": "src/core/sip-soap.c",
    "content": "/**\n * @file sip-soap.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * SOAP requests over SIP SERVICE messages\n *\n * Specification references:\n *\n *   - [MS-SIP]:  http://msdn.microsoft.com/en-us/library/cc246115.aspx\n *   - [MS-PRES]: http://msdn.microsoft.com/en-us/library/cc431501.aspx\n *\n */\n\n#include <glib.h>\n\n#include \"sip-soap.h\"\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-utils.h\"\n\nvoid sip_soap_raw_request_cb(struct sipe_core_private *sipe_private,\n\t\t\t     const gchar *from,\n\t\t\t     const gchar *soap,\n\t\t\t     SoapTransCallback callback,\n\t\t\t     struct transaction_payload *payload)\n{\n\tgchar *contact = get_contact(sipe_private);\n\tgchar *hdr = g_strdup_printf(\"Contact: %s\\r\\n\"\n\t\t\t\t     \"Content-Type: application/SOAP+xml\\r\\n\",\n\t\t\t\t     contact);\n\n\tstruct transaction *trans = sip_transport_service(sipe_private,\n\t\t\t\t\t\t\t  from,\n\t\t\t\t\t\t\t  hdr,\n\t\t\t\t\t\t\t  soap,\n\t\t\t\t\t\t\t  callback);\n\tif (trans) {\n\t\ttrans->payload = payload;\n\t/* SIP transport is no longer valid - give up */\n\t} else if (payload) {\n\t\tif (payload->destroy)\n\t\t\t(payload->destroy)(payload->data);\n\t\tg_free(payload);\n\t}\n\n\tg_free(contact);\n\tg_free(hdr);\n}\n\n/**\n * delta_num != NULL: use user sip: URI as from, include deltanum and increment it\n * delta_num == NULL; use sip: URI generated from domain name as from\n */\nstatic void sip_soap_request_full(struct sipe_core_private *sipe_private,\n\t\t\t\t  const gchar *method,\n\t\t\t\t  const gchar *request,\n\t\t\t\t  const gchar *additional,\n\t\t\t\t  guint *deltanum,\n\t\t\t\t  SoapTransCallback callback,\n\t\t\t\t  struct transaction_payload *payload)\n{\n\tgchar *from = deltanum ?\n\t\tsip_uri_self(sipe_private) :\n\t\tsip_uri_from_name(sipe_private->public.sip_domain);\n\tgchar *delta = deltanum ?\n\t\tg_strdup_printf(\"<m:deltaNum>%d</m:deltaNum>\", (*deltanum)++) :\n\t\tg_strdup(\"\");\n\tgchar *soap = g_strdup_printf(\"<s:Envelope\"\n\t\t\t\t      \" xmlns:s=\\\"http://schemas.xmlsoap.org/soap/envelope/\\\"\"\n\t\t\t\t      \" xmlns:m=\\\"http://schemas.microsoft.com/winrtc/2002/11/sip\\\"\"\n\t\t\t\t      \">\"\n\t\t\t\t        \"<s:Body>\"\n\t\t\t\t          \"<m:%s>\"\n\t\t\t\t            \"%s\"\n\t\t\t\t            \"%s\"\n\t\t\t\t          \"</m:%s>\"\n\t\t\t\t          \"%s\"\n\t\t\t\t         \"</s:Body>\"\n\t\t\t\t      \"</s:Envelope>\",\n\t\t\t\t      method,\n\t\t\t\t      request,\n\t\t\t\t      delta,\n\t\t\t\t      method,\n\t\t\t\t      additional ? additional : \"\");\n\tsip_soap_raw_request_cb(sipe_private, from, soap, callback, payload);\n\tg_free(soap);\n\tg_free(delta);\n\tg_free(from);\n}\n\nvoid sip_soap_request_cb(struct sipe_core_private *sipe_private,\n\t\t\t const gchar *method,\n\t\t\t const gchar *request,\n\t\t\t SoapTransCallback callback,\n\t\t\t struct transaction_payload *payload)\n{\n\tsip_soap_request_full(sipe_private,\n\t\t\t      method,\n\t\t\t      request,\n\t\t\t      NULL,\n\t\t\t      &sipe_private->deltanum_contacts,\n\t\t\t      callback,\n\t\t\t      payload);\n}\n\nvoid sip_soap_request(struct sipe_core_private *sipe_private,\n\t\t      const gchar *method,\n\t\t      const gchar *request)\n{\n\tsip_soap_request_cb(sipe_private,\n\t\t\t    method,\n\t\t\t    request,\n\t\t\t    NULL,\n\t\t\t    NULL);\n}\n\n/* This is the only user of deltanum_acl */\nvoid sip_soap_ocs2005_setacl(struct sipe_core_private *sipe_private,\n\t\t\t     const gchar *who,\n\t\t\t     gboolean allow)\n{\n\tgchar *request = g_strdup_printf(\"<m:type>USER</m:type>\"\n\t\t\t\t\t \"<m:mask>%s</m:mask>\"\n\t\t\t\t\t \"<m:rights>%s</m:rights>\",\n\t\t\t\t\t who,\n\t\t\t\t\t allow ? \"AA\" : \"BD\");\n\tsip_soap_request_full(sipe_private,\n\t\t\t      \"setACE\",\n\t\t\t      request,\n\t\t\t      NULL,\n\t\t\t      &sipe_private->deltanum_acl,\n\t\t\t      NULL,\n\t\t\t      NULL);\n\tg_free(request);\n}\n\n/**\n * This request is special:\n * a) it is send from domain URI and not the users\n * b) it has XML nodes outside the [MS-PRES] method node\n * c) doesn't use deltaNum\n */\nvoid sip_soap_directory_search(struct sipe_core_private *sipe_private,\n\t\t\t       guint max,\n\t\t\t       const gchar *rows,\n\t\t\t       SoapTransCallback callback,\n\t\t\t       struct transaction_payload *payload)\n{\n\tgchar *request = g_strdup_printf(\"<m:filter m:href=\\\"#searchArray\\\"/>\"\n\t\t\t\t\t \"<m:maxResults>%d</m:maxResults>\",\n\t\t\t\t\t max);\n\tgchar *additional = g_strdup_printf(\"<m:Array m:id=\\\"searchArray\\\">\"\n\t\t\t\t\t      \"%s\"\n\t\t\t\t\t    \"</m:Array>\",\n\t\t\t\t\t    rows);\n\tsip_soap_request_full(sipe_private,\n\t\t\t      \"directorySearch\",\n\t\t\t      request,\n\t\t\t      additional,\n\t\t\t      NULL,\n\t\t\t      callback,\n\t\t\t      payload);\n\tg_free(additional);\n\tg_free(request);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sip-soap.h",
    "content": "/**\n * @file sip-soap.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipmsg;\nstruct sipe_core_private;\nstruct transaction;\nstruct transaction_payload;\n\n/* Must be the same as sip-transport.h/TransCallback */\ntypedef gboolean (*SoapTransCallback) (struct sipe_core_private *,\n\t\t\t\t       struct sipmsg *,\n\t\t\t\t       struct transaction *);\n\n/**\n * Send raw SOAP request with callback\n *\n * @param sipe_private SIPE core private data\n * @param from         URI to use for SIP transport\n * @param soap         SOAP XML string\n * @param callback     callback function (may be @c NULL)\n * @param payload      callback data     (may be @c NULL)\n */\nvoid sip_soap_raw_request_cb(struct sipe_core_private *sipe_private,\n\t\t\t     const gchar *from,\n\t\t\t     const gchar *soap,\n\t\t\t     SoapTransCallback callback,\n\t\t\t     struct transaction_payload *payload);\n\n/**\n * Send [MS-SIP] SOAP request with callback\n *\n * @param sipe_private SIPE core private data\n * @param method       [MS-PRES] method\n * @param request      [MS-PRES] request data\n * @param callback     callback function (may be @c NULL)\n * @param payload      callback data     (may be @c NULL)\n */\nvoid sip_soap_request_cb(struct sipe_core_private *sipe_private,\n\t\t\t const gchar *method,\n\t\t\t const gchar *request,\n\t\t\t SoapTransCallback callback,\n\t\t\t struct transaction_payload *payload);\n\n/**\n * Send [MS-SIP] SOAP request\n *\n * @param sipe_private SIPE core private data\n * @param method       [MS-PRES] method\n * @param request      [MS-PRES] request data\n */\nvoid sip_soap_request(struct sipe_core_private *sipe_private,\n\t\t      const gchar *method,\n\t\t      const gchar *request);\n\n/**\n * Send [MS-SIP] setACE (set ACL for contact) SOAP request (OCS2005)\n *\n * @param sipe_private SIPE core private data\n * @param who          sip: URI of the contact\n * @param allow        allow or deny\n */\nvoid sip_soap_ocs2005_setacl(struct sipe_core_private *sipe_private,\n\t\t\t     const gchar *who,\n\t\t\t     gboolean allow);\n\n/**\n * Send [MS-PRES] directorySearch SOAP request (OCS2007 and older)\n *\n * @param sipe_private SIPE core private data\n * @param max          maximum number of results to return\n * @param rows         XML m:row nodes to add to request\n * @param callback     callback function\n * @param payload      callback data     (may be @c NULL)\n */\nvoid sip_soap_directory_search(struct sipe_core_private *sipe_private,\n\t\t\t       guint max,\n\t\t\t       const gchar *rows,\n\t\t\t       SoapTransCallback callback,\n\t\t\t       struct transaction_payload *payload);\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sip-transport.c",
    "content": "/**\n * @file sip-transport.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/**\n * This module incapsulates SIP (RFC3261) protocol and provides\n * higher level API (a layer) to XML-based SIPE (SIP with Extensions).\n * Underlying leyer for this is TCP/SSL layer.\n *\n * A diagram in pseudographics:\n *\n * === SIPE (XML-based) layer ======================\n * === SIP RFC3261 transport layer (This module) ===\n * === TCP/SSL layer ===============================\n *\n * Authentication (Kerberos and NTLM) is applicable to this layer only.\n * The same with message integtity (signing). No sip-sec* code should\n * be used ourside of this module.\n *\n * SIP errors as codes(both as a return codes and network conditions) should be\n * escalated to higher leyer (SIPE). Network conditions include no response\n * within timeout interval.\n *\n * This module should support redirect internally. No escalations to higher\n * layers needed.\n *\n * NO SIP-messages (headers) composing and processing should be outside of\n * this module (!) Like headers: Via, Route, Contact, Authorization, etc.\n * It's all irrelevant to higher layer responsibilities.\n *\n * Specification references:\n *\n *   - [MS-SIPAE]: http://msdn.microsoft.com/en-us/library/cc431510.aspx\n *   - RFC2732:    http://www.ietf.org/rfc/rfc2732.txt\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n#include <stdio.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipmsg.h\"\n#include \"sip-sec.h\"\n#include \"sip-sec-digest.h\"\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-certificate.h\"\n#include \"sipe-dialog.h\"\n#include \"sipe-incoming.h\"\n#include \"sipe-lync-autodiscover.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-notify.h\"\n#include \"sipe-schedule.h\"\n#include \"sipe-sign.h\"\n#include \"sipe-subscriptions.h\"\n#include \"sipe-utils.h\"\n#include \"uuid.h\"\n\nstruct sip_auth {\n\tguint type;\n\tstruct sip_sec_context *gssapi_context;\n\tgchar *gssapi_data;\n\tgchar *opaque;\n\tconst gchar *protocol;\n\tgchar *realm;\n\tgchar *sts_uri;\n\tgchar *target;\n\tguint version;\n\tguint retries;\n\tguint ntlm_num;\n\tguint expires;\n\tgboolean can_retry;\n};\n\n/* sip-transport.c private data */\nstruct sip_transport {\n\tstruct sipe_transport_connection *connection;\n\n\tgchar *server_name;\n\tguint  server_port;\n\n\tgchar *epid;\n\t                             /* local IP address of transport socket   */\n\tgchar *ip_address;   \t     /* RAW X.X.X.X (IPv4),  X:X:...:X  (IPv6) */\n\tgchar *uri_address;   \t     /* URI X.X.X.X (IPv4), [X:X:...:X] (IPv6) */\n\tconst gchar *sdp_marker;     /* SDP address marker: \"IP4\" or \"IP6\"     */\n\n\tGSList *transactions;\n\n\tstruct sip_auth registrar;\n\tstruct sip_auth proxy;\n\n\tguint cseq;\n\tguint register_attempt;\n\n\tguint keepalive_timeout;\n\ttime_t last_message;\n\n\tgboolean processing_input;   /* whether full header received */\n\tgboolean auth_incomplete;    /* whether authentication not completed */\n\tgboolean auth_retry;         /* whether next authentication should be tried */\n\tgboolean reregister_set;     /* whether reregister timer set */\n\tgboolean reauthenticate_set; /* whether reauthenticate timer set */\n\tgboolean subscribed;         /* whether subscribed to events, except buddies presence */\n\tgboolean deregister;         /* whether in deregistration */\n};\n\n/* Keep in sync with sipe_transport_type! */\nstatic const char *transport_descriptor[] = { \"\", \"tls\", \"tcp\"};\n#define TRANSPORT_DESCRIPTOR (transport_descriptor[transport->connection->type])\n\nstatic char *genbranch()\n{\n\treturn g_strdup_printf(\"z9hG4bK%04X%04X%04X%04X%04X\",\n\t\trand() & 0xFFFF, rand() & 0xFFFF, rand() & 0xFFFF,\n\t\trand() & 0xFFFF, rand() & 0xFFFF);\n}\n\nstatic void sipe_auth_free(struct sip_auth *auth)\n{\n\tg_free(auth->opaque);\n\tauth->opaque = NULL;\n\tauth->protocol = NULL;\n\tg_free(auth->realm);\n\tauth->realm = NULL;\n\tg_free(auth->sts_uri);\n\tauth->sts_uri = NULL;\n\tg_free(auth->target);\n\tauth->target = NULL;\n\tauth->version = 0;\n\tauth->type = SIPE_AUTHENTICATION_TYPE_UNSET;\n\tauth->retries = 0;\n\tauth->expires = 0;\n\tauth->can_retry = FALSE;\n\tg_free(auth->gssapi_data);\n\tauth->gssapi_data = NULL;\n\tsip_sec_destroy_context(auth->gssapi_context);\n\tauth->gssapi_context = NULL;\n}\n\nstatic void sipe_make_signature(struct sipe_core_private *sipe_private,\n\t\t\t\tstruct sipmsg *msg)\n{\n\tstruct sip_transport *transport = sipe_private->transport;\n\tif (sip_sec_context_is_ready(transport->registrar.gssapi_context)) {\n\t\tstruct sipmsg_breakdown msgbd;\n\t\tgchar *signature_input_str;\n\t\tmsgbd.msg = msg;\n\t\tsipmsg_breakdown_parse(&msgbd, transport->registrar.realm, transport->registrar.target,\n\t\t\t\t       transport->registrar.protocol);\n\t\tmsgbd.rand = g_strdup_printf(\"%08x\", g_random_int());\n\t\ttransport->registrar.ntlm_num++;\n\t\tmsgbd.num = g_strdup_printf(\"%d\", transport->registrar.ntlm_num);\n\t\tsignature_input_str = sipmsg_breakdown_get_string(transport->registrar.version, &msgbd);\n\t\tif (signature_input_str != NULL) {\n\t\t\tchar *signature_hex = sip_sec_make_signature(transport->registrar.gssapi_context, signature_input_str);\n\t\t\tg_free(msg->signature);\n\t\t\tmsg->signature = signature_hex;\n\t\t\tg_free(msg->rand);\n\t\t\tmsg->rand = g_strdup(msgbd.rand);\n\t\t\tg_free(msg->num);\n\t\t\tmsg->num = g_strdup(msgbd.num);\n\t\t\tg_free(signature_input_str);\n\t\t}\n\t\tsipmsg_breakdown_free(&msgbd);\n\t}\n}\n\nstatic const gchar *const auth_type_to_protocol[] = {\n\tNULL,       /* SIPE_AUTHENTICATION_TYPE_UNSET     */\n\tNULL,       /* SIPE_AUTHENTICATION_TYPE_BASIC     */\n\t\"NTLM\",     /* SIPE_AUTHENTICATION_TYPE_NTLM      */\n\t\"Kerberos\", /* SIPE_AUTHENTICATION_TYPE_KERBEROS  */\n\tNULL,       /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */\n\t\"TLS-DSK\",  /* SIPE_AUTHENTICATION_TYPE_TLS_DSK   */\n\tNULL,       /* SIPE_AUTHENTICATION_TYPE_AUTOMATIC */\n};\n#define AUTH_PROTOCOLS (sizeof(auth_type_to_protocol)/sizeof(gchar *))\n\nstatic gchar *msg_signature_to_auth(struct sip_auth *auth,\n\t\t\t\t    struct sipmsg *msg)\n{\n\treturn(g_strdup_printf(\"%s qop=\\\"auth\\\", opaque=\\\"%s\\\", realm=\\\"%s\\\", targetname=\\\"%s\\\", crand=\\\"%s\\\", cnum=\\\"%s\\\", response=\\\"%s\\\"\",\n\t\t\t       auth->protocol,\n\t\t\t       auth->opaque, auth->realm, auth->target,\n\t\t\t       msg->rand, msg->num, msg->signature));\n}\n\nstatic gboolean auth_can_retry(struct sip_transport *transport,\n\t\t\t       const struct sip_auth *auth)\n{\n\t/* NTLM is the scheme with lowest priority - don't retry */\n\tgboolean retry =\n\t\tauth->can_retry &&\n\t\t(auth->type != SIPE_AUTHENTICATION_TYPE_NTLM);\n\tif (retry)\n\t\ttransport->auth_retry = TRUE;\n\treturn(retry);\n}\n\nstatic void initialize_auth_retry(struct sipe_core_private *sipe_private,\n\t\t\t\t  struct sip_auth *auth)\n{\n\tstruct sip_transport *transport = sipe_private->transport;\n\n\tif (auth_can_retry(transport, auth)) {\n\t\tif (auth->gssapi_context) {\n\t\t\t/* need to drop context for retry */\n\t\t\tsip_sec_destroy_context(auth->gssapi_context);\n\t\t\tauth->gssapi_context = NULL;\n\t\t}\n\t} else {\n\t\tsipe_backend_connection_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t      SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,\n\t\t\t\t\t      _(\"Failed to authenticate to server\"));\n\t}\n}\n\nstatic gchar *initialize_auth_context(struct sipe_core_private *sipe_private,\n\t\t\t\t      struct sip_auth *auth,\n\t\t\t\t      struct sipmsg *msg)\n{\n\tstruct sip_transport *transport = sipe_private->transport;\n\tgchar *ret;\n\tgchar *gssapi_data = NULL;\n\tgchar *sign_str;\n\tgchar *gssapi_str;\n\tgchar *opaque_str;\n\tgchar *version_str;\n\n\t/*\n\t * If transport is de-registering when we reach this point then we\n\t * are in the middle of the previous authentication context setup\n\t * attempt. So we shouldn't try another attempt.\n\t */\n\tif (transport->deregister)\n\t\treturn NULL;\n\n\t/* Create security context or handshake continuation? */\n\tif (auth->gssapi_context) {\n\t\t/* Perform next step in authentication handshake */\n\t\tgboolean status = sip_sec_init_context_step(auth->gssapi_context,\n\t\t\t\t\t\t\t    auth->target,\n\t\t\t\t\t\t\t    auth->gssapi_data,\n\t\t\t\t\t\t\t    &gssapi_data,\n\t\t\t\t\t\t\t    &auth->expires);\n\n\t\t/* If authentication is completed gssapi_data can be NULL */\n\t\tif (!(status &&\n\t\t      (sip_sec_context_is_ready(auth->gssapi_context) || gssapi_data))) {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"initialize_auth_context: security context continuation failed\");\n\t\t\tg_free(gssapi_data);\n\t\t\tinitialize_auth_retry(sipe_private, auth);\n\t\t\treturn NULL;\n\t\t}\n\n\t} else {\n\t\t/* Create security context */\n\t\tgpointer password = sipe_private->password;\n\n\t\t/* For TLS-DSK the \"password\" is a certificate */\n\t\tif (auth->type == SIPE_AUTHENTICATION_TYPE_TLS_DSK) {\n\t\t\tpassword = sipe_certificate_tls_dsk_find(sipe_private,\n\t\t\t\t\t\t\t\t auth->target);\n\n\t\t\tif (!password) {\n\t\t\t\tif (auth->sts_uri) {\n\t\t\t\t\tSIPE_DEBUG_INFO(\"initialize_auth_context: TLS-DSK Certificate Provisioning URI %s\",\n\t\t\t\t\t\t\tauth->sts_uri);\n\t\t\t\t\tif (!sipe_certificate_tls_dsk_generate(sipe_private,\n\t\t\t\t\t\t\t\t\t       auth->target,\n\t\t\t\t\t\t\t\t\t       auth->sts_uri)) {\n\t\t\t\t\t\tgchar *tmp = g_strdup_printf(_(\"Can't request certificate from %s\"),\n\t\t\t\t\t\t\t\t\t     auth->sts_uri);\n\t\t\t\t\t\tsipe_backend_connection_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\t      SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,\n\t\t\t\t\t\t\t\t\t      tmp);\n\t\t\t\t\t\tg_free(tmp);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tsipe_backend_connection_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t      SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,\n\t\t\t\t\t\t\t\t      _(\"No URI for certificate provisioning service provided\"));\n\t\t\t\t}\n\n\t\t\t\t/* we can't authenticate the message yet */\n\t\t\t\ttransport->auth_incomplete = TRUE;\n\n\t\t\t\treturn(NULL);\n\t\t\t} else {\n\t\t\t\tSIPE_DEBUG_INFO(\"initialize_auth_context: TLS-DSK certificate for target '%s' found.\",\n\t\t\t\t\t\tauth->target);\n\t\t\t}\n\t\t}\n\n\t\tauth->gssapi_context = sip_sec_create_context(auth->type,\n\t\t\t\t\t\t\t      SIPE_CORE_PRIVATE_FLAG_IS(SSO),\n\t\t\t\t\t\t\t      FALSE, /* connection-less for SIP */\n\t\t\t\t\t\t\t      sipe_private->authuser,\n\t\t\t\t\t\t\t      password);\n\n\t\tif (auth->gssapi_context) {\n\t\t\tsip_sec_init_context_step(auth->gssapi_context,\n\t\t\t\t\t\t  auth->target,\n\t\t\t\t\t\t  NULL,\n\t\t\t\t\t\t  &gssapi_data,\n\t\t\t\t\t\t  &(auth->expires));\n\t\t}\n\n\t\t/* if auth->gssapi_context is NULL then gssapi_data is still NULL */\n\t\tif (!gssapi_data) {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"initialize_auth_context: security context initialization failed\");\n\t\t\tinitialize_auth_retry(sipe_private, auth);\n\t\t\treturn NULL;\n\t\t}\n\t}\n\n\tif ((auth->version > 3) &&\n\t    sip_sec_context_is_ready(auth->gssapi_context)) {\n\t\tsipe_make_signature(sipe_private, msg);\n\t\tsign_str = g_strdup_printf(\", crand=\\\"%s\\\", cnum=\\\"%s\\\", response=\\\"%s\\\"\",\n\t\t\t\t\t   msg->rand, msg->num, msg->signature);\n\t} else {\n\t\tsign_str = g_strdup(\"\");\n\t}\n\n\tif (gssapi_data) {\n\t\tgssapi_str = g_strdup_printf(\", gssapi-data=\\\"%s\\\"\",\n\t\t\t\t\t     gssapi_data);\n\t\tg_free(gssapi_data);\n\t} else {\n\t\tgssapi_str = g_strdup(\"\");\n\t}\n\n\topaque_str = auth->opaque ? g_strdup_printf(\", opaque=\\\"%s\\\"\", auth->opaque) : g_strdup(\"\");\n\n\tif (auth->version > 2) {\n\t\tversion_str = g_strdup_printf(\", version=%d\", auth->version);\n\t} else {\n\t\tversion_str = g_strdup(\"\");\n\t}\n\n\tret = g_strdup_printf(\"%s qop=\\\"auth\\\"%s, realm=\\\"%s\\\", targetname=\\\"%s\\\"%s%s%s\",\n\t\t\t      auth->protocol, opaque_str,\n\t\t\t      auth->realm, auth->target,\n\t\t\t      gssapi_str, version_str, sign_str);\n\tg_free(version_str);\n\tg_free(opaque_str);\n\tg_free(gssapi_str);\n\tg_free(sign_str);\n\n\treturn(ret);\n}\n\nstatic gchar *auth_header(struct sipe_core_private *sipe_private,\n\t\t\t  struct sip_auth *auth,\n\t\t\t  struct sipmsg *msg)\n{\n\tgchar *ret = NULL;\n\n\t/*\n\t * If the message is already signed then we have an authentication\n\t * context, i.e. the authentication handshake is complete. Generate\n\t * authentication header from message signature.\n\t */\n\tif (msg->signature) {\n\t\tret = msg_signature_to_auth(auth, msg);\n\n\t/*\n\t * We should reach this point only when the authentication context\n\t * needs to be initialized.\n\t */\n\t} else {\n\t\tret = initialize_auth_context(sipe_private, auth, msg);\n\t}\n\n\treturn(ret);\n}\n\nstatic void fill_auth(const gchar *hdr, struct sip_auth *auth)\n{\n\tconst gchar *param;\n\n\t/* skip authentication identifier */\n\thdr = strchr(hdr, ' ');\n\tif (!hdr) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"fill_auth: corrupted authentication header\");\n\t\treturn;\n\t}\n\twhile (*hdr == ' ')\n\t\thdr++;\n\n\t/* start of next parameter value */\n\twhile ((param = strchr(hdr, '=')) != NULL) {\n\t\tconst gchar *end;\n\n\t\t/* parameter value type */\n\t\tparam++;\n\t\tif (*param == '\"') {\n\t\t\t/* string: xyz=\"...\"(,) */\n\t\t\tend = strchr(++param, '\"');\n\t\t\tif (!end) {\n\t\t\t\tSIPE_DEBUG_ERROR(\"fill_auth: corrupted string parameter near '%s'\", hdr);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\t/* number: xyz=12345(,) */\n\t\t\tend = strchr(param, ',');\n\t\t\tif (!end) {\n\t\t\t\t/* last parameter */\n\t\t\t\tend = param + strlen(param);\n\t\t\t}\n\t\t}\n\n#if 0\n\t\tSIPE_DEBUG_INFO(\"fill_auth: hdr   '%s'\", hdr);\n\t\tSIPE_DEBUG_INFO(\"fill_auth: param '%s'\", param);\n\t\tSIPE_DEBUG_INFO(\"fill_auth: end   '%s'\", end);\n#endif\n\n\t\t/* parameter type */\n\t\tif        (g_str_has_prefix(hdr, \"gssapi-data=\\\"\")) {\n\t\t\tg_free(auth->gssapi_data);\n\t\t\tauth->gssapi_data = g_strndup(param, end - param);\n\t\t} else if (g_str_has_prefix(hdr, \"opaque=\\\"\")) {\n\t\t\tg_free(auth->opaque);\n\t\t\tauth->opaque = g_strndup(param, end - param);\n\t\t} else if (g_str_has_prefix(hdr, \"realm=\\\"\")) {\n\t\t\tg_free(auth->realm);\n\t\t\tauth->realm = g_strndup(param, end - param);\n\t\t} else if (g_str_has_prefix(hdr, \"sts-uri=\\\"\")) {\n\t\t\t/* Only used with SIPE_AUTHENTICATION_TYPE_TLS_DSK */\n\t\t\tg_free(auth->sts_uri);\n\t\t\tauth->sts_uri = g_strndup(param, end - param);\n\t\t} else if (g_str_has_prefix(hdr, \"targetname=\\\"\")) {\n\t\t\tg_free(auth->target);\n\t\t\tauth->target = g_strndup(param, end - param);\n\t\t} else if (g_str_has_prefix(hdr, \"version=\")) {\n\t\t\tauth->version = atoi(param);\n\t\t}\n\n\t\t/* skip to next parameter */\n\t\twhile ((*end == '\"') || (*end == ',') || (*end == ' '))\n\t\t\tend++;\n\t\thdr = end;\n\t}\n\n\treturn;\n}\n\nstatic void sign_outgoing_message(struct sipe_core_private *sipe_private,\n\t\t\t\t  struct sipmsg *msg)\n{\n\tstruct sip_transport *transport = sipe_private->transport;\n\tgchar *buf;\n\n\tif (transport->registrar.type == SIPE_AUTHENTICATION_TYPE_UNSET) {\n\t\treturn;\n\t}\n\n\tsipe_make_signature(sipe_private, msg);\n\n\tbuf = auth_header(sipe_private, &transport->registrar, msg);\n\tif (buf) {\n\t\tsipmsg_add_header_now(msg, \"Authorization\", buf);\n\t\tg_free(buf);\n\t}\n}\n\n/*\n * NOTE: Do *NOT* call sipe_backend_transport_message(...) directly!\n *\n * All SIP messages must pass through this function in order to update\n * the timestamp for keepalive tracking.\n */\nstatic void send_sip_message(struct sip_transport *transport,\n\t\t\t     const gchar *string)\n{\n\tsipe_utils_message_debug(transport->connection, \"SIP\", string, NULL, TRUE);\n\ttransport->last_message = time(NULL);\n\tsipe_backend_transport_message(transport->connection, string);\n}\n\nstatic void start_keepalive_timer(struct sipe_core_private *sipe_private,\n\t\t\t\t  guint seconds);\nstatic void keepalive_timeout(struct sipe_core_private *sipe_private,\n\t\t\t      SIPE_UNUSED_PARAMETER gpointer data)\n{\n\tstruct sip_transport *transport = sipe_private->transport;\n\tif (transport) {\n\t\tguint since_last = time(NULL) - transport->last_message;\n\t\tguint restart    = transport->keepalive_timeout;\n\t\tif (since_last >= restart) {\n\t\t\tSIPE_DEBUG_INFO(\"keepalive_timeout: expired %d\", restart);\n\t\t\tsend_sip_message(transport, \"\\r\\n\\r\\n\");\n\t\t} else {\n\t\t\t/* timeout not reached since last message -> reschedule */\n\t\t\trestart -= since_last;\n\t\t}\n\t\tstart_keepalive_timer(sipe_private, restart);\n\t}\n}\n\nstatic void start_keepalive_timer(struct sipe_core_private *sipe_private,\n\t\t\t\t  guint seconds)\n{\n\tsipe_schedule_seconds(sipe_private,\n\t\t\t      \"<+keepalive-timeout>\",\n\t\t\t      NULL,\n\t\t\t      seconds,\n\t\t\t      keepalive_timeout,\n\t\t\t      NULL);\n}\n\nvoid sip_transport_response(struct sipe_core_private *sipe_private,\n\t\t\t    struct sipmsg *msg,\n\t\t\t    guint code,\n\t\t\t    const char *text,\n\t\t\t    const char *body)\n{\n\tgchar *name;\n\tgchar *value;\n\tGString *outstr = g_string_new(\"\");\n\tgchar *contact;\n\tGSList *tmp;\n\tstatic const gchar *keepers[] = { \"To\", \"From\", \"Call-ID\", \"CSeq\", \"Via\", \"Record-Route\", NULL };\n\n\t/* Can return NULL! */\n\tcontact = get_contact(sipe_private);\n\tif (contact) {\n\t\tsipmsg_add_header(msg, \"Contact\", contact);\n\t\tg_free(contact);\n\t}\n\n\tif (body) {\n\t\tgchar *len = g_strdup_printf(\"%\" G_GSIZE_FORMAT , (gsize) strlen(body));\n\t\tsipmsg_add_header(msg, \"Content-Length\", len);\n\t\tg_free(len);\n\t} else {\n\t\tsipmsg_add_header(msg, \"Content-Length\", \"0\");\n\t}\n\n\tsipmsg_add_header(msg, \"User-Agent\", sipe_core_user_agent(sipe_private));\n\n\tmsg->response = code;\n\n\tsipmsg_strip_headers(msg, keepers);\n\tsipmsg_merge_new_headers(msg);\n\tsign_outgoing_message(sipe_private, msg);\n\n\tg_string_append_printf(outstr, \"SIP/2.0 %d %s\\r\\n\", code, text);\n\ttmp = msg->headers;\n\twhile (tmp) {\n\t\tname = ((struct sipnameval*) (tmp->data))->name;\n\t\tvalue = ((struct sipnameval*) (tmp->data))->value;\n\n\t\tg_string_append_printf(outstr, \"%s: %s\\r\\n\", name, value);\n\t\ttmp = g_slist_next(tmp);\n\t}\n\tg_string_append_printf(outstr, \"\\r\\n%s\", body ? body : \"\");\n\tsend_sip_message(sipe_private->transport, outstr->str);\n\tg_string_free(outstr, TRUE);\n}\n\nstatic void transactions_remove(struct sipe_core_private *sipe_private,\n\t\t\t\tstruct transaction *trans)\n{\n\tstruct sip_transport *transport = sipe_private->transport;\n\tif (transport->transactions) {\n\t\ttransport->transactions = g_slist_remove(transport->transactions,\n\t\t\t\t\t\t\t trans);\n\t\tSIPE_DEBUG_INFO(\"SIP transactions count:%d after removal\", g_slist_length(transport->transactions));\n\n\t\tif (trans->msg) sipmsg_free(trans->msg);\n\t\tif (trans->payload) {\n\t\t\tif (trans->payload->destroy)\n\t\t\t\t(*trans->payload->destroy)(trans->payload->data);\n\t\t\tg_free(trans->payload);\n\t\t}\n\t\tg_free(trans->key);\n\t\tif (trans->timeout_key) {\n\t\t\tsipe_schedule_cancel(sipe_private, trans->timeout_key);\n\t\t\tg_free(trans->timeout_key);\n\t\t}\n\t\tg_free(trans);\n\t}\n}\n\nstatic struct transaction *transactions_find(struct sip_transport *transport,\n\t\t\t\t\t     struct sipmsg *msg)\n{\n\tGSList *transactions = transport->transactions;\n\tconst gchar *call_id = sipmsg_find_call_id_header(msg);\n\tconst gchar *cseq = sipmsg_find_cseq_header(msg);\n\tgchar *key;\n\n\tif (!call_id || !cseq) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"transaction_find: no Call-ID or CSeq!\");\n\t\treturn NULL;\n\t}\n\n\tkey = g_strdup_printf(\"<%s><%s>\", call_id, cseq);\n\twhile (transactions) {\n\t\tstruct transaction *trans = transactions->data;\n\t\tif (!g_ascii_strcasecmp(trans->key, key)) {\n\t\t\tg_free(key);\n\t\t\treturn trans;\n\t\t}\n\t\ttransactions = transactions->next;\n\t}\n\tg_free(key);\n\n\treturn NULL;\n}\n\nstatic void transaction_timeout_cb(struct sipe_core_private *sipe_private,\n\t\t\t\t   gpointer data)\n{\n\tstruct transaction *trans = data;\n\t(trans->timeout_callback)(sipe_private, trans->msg, trans);\n\ttransactions_remove(sipe_private, trans);\n}\n\nstruct transaction *sip_transport_request_timeout(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t  const gchar *method,\n\t\t\t\t\t\t  const gchar *url,\n\t\t\t\t\t\t  const gchar *to,\n\t\t\t\t\t\t  const gchar *addheaders,\n\t\t\t\t\t\t  const gchar *body,\n\t\t\t\t\t\t  struct sip_dialog *dialog,\n\t\t\t\t\t\t  TransCallback callback,\n\t\t\t\t\t\t  guint timeout,\n\t\t\t\t\t\t  TransCallback timeout_callback)\n{\n\tstruct sip_transport *transport = sipe_private->transport;\n\tchar *buf;\n\tstruct sipmsg *msg;\n\tgchar *ourtag     = dialog && dialog->ourtag    ? g_strdup(dialog->ourtag)    : NULL;\n\tgchar *theirtag   = dialog && dialog->theirtag  ? g_strdup(dialog->theirtag)  : NULL;\n\tgchar *theirepid  = dialog && dialog->theirepid ? g_strdup(dialog->theirepid) : NULL;\n\tgchar *callid     = dialog && dialog->callid    ? g_strdup(dialog->callid)    : gencallid();\n\tgchar *branch     = dialog && dialog->callid    ? NULL : genbranch();\n\tgchar *route      = g_strdup(\"\");\n\tconst gchar *epid = transport->epid;\n\tint cseq          = dialog ? ++dialog->cseq : 1 /* as Call-Id is new in this case */;\n\tstruct transaction *trans = NULL;\n\n\tif (dialog && dialog->routes)\n\t{\n\t\tGSList *iter = dialog->routes;\n\n\t\twhile(iter)\n\t\t{\n\t\t\tchar *tmp = route;\n\t\t\troute = g_strdup_printf(\"%sRoute: %s\\r\\n\", route, (char *)iter->data);\n\t\t\tg_free(tmp);\n\t\t\titer = g_slist_next(iter);\n\t\t}\n\t}\n\n\tif (!ourtag && !dialog) {\n\t\tourtag = gentag();\n\t}\n\n\tif (sipe_strequal(method, \"REGISTER\")) {\n\t\tif (sipe_private->register_callid) {\n\t\t\tg_free(callid);\n\t\t\tcallid = g_strdup(sipe_private->register_callid);\n\t\t} else {\n\t\t\tsipe_private->register_callid = g_strdup(callid);\n\t\t}\n\t\tcseq = ++transport->cseq;\n\t}\n\n\tbuf = g_strdup_printf(\"%s %s SIP/2.0\\r\\n\"\n\t\t\t\"Via: SIP/2.0/%s %s:%d%s%s\\r\\n\"\n\t\t\t\"From: <sip:%s>%s%s;epid=%s\\r\\n\"\n\t\t\t\"To: <%s>%s%s%s%s\\r\\n\"\n\t\t\t\"Max-Forwards: 70\\r\\n\"\n\t\t\t\"CSeq: %d %s\\r\\n\"\n\t\t\t\"User-Agent: %s\\r\\n\"\n\t\t\t\"Call-ID: %s\\r\\n\"\n\t\t\t\"%s%s\"\n\t\t\t\"Content-Length: %\" G_GSIZE_FORMAT \"\\r\\n\\r\\n%s\",\n\t\t\tmethod,\n\t\t\tdialog && dialog->request ? dialog->request : url,\n\t\t\tTRANSPORT_DESCRIPTOR,\n\t\t\ttransport->uri_address,\n\t\t\ttransport->connection->client_port,\n\t\t\tbranch ? \";branch=\" : \"\",\n\t\t\tbranch ? branch : \"\",\n\t\t\tsipe_private->username,\n\t\t\tourtag ? \";tag=\" : \"\",\n\t\t\tourtag ? ourtag : \"\",\n\t\t\tepid,\n\t\t\tto,\n\t\t\ttheirtag ? \";tag=\" : \"\",\n\t\t\ttheirtag ? theirtag : \"\",\n\t\t\ttheirepid ? \";epid=\" : \"\",\n\t\t\ttheirepid ? theirepid : \"\",\n\t\t\tcseq,\n\t\t\tmethod,\n\t\t\tsipe_core_user_agent(sipe_private),\n\t\t\tcallid,\n\t\t\troute,\n\t\t\taddheaders ? addheaders : \"\",\n\t\t\tbody ? (gsize) strlen(body) : 0,\n\t\t\tbody ? body : \"\");\n\n\n\t//printf (\"parsing msg buf:\\n%s\\n\\n\", buf);\n\tmsg = sipmsg_parse_msg(buf);\n\n\tg_free(buf);\n\tg_free(ourtag);\n\tg_free(theirtag);\n\tg_free(theirepid);\n\tg_free(branch);\n\tg_free(route);\n\n\tsign_outgoing_message(sipe_private, msg);\n\n\t/* The authentication scheme is not ready so we can't send the message.\n\t   This should only happen for REGISTER messages. */\n\tif (!transport->auth_incomplete) {\n\t\tbuf = sipmsg_to_string(msg);\n\n\t\t/* add to ongoing transactions */\n\t\t/* ACK isn't supposed to be answered ever. So we do not keep transaction for it. */\n\t\tif (!sipe_strequal(method, \"ACK\")) {\n\t\t\ttrans = g_new0(struct transaction, 1);\n\t\t\ttrans->callback = callback;\n\t\t\ttrans->msg = msg;\n\t\t\ttrans->key = g_strdup_printf(\"<%s><%d %s>\", callid, cseq, method);\n\t\t\tif (timeout_callback) {\n\t\t\t\ttrans->timeout_callback = timeout_callback;\n\t\t\t\ttrans->timeout_key = g_strdup_printf(\"<transaction timeout>%s\", trans->key);\n\t\t\t\tsipe_schedule_seconds(sipe_private,\n\t\t\t\t\t\t      trans->timeout_key,\n\t\t\t\t\t\t      trans,\n\t\t\t\t\t\t      timeout,\n\t\t\t\t\t\t      transaction_timeout_cb,\n\t\t\t\t\t\t      NULL);\n\t\t\t}\n\t\t\ttransport->transactions = g_slist_append(transport->transactions,\n\t\t\t\t\t\t\t\t trans);\n\t\t\tSIPE_DEBUG_INFO(\"SIP transactions count:%d after addition\", g_slist_length(transport->transactions));\n\t\t}\n\n\t\tsend_sip_message(transport, buf);\n\t\tg_free(buf);\n\t}\n\n\tif (!trans) sipmsg_free(msg);\n\tg_free(callid);\n\treturn trans;\n}\n\nstruct transaction *sip_transport_request(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  const gchar *method,\n\t\t\t\t\t  const gchar *url,\n\t\t\t\t\t  const gchar *to,\n\t\t\t\t\t  const gchar *addheaders,\n\t\t\t\t\t  const gchar *body,\n\t\t\t\t\t  struct sip_dialog *dialog,\n\t\t\t\t\t  TransCallback callback)\n{\n\treturn sip_transport_request_timeout(sipe_private,\n\t\t\t\t\t     method,\n\t\t\t\t\t     url,\n\t\t\t\t\t     to,\n\t\t\t\t\t     addheaders,\n\t\t\t\t\t     body,\n\t\t\t\t\t     dialog,\n\t\t\t\t\t     callback,\n\t\t\t\t\t     0,\n\t\t\t\t\t     NULL);\n}\n\nstatic void sip_transport_simple_request(struct sipe_core_private *sipe_private,\n\t\t\t\t\t const gchar *method,\n\t\t\t\t\t struct sip_dialog *dialog)\n{\n\tsip_transport_request(sipe_private,\n\t\t\t      method,\n\t\t\t      dialog->with,\n\t\t\t      dialog->with,\n\t\t\t      NULL,\n\t\t\t      NULL,\n\t\t\t      dialog,\n\t\t\t      NULL);\n}\n\nvoid sip_transport_ack(struct sipe_core_private *sipe_private,\n\t\t       struct sip_dialog *dialog)\n{\n\tsip_transport_simple_request(sipe_private, \"ACK\", dialog);\n}\n\nvoid sip_transport_bye(struct sipe_core_private *sipe_private,\n\t\t       struct sip_dialog *dialog)\n{\n\tsip_transport_simple_request(sipe_private, \"BYE\", dialog);\n}\n\nstruct transaction *sip_transport_info(struct sipe_core_private *sipe_private,\n\t\t\t\t       const gchar *addheaders,\n\t\t\t\t       const gchar *body,\n\t\t\t\t       struct sip_dialog *dialog,\n\t\t\t\t       TransCallback callback)\n{\n\treturn sip_transport_request(sipe_private,\n\t\t\t\t     \"INFO\",\n\t\t\t\t     dialog->with,\n\t\t\t\t     dialog->with,\n\t\t\t\t     addheaders,\n\t\t\t\t     body,\n\t\t\t\t     dialog,\n\t\t\t\t     callback);\n}\n\nstruct transaction *sip_transport_invite(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  const gchar *addheaders,\n\t\t\t\t\t  const gchar *body,\n\t\t\t\t\t  struct sip_dialog *dialog,\n\t\t\t\t\t  TransCallback callback)\n{\n\treturn sip_transport_request(sipe_private,\n\t\t\t\t     \"INVITE\",\n\t\t\t\t     dialog->with,\n\t\t\t\t     dialog->with,\n\t\t\t\t     addheaders,\n\t\t\t\t     body,\n\t\t\t\t     dialog,\n\t\t\t\t     callback);\n}\n\nstruct transaction *sip_transport_service(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  const gchar *uri,\n\t\t\t\t\t  const gchar *addheaders,\n\t\t\t\t\t  const gchar *body,\n\t\t\t\t\t  TransCallback callback)\n{\n\treturn sip_transport_request(sipe_private,\n\t\t\t\t     \"SERVICE\",\n\t\t\t\t     uri,\n\t\t\t\t     uri,\n\t\t\t\t     addheaders,\n\t\t\t\t     body,\n\t\t\t\t     NULL,\n\t\t\t\t     callback);\n}\n\nvoid sip_transport_subscribe(struct sipe_core_private *sipe_private,\n\t\t\t     const gchar *uri,\n\t\t\t     const gchar *addheaders,\n\t\t\t     const gchar *body,\n\t\t\t     struct sip_dialog *dialog,\n\t\t\t     TransCallback callback)\n{\n\tsip_transport_request(sipe_private,\n\t\t\t      \"SUBSCRIBE\",\n\t\t\t      uri,\n\t\t\t      uri,\n\t\t\t      addheaders,\n\t\t\t      body,\n\t\t\t      dialog,\n\t\t\t      callback);\n}\n\nvoid sip_transport_update(struct sipe_core_private *sipe_private,\n\t\t\t  struct sip_dialog *dialog,\n\t\t\t  TransCallback callback)\n{\n\tsip_transport_request(sipe_private,\n\t\t\t      \"UPDATE\",\n\t\t\t      dialog->with,\n\t\t\t      dialog->with,\n\t\t\t      NULL,\n\t\t\t      NULL,\n\t\t\t      dialog,\n\t\t\t      callback);\n}\n\nstatic const gchar *get_auth_header(struct sipe_core_private *sipe_private,\n\t\t\t\t    guint type,\n\t\t\t\t    struct sipmsg *msg)\n{\n\tstruct sip_auth *auth = &sipe_private->transport->registrar;\n\n\tauth->type     = type;\n\tauth->protocol = auth_type_to_protocol[auth->type];\n\n\treturn(sipmsg_find_auth_header(msg, auth->protocol));\n}\n\nstatic void do_register(struct sipe_core_private *sipe_private,\n\t\t\tgboolean deregister);\n\nstatic void do_reauthenticate_cb(struct sipe_core_private *sipe_private,\n\t\t\t\t SIPE_UNUSED_PARAMETER gpointer unused)\n{\n\tstruct sip_transport *transport = sipe_private->transport;\n\n\t/* register again when security token expires */\n\t/* we have to start a new authentication as the security token\n\t * is almost expired by sending a not signed REGISTER message */\n\tSIPE_LOG_INFO_NOFORMAT(\"do_reauthenticate_cb: do a full reauthentication\");\n\tsipe_auth_free(&transport->registrar);\n\tsipe_auth_free(&transport->proxy);\n\tsipe_schedule_cancel(sipe_private, \"<registration>\");\n\ttransport->auth_retry     = TRUE;\n\ttransport->reregister_set = FALSE;\n\ttransport->register_attempt = 0;\n\tdo_register(sipe_private, FALSE);\n\ttransport->reauthenticate_set = FALSE;\n}\n\nstatic void sip_transport_default_contact(struct sipe_core_private *sipe_private)\n{\n\tstruct sip_transport *transport = sipe_private->transport;\n\tsipe_private->contact = g_strdup_printf(\"<sip:%s:%d;maddr=%s;transport=%s>;proxy=replace\",\n\t\t\t\t\t\tsipe_private->username,\n\t\t\t\t\t\ttransport->connection->client_port,\n\t\t\t\t\t\ttransport->uri_address,\n\t\t\t\t\t\tTRANSPORT_DESCRIPTOR);\n}\n\nstatic void do_register_cb(struct sipe_core_private *sipe_private,\n\t\t\t   SIPE_UNUSED_PARAMETER void *unused)\n{\n\tdo_register(sipe_private, FALSE);\n}\n\nstatic void sip_transport_set_reregister(struct sipe_core_private *sipe_private,\n\t\t\t\t\t int expires)\n{\n\tsipe_schedule_seconds(sipe_private,\n\t\t\t      \"<registration>\",\n\t\t\t      NULL,\n\t\t\t      expires,\n\t\t\t      do_register_cb,\n\t\t\t      NULL);\n}\n\nstatic void sipe_server_register(struct sipe_core_private *sipe_private,\n\t\t\t\t guint type,\n\t\t\t\t gchar *server_name,\n\t\t\t\t guint server_port);\n\nstatic gboolean process_register_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  struct sipmsg *msg,\n\t\t\t\t\t  SIPE_UNUSED_PARAMETER struct transaction *trans)\n{\n\tstruct sip_transport *transport = sipe_private->transport;\n\tconst gchar *expires_header;\n\tint expires, i;\n        GSList *hdr = msg->headers;\n        struct sipnameval *elem;\n\n\texpires_header = sipmsg_find_expires_header(msg);\n\texpires = expires_header != NULL ? strtol(expires_header, NULL, 10) : 0;\n\tSIPE_DEBUG_INFO(\"process_register_response: got response to REGISTER; expires = %d\", expires);\n\n\tswitch (msg->response) {\n\t\tcase 200:\n\t\t\tif (expires) {\n\t\t\t\tconst gchar *contact_hdr;\n\t\t\t\tconst gchar *auth_hdr;\n\t\t\t\tgchar *gruu = NULL;\n\t\t\t\tgchar *uuid;\n\t\t\t\tgchar *timeout;\n\n\t\t\t\tif (!transport->reregister_set) {\n\t\t\t\t\t/* Schedule re-register 30 seconds before expiration */\n\t\t\t\t\tif (expires > 30)\n\t\t\t\t\t\texpires -= 30;\n\t\t\t\t\tsip_transport_set_reregister(sipe_private,\n\t\t\t\t\t\t\t\t     expires);\n\t\t\t\t\ttransport->reregister_set = TRUE;\n\t\t\t\t}\n\n\t\t\t\tauth_hdr = sipmsg_find_auth_header(msg,\n\t\t\t\t\t\t\t\t   transport->registrar.protocol);\n\t\t\t\tif (auth_hdr) {\n\t\t\t\t\tSIPE_DEBUG_INFO(\"process_register_response: Auth header: %s\", auth_hdr);\n\t\t\t\t\tfill_auth(auth_hdr, &transport->registrar);\n\t\t\t\t}\n\n\t\t\t\tif (!transport->reauthenticate_set) {\n\t\t\t\t\t/* [MS-SIPAE] Section 3.2.2 Timers\n\t\t\t\t\t *\n\t\t\t\t\t * When the ... authentication handshake completes\n\t\t\t\t\t * and the SA enters the \"established\" state, the\n\t\t\t\t\t * SIP protocol client MUST start an SA expiration\n\t\t\t\t\t * timer.\n\t\t\t\t\t * ...\n\t\t\t\t\t * The expiration timer value is the lesser of\n\t\t\t\t\t *\n\t\t\t\t\t *   - Kerberos: the service ticket expiry time\n\t\t\t\t\t *   - TLS-DSK:  the certificate expiration time\n\t\t\t\t\t *\n\t\t\t\t\t * and eight hours, further reduced by some buffer\n\t\t\t\t\t * time.\n\t\t\t\t\t * ...\n\t\t\t\t\t * The protocol client MUST choose a sufficient\n\t\t\t\t\t * buffer time to allow for the ... authentication\n\t\t\t\t\t * handshake that reestablishes the SA to complete\n\t\t\t\t\t * ... This value SHOULD be five (5) minutes or\n\t\t\t\t\t * longer.\n\t\t\t\t\t */\n\t\t\t\t\tguint reauth_timeout = transport->registrar.expires;\n\n\t\t\t\t\tSIPE_LOG_INFO_NOFORMAT(\"process_register_response: authentication handshake completed successfully\");\n\n\t\t\t\t\tif ((reauth_timeout == 0) ||\n\t\t\t\t\t    (reauth_timeout >  8 * 60 * 60))\n\t\t\t\t\t\treauth_timeout = 8 * 60 * 60;\n\t\t\t\t\tif (reauth_timeout > 5 * 60)\n\t\t\t\t\t\treauth_timeout -= 5 * 60;\n\n\t\t\t\t\tsipe_schedule_seconds(sipe_private,\n\t\t\t\t\t\t\t      \"<+reauthentication>\",\n\t\t\t\t\t\t\t      NULL,\n\t\t\t\t\t\t\t      reauth_timeout,\n\t\t\t\t\t\t\t      do_reauthenticate_cb,\n\t\t\t\t\t\t\t      NULL);\n\t\t\t\t\ttransport->reauthenticate_set = TRUE;\n\t\t\t\t}\n\n\t\t\t\tuuid = get_uuid(sipe_private);\n\n\t\t\t\t// There can be multiple Contact headers (one per location where the user is logged in) so\n\t\t\t\t// make sure to only get the one for this uuid\n\t\t\t\tfor (i = 0; (contact_hdr = sipmsg_find_header_instance (msg, \"Contact\", i)); i++) {\n\t\t\t\t\tgchar * valid_contact = sipmsg_find_part_of_header (contact_hdr, uuid, NULL, NULL);\n\t\t\t\t\tif (valid_contact) {\n\t\t\t\t\t\tgruu = sipmsg_find_part_of_header(contact_hdr, \"gruu=\\\"\", \"\\\"\", NULL);\n\t\t\t\t\t\t//SIPE_DEBUG_INFO(\"process_register_response: got gruu %s from contact hdr w/ right uuid: %s\", gruu, contact_hdr);\n\t\t\t\t\t\tg_free(valid_contact);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//SIPE_DEBUG_INFO(\"process_register_response: ignoring contact hdr b/c not right uuid: %s\", contact_hdr);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tg_free(uuid);\n\n\t\t\t\tg_free(sipe_private->contact);\n\t\t\t\tif(gruu) {\n\t\t\t\t\tsipe_private->contact = g_strdup_printf(\"<%s>\", gruu);\n\t\t\t\t\tg_free(gruu);\n\t\t\t\t} else {\n\t\t\t\t\t//SIPE_DEBUG_INFO_NOFORMAT(\"process_register_response: didn't find gruu in a Contact hdr\");\n\t\t\t\t\tsip_transport_default_contact(sipe_private);\n\t\t\t\t}\n                                SIPE_CORE_PRIVATE_FLAG_UNSET(OCS2007);\n\t\t\t\tSIPE_CORE_PRIVATE_FLAG_UNSET(REMOTE_USER);\n\t\t\t\tSIPE_CORE_PRIVATE_FLAG_UNSET(BATCHED_SUPPORT);\n\t\t\t\tSIPE_CORE_PRIVATE_FLAG_UNSET(SFB);\n\n                                while(hdr)\n                                {\n\t\t\t\t\telem = hdr->data;\n\t\t\t\t\tif (sipe_strcase_equal(elem->name, \"Supported\")) {\n\t\t\t\t\t\tif (sipe_strcase_equal(elem->value, \"msrtc-event-categories\")) {\n\t\t\t\t\t\t\t/* We interpret this as OCS2007+ indicator */\n\t\t\t\t\t\t\tSIPE_CORE_PRIVATE_FLAG_SET(OCS2007);\n\t\t\t\t\t\t\tSIPE_LOG_INFO(\"process_register_response: Supported: %s (indicates OCS2007+)\", elem->value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (sipe_strcase_equal(elem->value, \"adhoclist\")) {\n\t\t\t\t\t\t\tSIPE_CORE_PRIVATE_FLAG_SET(BATCHED_SUPPORT);\n\t\t\t\t\t\t\tSIPE_DEBUG_INFO(\"process_register_response: Supported: %s\", elem->value);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (sipe_strcase_equal(elem->name, \"Allow-Events\")){\n\t\t\t\t\t\tgchar **caps = g_strsplit(elem->value,\",\",0);\n\t\t\t\t\t\ti = 0;\n\t\t\t\t\t\twhile (caps[i]) {\n\t\t\t\t\t\t\tsipe_private->allowed_events =  g_slist_append(sipe_private->allowed_events, g_strdup(caps[i]));\n\t\t\t\t\t\t\tSIPE_DEBUG_INFO(\"process_register_response: Allow-Events: %s\", caps[i]);\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tg_strfreev(caps);\n                                        } else if (sipe_strcase_equal(elem->name, \"ms-user-logon-data\")) {\n\t\t\t\t\t\tif (sipe_strcase_equal(elem->value, \"RemoteUser\")) {\n\t\t\t\t\t\t\tSIPE_CORE_PRIVATE_FLAG_SET(REMOTE_USER);\n\t\t\t\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_register_response: ms-user-logon-data: RemoteUser (connected \"\n\t\t\t\t\t\t\t\t\t\t \"via Edge Server)\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (sipe_strcase_equal(elem->name, \"Server\")) {\n\t\t\t\t\t\t/* Server string has format like 'RTC/6.0'.\n\t\t\t\t\t\t * We want to check the first digit. */\n\t\t\t\t\t\tgchar **parts = g_strsplit_set(elem->value, \"/.\", 3);\n\t\t\t\t\t\tif (g_strv_length(parts) > 1) {\n\t\t\t\t\t\t\tguint version = atoi(parts[1]);\n\t\t\t\t\t\t\tif (version >= 6) {\n\t\t\t\t\t\t\t\tSIPE_CORE_PRIVATE_FLAG_SET(SFB);\n\t\t\t\t\t\t\t\tSIPE_LOG_INFO(\"process_register_response: server version is %d >= 6 (indicates Skype for Business+)\", version);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tg_strfreev(parts);\n\t\t\t\t\t}\n                                        hdr = g_slist_next(hdr);\n                                }\n\n\t\t\t\tsipe_backend_connection_completed(SIPE_CORE_PUBLIC);\n\n\t\t\t\t/* rejoin open chats to be able to use them by continue to send messages */\n\t\t\t\tsipe_backend_chat_rejoin_all(SIPE_CORE_PUBLIC);\n\n\t\t\t\t/* subscriptions, done only once */\n\t\t\t\tif (!transport->subscribed) {\n\t\t\t\t\tsipe_subscription_self_events(sipe_private);\n\t\t\t\t\ttransport->subscribed = TRUE;\n\t\t\t\t}\n\n\t\t\t\ttimeout = sipmsg_find_part_of_header(sipmsg_find_header(msg, \"ms-keep-alive\"),\n\t\t\t\t\t\t\t\t     \"timeout=\", \";\", NULL);\n\t\t\t\tif (timeout != NULL) {\n\t\t\t\t\tsscanf(timeout, \"%u\", &transport->keepalive_timeout);\n\t\t\t\t\tSIPE_DEBUG_INFO(\"process_register_response: server determined keep alive timeout is %u seconds\",\n\t\t\t\t\t\t\ttransport->keepalive_timeout);\n\t\t\t\t\tg_free(timeout);\n\t\t\t\t}\n\n\t\t\t\tSIPE_DEBUG_INFO(\"process_register_response: got 200, removing CSeq: %d\", transport->cseq);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 301:\n\t\t\t{\n\t\t\t\tgchar *redirect = sipmsg_parse_contact_address(msg);\n\n\t\t\t\tSIPE_LOG_INFO_NOFORMAT(\"process_register_response: authentication handshake completed successfully (with redirect)\");\n\n\t\t\t\tif (redirect && (g_ascii_strncasecmp(\"sip:\", redirect, 4) == 0)) {\n\t\t\t\t\tgchar **parts = g_strsplit(redirect + 4, \";\", 0);\n\t\t\t\t\tgchar **tmp;\n\t\t\t\t\tgchar *hostname;\n\t\t\t\t\tint port = 0;\n\t\t\t\t\tguint transport_type = SIPE_TRANSPORT_TLS;\n\t\t\t\t\tint i = 1;\n\n\t\t\t\t\ttmp = g_strsplit(parts[0], \":\", 0);\n\t\t\t\t\thostname = g_strdup(tmp[0]);\n\t\t\t\t\tif (tmp[1]) port = strtoul(tmp[1], NULL, 10);\n\t\t\t\t\tg_strfreev(tmp);\n\n\t\t\t\t\twhile (parts[i]) {\n\t\t\t\t\t\ttmp = g_strsplit(parts[i], \"=\", 0);\n\t\t\t\t\t\tif (tmp[1]) {\n\t\t\t\t\t\t\tif (g_ascii_strcasecmp(\"transport\", tmp[0]) == 0) {\n\t\t\t\t\t\t\t\tif (g_ascii_strcasecmp(\"tcp\", tmp[1]) == 0) {\n\t\t\t\t\t\t\t\t\ttransport_type = SIPE_TRANSPORT_TCP;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tg_strfreev(tmp);\n\t\t\t\t\t\ti++;\n\t\t\t\t\t}\n\t\t\t\t\tg_strfreev(parts);\n\n\t\t\t\t\t/* Close old connection */\n\t\t\t\t\tsipe_core_connection_cleanup(sipe_private);\n\t\t\t\t\t/* transport and sipe_private->transport are invalid after this */\n\n\t\t\t\t\t/* Create new connection */\n\t\t\t\t\tsipe_server_register(sipe_private, transport_type, hostname, port);\n\t\t\t\t\t/* sipe_private->transport has a new value */\n\t\t\t\t\tSIPE_DEBUG_INFO(\"process_register_response: redirected to host %s port %d transport %d\",\n\t\t\t\t\t\t\thostname, port, transport_type);\n\t\t\t\t}\n\t\t\t\tg_free(redirect);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 401:\n\t\t        {\n\t\t\t\tconst char *auth_hdr = NULL;\n\n\t\t\t\tSIPE_DEBUG_INFO(\"process_register_response: REGISTER retries %d\", transport->registrar.retries);\n\n\t\t\t\tif (transport->reauthenticate_set) {\n\t\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"process_register_response: RE-REGISTER rejected, triggering re-authentication\");\n\t\t\t\t\tdo_reauthenticate_cb(sipe_private, NULL);\n\t\t\t\t\treturn TRUE;\n\t\t\t\t}\n\n\t\t\t\tif (sip_sec_context_is_ready(transport->registrar.gssapi_context)) {\n\t\t\t\t\tstruct sip_auth *auth = &transport->registrar;\n\n\t\t\t\t\t/* NTLM is the scheme with lowest priority - don't retry */\n\t\t\t\t\tif (auth_can_retry(transport, auth)) {\n\t\t\t\t\t\tguint failed = auth->type;\n\t\t\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_register_response: authentication handshake failed - trying next authentication scheme.\");\n\t\t\t\t\t\tsipe_auth_free(auth);\n\t\t\t\t\t\tauth->type = failed;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSIPE_LOG_ERROR_NOFORMAT(\"process_register_response: authentication handshake failed - giving up.\");\n\t\t\t\t\t\tsipe_backend_connection_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\t      SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,\n\t\t\t\t\t\t\t\t\t      _(\"Authentication failed\"));\n\t\t\t\t\t\treturn TRUE;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (sipe_private->authentication_type == SIPE_AUTHENTICATION_TYPE_AUTOMATIC) {\n\t\t\t\t\tstruct sip_auth *auth = &transport->registrar;\n\t\t\t\t\tguint try             = auth->type;\n\n\t\t\t\t\twhile (!auth_hdr) {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t * Determine next authentication\n\t\t\t\t\t\t * scheme in priority order\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (transport->auth_retry)\n\t\t\t\t\t\t\tswitch (try) {\n\t\t\t\t\t\t\tcase SIPE_AUTHENTICATION_TYPE_UNSET:\n\t\t\t\t\t\t\t\ttry = SIPE_AUTHENTICATION_TYPE_TLS_DSK;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase SIPE_AUTHENTICATION_TYPE_TLS_DSK:\n#if defined(HAVE_GSSAPI_GSSAPI_H) || defined(HAVE_SSPI)\n\t\t\t\t\t\t\t\ttry = SIPE_AUTHENTICATION_TYPE_KERBEROS;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase SIPE_AUTHENTICATION_TYPE_KERBEROS:\n#endif\n\t\t\t\t\t\t\t\ttry = SIPE_AUTHENTICATION_TYPE_NTLM;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\ttry = SIPE_AUTHENTICATION_TYPE_UNSET;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\tauth->can_retry = (try != SIPE_AUTHENTICATION_TYPE_UNSET);\n\n\t\t\t\t\t\tif (!auth->can_retry) {\n\t\t\t\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_register_response: no more authentication schemes to try\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tauth_hdr = get_auth_header(sipe_private,\n\t\t\t\t\t\t\t\t\t   try,\n\t\t\t\t\t\t\t\t\t   msg);\n\t\t\t\t\t}\n\n\t\t\t\t\ttransport->auth_retry = FALSE;\n\n\t\t\t\t} else\n\t\t\t\t\tauth_hdr = get_auth_header(sipe_private,\n\t\t\t\t\t\t\t\t   sipe_private->authentication_type,\n\t\t\t\t\t\t\t\t   msg);\n\n\t\t\t\tif (!auth_hdr) {\n\t\t\t\t\tsipe_backend_connection_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t      SIPE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,\n\t\t\t\t\t\t\t\t      _(\"Incompatible authentication scheme chosen\"));\n\t\t\t\t\treturn TRUE;\n\t\t\t\t}\n\t\t\t\tSIPE_DEBUG_INFO(\"process_register_response: Auth header: %s\", auth_hdr);\n\t\t\t\tfill_auth(auth_hdr, &transport->registrar);\n\t\t\t\ttransport->reregister_set = FALSE;\n\t\t\t\ttransport->register_attempt = 0;\n\t\t\t\tdo_register(sipe_private,\n\t\t\t\t\t    sipe_backend_connection_is_disconnecting(SIPE_CORE_PUBLIC));\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 403:\n\t\t\t{\n\t\t\t\tgchar *reason;\n\t\t\t\tgchar *warning;\n\t\t\t\tsipmsg_parse_warning(msg, &reason);\n\t\t\t\treason = reason ? reason : sipmsg_get_ms_diagnostics_public_reason(msg);\n\t\t\t\twarning = g_strdup_printf(_(\"You have been rejected by the server: %s\"),\n\t\t\t\t\t\t\t  reason ? reason : _(\"no reason given\"));\n\t\t\t\tg_free(reason);\n\n\t\t\t\tsipe_backend_connection_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t      SIPE_CONNECTION_ERROR_INVALID_SETTINGS,\n\t\t\t\t\t\t\t      warning);\n\t\t\t\tg_free(warning);\n\t\t\t\treturn TRUE;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 404:\n\t\t\t{\n\t\t\t\tconst gchar *diagnostics = sipmsg_find_header(msg, \"ms-diagnostics\");\n\t\t\t\tgchar *reason = sipmsg_get_ms_diagnostics_reason(msg);\n\t\t\t\tgchar *warning;\n\t\t\t\twarning = g_strdup_printf(_(\"Not found: %s. Please contact your Administrator\"),\n\t\t\t\t\t\t\t  diagnostics ? (reason ? reason : _(\"no reason given\")) :\n\t\t\t\t\t\t\t  _(\"SIP is either not enabled for the destination URI or it does not exist\"));\n\t\t\t\tg_free(reason);\n\n\t\t\t\tsipe_backend_connection_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t      SIPE_CONNECTION_ERROR_INVALID_USERNAME,\n\t\t\t\t\t\t\t      warning);\n\t\t\t\tg_free(warning);\n\t\t\t\treturn TRUE;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 504: /* Server time-out */\n\t\t\t/* first attempt + 5 retries */\n\t\t\tif (transport->register_attempt < 6) {\n\t\t\t\tSIPE_DEBUG_INFO(\"process_register_response: RE-REGISTER timeout on attempt %d, retrying later\",\n\t\t\t\t\t\ttransport->register_attempt);\n\t\t\t\tsip_transport_set_reregister(sipe_private, 60);\n\t\t\t\treturn TRUE;\n\t\t\t}\n\t\t\t/* FALLTHROUGH */\n                case 503:\n                        {\n\t\t\t\tgchar *reason = sipmsg_get_ms_diagnostics_reason(msg);\n\t\t\t\tgchar *warning;\n\t\t\t\twarning = g_strdup_printf(_(\"Service unavailable: %s\"), reason ? reason : _(\"no reason given\"));\n\t\t\t\tg_free(reason);\n\n\t\t\t\tsipe_backend_connection_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t      SIPE_CONNECTION_ERROR_NETWORK,\n\t\t\t\t\t\t\t      warning);\n\t\t\t\tg_free(warning);\n\t\t\t\treturn TRUE;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\treturn TRUE;\n}\n\nstatic gboolean register_response_timeout(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  SIPE_UNUSED_PARAMETER struct sipmsg *msg,\n\t\t\t\t\t  SIPE_UNUSED_PARAMETER struct transaction *trans)\n{\n\tstruct sip_transport *transport = sipe_private->transport;\n\tif (transport->register_attempt < 6) {\n\t\tSIPE_DEBUG_INFO(\"register_response_timeout: no answer to attempt %d, retrying\",\n\t\t\t\ttransport->register_attempt);\n\t\tdo_register(sipe_private, FALSE);\n\t} else {\n\t\tgchar *warning = g_strdup_printf(_(\"Service unavailable: %s\"), _(\"no reason given\"));\n\t\tsipe_backend_connection_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t      SIPE_CONNECTION_ERROR_NETWORK,\n\t\t\t\t\t      warning);\n\t\tg_free(warning);\n\t}\n\treturn TRUE;\n}\n\nstatic void do_register(struct sipe_core_private *sipe_private,\n\t\t\tgboolean deregister)\n{\n\tstruct sip_transport *transport = sipe_private->transport;\n\tchar *uri;\n\tchar *to;\n\tchar *hdr;\n\tchar *uuid;\n\n\tif (!sipe_private->public.sip_domain) return;\n\n\tif (!deregister) {\n\t\tif (transport->reregister_set) {\n\t\t\ttransport->reregister_set = FALSE;\n\t\t\ttransport->register_attempt = 1;\n\t\t} else {\n\t\t\ttransport->register_attempt++;\n\t\t}\n\t}\n\n\ttransport->deregister      = deregister;\n\ttransport->auth_incomplete = FALSE;\n\n\tuuid = get_uuid(sipe_private);\n\thdr = g_strdup_printf(\"Contact: <sip:%s:%d;transport=%s;ms-opaque=d3470f2e1d>;methods=\\\"INVITE, MESSAGE, INFO, SUBSCRIBE, OPTIONS, BYE, CANCEL, NOTIFY, ACK, REFER, BENOTIFY\\\";proxy=replace;+sip.instance=\\\"<urn:uuid:%s>\\\"\\r\\n\"\n\t\t\t\t    \"Supported: gruu-10, adhoclist, msrtc-event-categories, com.microsoft.msrtc.presence\\r\\n\"\n\t\t\t\t    \"Event: registration\\r\\n\"\n\t\t\t\t    \"Allow-Events: presence\\r\\n\"\n\t\t\t\t    \"ms-keep-alive: UAC;hop-hop=yes\\r\\n\"\n\t\t\t\t    \"%s\",\n\t\t\t      transport->uri_address,\n\t\t\t      transport->connection->client_port,\n\t\t\t      TRANSPORT_DESCRIPTOR,\n\t\t\t      uuid,\n\t\t\t      deregister ? \"Expires: 0\\r\\n\" : \"\");\n\tg_free(uuid);\n\n\turi = sip_uri_from_name(sipe_private->public.sip_domain);\n\tto = sip_uri_self(sipe_private);\n\tsip_transport_request_timeout(sipe_private,\n\t\t\t\t      \"REGISTER\",\n\t\t\t\t      uri,\n\t\t\t\t      to,\n\t\t\t\t      hdr,\n\t\t\t\t      \"\",\n\t\t\t\t      NULL,\n\t\t\t\t      process_register_response,\n\t\t\t\t      60,\n\t\t\t\t      deregister ? NULL : register_response_timeout);\n\tg_free(to);\n\tg_free(uri);\n\tg_free(hdr);\n\n\tif (deregister) {\n\t\t/* Make sure that all messages are pushed to the server\n\t\t   before the connection gets shut down */\n\t\tSIPE_LOG_INFO_NOFORMAT(\"De-register from server. Flushing outstanding messages.\");\n\t\tsipe_backend_transport_flush(transport->connection);\n\t}\n}\n\nvoid sip_transport_deregister(struct sipe_core_private *sipe_private)\n{\n\tdo_register(sipe_private, TRUE);\n}\n\nvoid sip_transport_drop(struct sipe_core_private *sipe_private)\n{\n\tstruct sip_transport *transport = sipe_private->transport;\n\n\t/* transport can be NULL during connection setup */\n\tif (transport) {\n\t\tSIPE_LOG_INFO(\"sip_transport_drop: '%s:%u'(%p)\",\n\t\t\t      transport->server_name,\n\t\t\t      transport->server_port,\n\t\t\t      transport->connection);\n\n\t\tsipe_backend_transport_disconnect(transport->connection);\n\n\t\tsipe_auth_free(&transport->registrar);\n\t\tsipe_auth_free(&transport->proxy);\n\n\t\tg_free(transport->server_name);\n\t\tg_free(transport->uri_address);\n\t\tg_free(transport->ip_address);\n\t\tg_free(transport->epid);\n\n\t\twhile (transport->transactions)\n\t\t\ttransactions_remove(sipe_private,\n\t\t\t\t\t    transport->transactions->data);\n\n\t\tg_free(transport);\n\t}\n\n\tsipe_private->transport    = NULL;\n\tsipe_private->service_data = NULL;\n\tsipe_private->address_data = NULL;\n\n\tsipe_schedule_cancel(sipe_private, \"<+keepalive-timeout>\");\n\n\tif (sipe_private->dns_query)\n\t\tsipe_backend_dns_query_cancel(sipe_private->dns_query);\n\n}\n\nvoid sip_transport_authentication_completed(struct sipe_core_private *sipe_private)\n{\n\tdo_reauthenticate_cb(sipe_private, NULL);\n}\n\nguint sip_transport_port(struct sipe_core_private *sipe_private)\n{\n\treturn sipe_private->transport->server_port;\n}\n\nstatic void process_input_message(struct sipe_core_private *sipe_private,\n\t\t\t\t  struct sipmsg *msg)\n{\n\tstruct sip_transport *transport = sipe_private->transport;\n\tgboolean notfound = FALSE;\n\tconst char *method = msg->method ? msg->method : \"NOT FOUND\";\n\n\tSIPE_DEBUG_INFO(\"process_input_message: msg->response(%d),msg->method(%s)\",\n\t\t\tmsg->response, method);\n\n\tif (msg->response == 0) { /* request */\n\t\tif (sipe_strequal(method, \"MESSAGE\")) {\n\t\t\tprocess_incoming_message(sipe_private, msg);\n\t\t} else if (sipe_strequal(method, \"NOTIFY\")) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"send->process_incoming_notify\");\n\t\t\tprocess_incoming_notify(sipe_private, msg);\n\t\t\tsip_transport_response(sipe_private, msg, 200, \"OK\", NULL);\n\t\t} else if (sipe_strequal(method, \"BENOTIFY\")) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"send->process_incoming_benotify\");\n\t\t\tprocess_incoming_notify(sipe_private, msg);\n\t\t} else if (sipe_strequal(method, \"INVITE\")) {\n\t\t\tprocess_incoming_invite(sipe_private, msg);\n\t\t} else if (sipe_strequal(method, \"REFER\")) {\n\t\t\tprocess_incoming_refer(sipe_private, msg);\n\t\t} else if (sipe_strequal(method, \"OPTIONS\")) {\n\t\t\tprocess_incoming_options(sipe_private, msg);\n\t\t} else if (sipe_strequal(method, \"INFO\")) {\n\t\t\tprocess_incoming_info(sipe_private, msg);\n\t\t} else if (sipe_strequal(method, \"ACK\")) {\n\t\t\t/* ACK's don't need any response */\n\t\t} else if (sipe_strequal(method, \"PRACK\")) {\n\t\t\tsip_transport_response(sipe_private, msg, 200, \"OK\", NULL);\n\t\t} else if (sipe_strequal(method, \"SUBSCRIBE\")) {\n\t\t\t/* LCS 2005 sends us these - just respond 200 OK */\n\t\t\tsip_transport_response(sipe_private, msg, 200, \"OK\", NULL);\n\t\t} else if (sipe_strequal(method, \"CANCEL\")) {\n\t\t\tprocess_incoming_cancel(sipe_private, msg);\n\t\t} else if (sipe_strequal(method, \"BYE\")) {\n\t\t\tprocess_incoming_bye(sipe_private, msg);\n\t\t} else {\n\t\t\tsip_transport_response(sipe_private, msg, 501, \"Not implemented\", NULL);\n\t\t\tnotfound = TRUE;\n\t\t}\n\n\t} else { /* response */\n\t\tstruct transaction *trans = transactions_find(transport, msg);\n\t\tif (trans) {\n\t\t\tif (msg->response < 200) {\n\t\t\t\t/* ignore provisional response */\n\t\t\t\tSIPE_DEBUG_INFO(\"process_input_message: got provisional (%d) response, ignoring\", msg->response);\n\n\t\t\t\t/* Transaction not yet completed */\n\t\t\t\ttrans = NULL;\n\n\t\t\t} else if (msg->response == 401) { /* Unauthorized */\n\n\t\t\t\tif (sipe_strequal(trans->msg->method, \"REGISTER\")) {\n\t\t\t\t\t/* Expected response during authentication handshake */\n\t\t\t\t\ttransport->registrar.retries++;\n\t\t\t\t\tSIPE_DEBUG_INFO(\"process_input_message: RE-REGISTER CSeq: %d\", transport->cseq);\n\t\t\t\t} else {\n\t\t\t\t\tgchar *resend;\n\n\t\t\t\t\t/* Are we registered? */\n\t\t\t\t\tif (transport->reregister_set) {\n\t\t\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_input_message: 401 response to non-REGISTER message. Retrying with new authentication.\");\n\t\t\t\t\t\tsipmsg_remove_header_now(trans->msg, \"Authorization\");\n\t\t\t\t\t\tsign_outgoing_message(sipe_private,\n\t\t\t\t\t\t\t\t      trans->msg);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * We don't have a valid authentication at the moment.\n\t\t\t\t\t\t * Resend message unchanged. It will be rejected again\n\t\t\t\t\t\t * and hopefully by then we have a valid authentication.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_input_message: 401 response to non-REGISTER message. Bouncing...\");\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Resend request */\n\t\t\t\t\tresend = sipmsg_to_string(trans->msg);\n\t\t\t\t\tsend_sip_message(sipe_private->transport, resend);\n\t\t\t\t\tg_free(resend);\n\n\t\t\t\t\t/* Transaction not yet completed */\n\t\t\t\t\ttrans = NULL;\n\t\t\t\t}\n\n\t\t\t} else if (msg->response == 407) { /* Proxy Authentication Required */\n\n\t\t\t\tif (transport->proxy.retries++ <= 30) {\n\t\t\t\t\tconst gchar *proxy_hdr = sipmsg_find_header(msg, \"Proxy-Authenticate\");\n\n\t\t\t\t\tif (proxy_hdr) {\n\t\t\t\t\t\tgchar *auth = NULL;\n\n\t\t\t\t\t\tif (!g_ascii_strncasecmp(proxy_hdr, \"Digest\", 6)) {\n\t\t\t\t\t\t\tauth = sip_sec_digest_authorization(sipe_private,\n\t\t\t\t\t\t\t\t\t\t\t    proxy_hdr + 7,\n\t\t\t\t\t\t\t\t\t\t\t    msg->method,\n\t\t\t\t\t\t\t\t\t\t\t    msg->target);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tguint i;\n\n\t\t\t\t\t\t\ttransport->proxy.type = SIPE_AUTHENTICATION_TYPE_UNSET;\n\t\t\t\t\t\t\tfor (i = 0; i < AUTH_PROTOCOLS; i++) {\n\t\t\t\t\t\t\t\tconst gchar *protocol = auth_type_to_protocol[i];\n\t\t\t\t\t\t\t\tif (protocol &&\n\t\t\t\t\t\t\t\t    !g_ascii_strncasecmp(proxy_hdr, protocol, strlen(protocol))) {\n\t\t\t\t\t\t\t\t\tSIPE_DEBUG_INFO(\"process_input_message: proxy authentication scheme '%s'\", protocol);\n\t\t\t\t\t\t\t\t\ttransport->proxy.type     = i;\n\t\t\t\t\t\t\t\t\ttransport->proxy.protocol = protocol;\n\t\t\t\t\t\t\t\t\tfill_auth(proxy_hdr, &transport->proxy);\n\t\t\t\t\t\t\t\t\tauth = auth_header(sipe_private, &transport->proxy, trans->msg);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (auth) {\n\t\t\t\t\t\t\tgchar *resend;\n\n\t\t\t\t\t\t\t/* replace old proxy authentication with new one */\n\t\t\t\t\t\t\tsipmsg_remove_header_now(trans->msg, \"Proxy-Authorization\");\n\t\t\t\t\t\t\tsipmsg_add_header_now(trans->msg, \"Proxy-Authorization\", auth);\n\t\t\t\t\t\t\tg_free(auth);\n\n\t\t\t\t\t\t\t/* resend request with proxy authentication */\n\t\t\t\t\t\t\tresend = sipmsg_to_string(trans->msg);\n\t\t\t\t\t\t\tsend_sip_message(sipe_private->transport, resend);\n\t\t\t\t\t\t\tg_free(resend);\n\n\t\t\t\t\t\t\t/* Transaction not yet completed */\n\t\t\t\t\t\t\ttrans = NULL;\n\n\t\t\t\t\t\t} else\n\t\t\t\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"process_input_message: can't generate proxy authentication. Giving up.\");\n\t\t\t\t\t} else\n\t\t\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"process_input_message: 407 response without 'Proxy-Authenticate' header. Giving up.\");\n\t\t\t\t} else\n\t\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"process_input_message: too many proxy authentication retries. Giving up.\");\n\n\t\t\t} else {\n\t\t\t\ttransport->registrar.retries = 0;\n\t\t\t\ttransport->proxy.retries = 0;\n\t\t\t}\n\n\t\t\t/* Is transaction completed? */\n\t\t\tif (trans) {\n\t\t\t\tif (trans->callback) {\n\t\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_input_message: we have a transaction callback\");\n\t\t\t\t\t/* call the callback to process response */\n\t\t\t\t\t(trans->callback)(sipe_private, msg, trans);\n\t\t\t\t\t/* transport && trans no longer valid after redirect */\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t * Redirect case: sipe_private->transport is\n\t\t\t\t * the new transport with empty queue\n\t\t\t\t */\n\t\t\t\tif (sipe_private->transport->transactions) {\n\t\t\t\t\tSIPE_DEBUG_INFO(\"process_input_message: removing CSeq %d\", transport->cseq);\n\t\t\t\t\ttransactions_remove(sipe_private, trans);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_input_message: received response to unknown transaction\");\n\t\t\tnotfound = TRUE;\n\t\t}\n\t}\n\n\tif (notfound) {\n\t\tSIPE_DEBUG_INFO(\"received a unknown sip message with method %s and response %d\", method, msg->response);\n\t}\n}\n\nstatic void sip_transport_input(struct sipe_transport_connection *conn)\n{\n\tstruct sipe_core_private *sipe_private = conn->user_data;\n\tstruct sip_transport *transport = sipe_private->transport;\n\tgchar *cur = conn->buffer;\n\n\t/* according to the RFC remove CRLF at the beginning */\n\twhile (*cur == '\\r' || *cur == '\\n') {\n\t\tcur++;\n\t}\n\tif (cur != conn->buffer)\n\t\tsipe_utils_shrink_buffer(conn, cur);\n\n\t/* Received a full Header? */\n\ttransport->processing_input = TRUE;\n\twhile (transport->processing_input &&\n\t       ((cur = strstr(conn->buffer, \"\\r\\n\\r\\n\")) != NULL)) {\n\t\tstruct sipmsg *msg;\n\t\tguint remainder;\n\n\t\tcur += 2;\n\t\tcur[0] = '\\0';\n\t\tmsg = sipmsg_parse_header(conn->buffer);\n\n\t\tcur += 2;\n\t\tremainder = conn->buffer_used - (cur - conn->buffer);\n\t\tif (msg && remainder >= (guint) msg->bodylen) {\n\t\t\tchar *dummy = g_malloc(msg->bodylen + 1);\n\t\t\tmemcpy(dummy, cur, msg->bodylen);\n\t\t\tdummy[msg->bodylen] = '\\0';\n\t\t\tmsg->body = dummy;\n\t\t\tcur += msg->bodylen;\n\t\t\tsipe_utils_message_debug(conn,\n\t\t\t\t\t\t \"SIP\",\n\t\t\t\t\t\t conn->buffer,\n\t\t\t\t\t\t msg->body,\n\t\t\t\t\t\t FALSE);\n\t\t\tsipe_utils_shrink_buffer(conn, cur);\n\t\t} else {\n\t\t\tif (msg) {\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_transport_input: body too short (%d < %d, strlen %d) - ignoring message\", remainder, msg->bodylen, (int)strlen(conn->buffer));\n\t\t\t\tsipmsg_free(msg);\n                        }\n\n\t\t\t/* restore header for next try */\n\t\t\tcur[-2] = '\\r';\n\t\t\treturn;\n\t\t}\n\n\t\t/* Fatal header parse error? */\n\t\tif (msg->response == SIPMSG_RESPONSE_FATAL_ERROR) {\n\t\t\t/* can't proceed -> drop connection */\n\t\t\tsipe_backend_connection_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t      SIPE_CONNECTION_ERROR_NETWORK,\n\t\t\t\t\t\t      _(\"Corrupted message received\"));\n\t\t\ttransport->processing_input = FALSE;\n\n\t\t/* Verify the signature before processing it */\n\t\t} else if (sip_sec_context_is_ready(transport->registrar.gssapi_context)) {\n\t\t\tstruct sipmsg_breakdown msgbd;\n\t\t\tgchar *signature_input_str;\n\t\t\tgchar *rspauth;\n\t\t\tmsgbd.msg = msg;\n\t\t\tsipmsg_breakdown_parse(&msgbd, transport->registrar.realm, transport->registrar.target,\n\t\t\t\t\t       transport->registrar.protocol);\n\t\t\tsignature_input_str = sipmsg_breakdown_get_string(transport->registrar.version, &msgbd);\n\n\t\t\trspauth = sipmsg_find_part_of_header(sipmsg_find_header(msg, \"Authentication-Info\"), \"rspauth=\\\"\", \"\\\"\", NULL);\n\n\t\t\tif (rspauth != NULL) {\n\t\t\t\tif (sip_sec_verify_signature(transport->registrar.gssapi_context, signature_input_str, rspauth)) {\n\t\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_transport_input: signature of incoming message validated\");\n\t\t\t\t\tprocess_input_message(sipe_private, msg);\n\t\t\t\t\t/* transport is invalid after redirect */\n\t\t\t\t} else {\n\t\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_transport_input: signature of incoming message is invalid.\");\n\t\t\t\t\tsipe_backend_connection_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t      SIPE_CONNECTION_ERROR_NETWORK,\n\t\t\t\t\t\t\t\t      _(\"Invalid message signature received\"));\n\t\t\t\t\ttransport->processing_input = FALSE;\n\t\t\t\t}\n\t\t\t} else if ((msg->response == 401) ||\n\t\t\t\t   sipe_strequal(msg->method, \"REGISTER\")) {\n\t\t\t\t/* a) Retry non-REGISTER requests with updated authentication */\n\t\t\t\t/* b) We must always process REGISTER responses */\n\t\t\t\tprocess_input_message(sipe_private, msg);\n\t\t\t} else {\n\t\t\t\t/* OCS sends provisional messages that are *not* signed */\n\t\t\t\tif (msg->response >= 200) {\n\t\t\t\t\t/* We are not calling process_input_message(),\n\t\t\t\t\t   so we need to drop the transaction here. */\n\t\t\t\t\tstruct transaction *trans = transactions_find(transport, msg);\n\t\t\t\t\tif (trans) transactions_remove(sipe_private, trans);\n\t\t\t\t}\n\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sip_transport_input: message without authentication data - ignoring\");\n\t\t\t}\n\t\t\tg_free(signature_input_str);\n\n\t\t\tg_free(rspauth);\n\t\t\tsipmsg_breakdown_free(&msgbd);\n\t\t} else {\n\t\t\tprocess_input_message(sipe_private, msg);\n\t\t}\n\n\t\tsipmsg_free(msg);\n\n\t\t/* Redirect: old content of \"transport\" & \"conn\" is no longer valid */\n\t\ttransport = sipe_private->transport;\n\t\tconn      = transport->connection;\n\t}\n}\n\nstatic void sip_transport_connected(struct sipe_transport_connection *conn)\n{\n\tstruct sipe_core_private *sipe_private = conn->user_data;\n\tstruct sip_transport *transport = sipe_private->transport;\n\tgchar *self_sip_uri = sip_uri_self(sipe_private);\n\n\tSIPE_LOG_INFO(\"sip_transport_connected: '%s:%u'(%p)\",\n\t\t      transport->server_name, transport->server_port, conn);\n\n\twhile (sipe_private->lync_autodiscover_servers)\n\t\tsipe_private->lync_autodiscover_servers =\n\t\t\tsipe_lync_autodiscover_pop(sipe_private->lync_autodiscover_servers);\n\n\tsipe_private->service_data = NULL;\n\tsipe_private->address_data = NULL;\n\n\t/*\n\t * Initial keepalive timeout during REGISTER phase\n\t *\n\t * NOTE: 60 seconds is a guess. Needs more testing!\n\t */\n\ttransport->keepalive_timeout = 60;\n\tstart_keepalive_timer(sipe_private, transport->keepalive_timeout);\n\n\ttransport->ip_address = sipe_backend_transport_ip_address(conn);\n\tif (strchr(transport->ip_address, ':') != NULL)\n\t\t/* RFC2732: Format for Literal IPv6 Addresses in URL's */\n\t\ttransport->uri_address = g_strdup_printf(\"[%s]\", transport->ip_address);\n\telse\n\t\ttransport->uri_address = g_strdup(transport->ip_address);\n\ttransport->sdp_marker = sipe_utils_ip_sdp_address_marker(transport->ip_address);\n\ttransport->epid       = sipe_get_epid(self_sip_uri,\n\t\t\t\t\t      g_get_host_name(),\n\t\t\t\t\t      transport->ip_address);\n\tg_free(self_sip_uri);\n\n\tdo_register(sipe_private, FALSE);\n}\n\nstatic void resolve_next_lync(struct sipe_core_private *sipe_private);\nstatic void resolve_next_service(struct sipe_core_private *sipe_private,\n\t\t\t\t const struct sip_service_data *start);\nstatic void resolve_next_address(struct sipe_core_private *sipe_private,\n\t\t\t\t gboolean initial);\nstatic void sip_transport_error(struct sipe_transport_connection *conn,\n\t\t\t\tconst gchar *msg)\n{\n\tstruct sipe_core_private *sipe_private = conn->user_data;\n\n\t/* This failed attempt was based on a Lync Autodiscover result */\n\tif (sipe_private->lync_autodiscover_servers) {\n\t\tresolve_next_lync(sipe_private);\n\t/* This failed attempt was based on a DNS SRV record */\n\t} else if (sipe_private->service_data) {\n\t\tresolve_next_service(sipe_private, NULL);\n\t/* This failed attempt was based on a DNS A record */\n\t} else if (sipe_private->address_data) {\n\t\tresolve_next_address(sipe_private, FALSE);\n\t} else {\n\t\tsipe_backend_connection_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t      SIPE_CONNECTION_ERROR_NETWORK,\n\t\t\t\t\t      msg);\n\t}\n}\n\n/* server_name must be g_alloc()'ed */\nstatic void sipe_server_register(struct sipe_core_private *sipe_private,\n\t\t\t\t guint type,\n\t\t\t\t gchar *server_name,\n\t\t\t\t guint server_port)\n{\n\tsipe_connect_setup setup = {\n\t\ttype,\n\t\tserver_name,\n\t\t(server_port != 0)           ? server_port :\n\t\t(type == SIPE_TRANSPORT_TLS) ? 5061 : 5060,\n\t\tsipe_private,\n\t\tsip_transport_connected,\n\t\tsip_transport_input,\n\t\tsip_transport_error\n\t};\n\tstruct sip_transport *transport = g_new0(struct sip_transport, 1);\n\n\ttransport->auth_retry   = TRUE;\n\ttransport->server_name  = server_name;\n\ttransport->server_port  = setup.server_port;\n\ttransport->connection   = sipe_backend_transport_connect(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t &setup);\n\tsipe_private->transport = transport;\n}\n\nstruct sip_service_data {\n\tconst char *protocol;\n\tconst char *transport;\n\tguint type;\n};\n\n/*\n * Autodiscover using DNS SRV records. See RFC2782/3263\n *\n * Service list for AUTO\n */\nstatic const struct sip_service_data service_autodetect[] = {\n\t{ \"sipinternaltls\", \"tcp\", SIPE_TRANSPORT_TLS }, /* for internal TLS connections */\n\t{ \"sipinternal\",    \"tcp\", SIPE_TRANSPORT_TCP }, /* for internal TCP connections */\n\t{ \"sip\",            \"tls\", SIPE_TRANSPORT_TLS }, /* for external TLS connections */\n\t{ \"sip\",            \"tcp\", SIPE_TRANSPORT_TCP }, /*.for external TCP connections */\n\t{ NULL,             NULL,  0 }\n};\n\n/* Service list for SSL/TLS */\nstatic const struct sip_service_data service_tls[] = {\n\t{ \"sipinternaltls\", \"tcp\", SIPE_TRANSPORT_TLS }, /* for internal TLS connections */\n\t{ \"sip\",            \"tls\", SIPE_TRANSPORT_TLS }, /* for external TLS connections */\n\t{ NULL,             NULL,  0 }\n};\n\n/* Service list for TCP */\nstatic const struct sip_service_data service_tcp[] = {\n\t{ \"sipinternal\",    \"tcp\", SIPE_TRANSPORT_TCP }, /* for internal TCP connections */\n\t{ \"sip\",            \"tcp\", SIPE_TRANSPORT_TCP }, /*.for external TCP connections */\n\t{ NULL,             NULL,  0 }\n};\n\nstatic const struct sip_service_data *services[] = {\n\tservice_autodetect, /* SIPE_TRANSPORT_AUTO */\n\tservice_tls,        /* SIPE_TRANSPORT_TLS  */\n\tservice_tcp         /* SIPE_TRANSPORT_TCP  */\n};\n\nstruct sip_address_data {\n\tconst char *prefix;\n\tguint port;\n};\n\n/*\n * Autodiscover using DNS A records. This is an extension addded\n * by Microsoft. See http://support.microsoft.com/kb/2619522\n */\nstatic const struct sip_address_data addresses[] = {\n\t{ \"sipinternal\", 5061 },\n\t{ \"sipexternal\",  443 },\n/*\n * Our implementation supports only one port per host name. If the host name\n * resolves OK, we abort the search and try to connect. If we would know if we\n * are trying to connect from \"Intranet\" or \"Internet\" then we could choose\n * between those two ports.\n *\n * We drop port 5061 in order to cover the \"Internet\" case.\n *\n *\t{ \"sip\",         5061 },\n */\n\t{ \"sip\",          443 },\n\t{ NULL,             0 }\n};\n\nstatic void sipe_core_dns_resolved(struct sipe_core_public *sipe_public,\n\t\t\t\t   const gchar *hostname, guint port)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tgboolean service = sipe_private->service_data != NULL;\n\n\tsipe_private->dns_query = NULL;\n\n\tif (hostname) {\n\t\tgchar *host;\n\t\tguint type;\n\n\t\tif (service) {\n\t\t\thost = g_strdup(hostname);\n\t\t\ttype = sipe_private->service_data->type;\n\t\t} else {\n\t\t\t/* DNS A resolver returns an IP address */\n\t\t\thost = g_strdup_printf(\"%s.%s\",\n\t\t\t\t\t       sipe_private->address_data->prefix,\n\t\t\t\t\t       sipe_private->public.sip_domain);\n\t\t\tport = sipe_private->address_data->port;\n\t\t\ttype = sipe_private->transport_type;\n\t\t\tif (type == SIPE_TRANSPORT_AUTO)\n\t\t\t\ttype = SIPE_TRANSPORT_TLS;\n\t\t}\n\n\t\tSIPE_DEBUG_INFO(\"sipe_core_dns_resolved - %s hostname: %s port: %d\",\n\t\t\t\tservice ? \"SRV\" : \"A\", hostname, port);\n\t\tsipe_server_register(sipe_private, type, host, port);\n\t} else {\n\t\tif (service)\n\t\t\tresolve_next_service(SIPE_CORE_PRIVATE, NULL);\n\t\telse\n\t\t\tresolve_next_address(SIPE_CORE_PRIVATE, FALSE);\n\t}\n}\n\nstatic void resolve_next_lync(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_lync_autodiscover_data *lync_data = sipe_private->lync_autodiscover_servers->data;\n\tguint type = sipe_private->transport_type;\n\n\tif (lync_data) {\n\t\t/* Try to connect to next server on the list */\n\t\tif (type == SIPE_TRANSPORT_AUTO)\n\t\t\ttype = SIPE_TRANSPORT_TLS;\n\n\t\tsipe_server_register(sipe_private,\n\t\t\t\t     type,\n\t\t\t\t     g_strdup(lync_data->server),\n\t\t\t\t     lync_data->port);\n\n\t} else {\n\t\t/* We tried all servers -> try DNS SRV next */\n\t\tSIPE_LOG_INFO_NOFORMAT(\"no Lync Autodiscover servers found; trying SRV records next\");\n\t\tresolve_next_service(sipe_private, services[type]);\n\t}\n\n\tsipe_private->lync_autodiscover_servers =\n\t\tsipe_lync_autodiscover_pop(sipe_private->lync_autodiscover_servers);\n}\n\nstatic void resolve_next_service(struct sipe_core_private *sipe_private,\n\t\t\t\t const struct sip_service_data *start)\n{\n\tif (start) {\n\t\tsipe_private->service_data = start;\n\t} else {\n\t\tsipe_private->service_data++;\n\t\tif (sipe_private->service_data->protocol == NULL) {\n\n\t\t\t/* We tried all services */\n\t\t\tsipe_private->service_data = NULL;\n\n\t\t\t/* Try A records list next */\n\t\t\tSIPE_LOG_INFO_NOFORMAT(\"no SRV records found; trying A records next\");\n\t\t\tresolve_next_address(sipe_private, TRUE);\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/* Try to resolve next service */\n\tsipe_private->dns_query = sipe_backend_dns_query_srv(\n\t\t\t\t\tSIPE_CORE_PUBLIC,\n\t\t\t\t\tsipe_private->service_data->protocol,\n\t\t\t\t\tsipe_private->service_data->transport,\n\t\t\t\t\tsipe_private->public.sip_domain,\n\t\t\t\t\t(sipe_dns_resolved_cb) sipe_core_dns_resolved,\n\t\t\t\t\tSIPE_CORE_PUBLIC);\n}\n\nstatic void resolve_next_address(struct sipe_core_private *sipe_private,\n\t\t\t\t gboolean initial)\n{\n\tgchar *hostname;\n\n\tif (initial) {\n\t\tsipe_private->address_data = addresses;\n\t} else {\n\t\tsipe_private->address_data++;\n\t\tif (sipe_private->address_data->prefix == NULL) {\n\t\t\tguint type = sipe_private->transport_type;\n\n\t\t\t/* We tried all addresss */\n\t\t\tsipe_private->address_data = NULL;\n\n\t\t\t/* Try connecting to the SIP hostname directly */\n\t\t\tSIPE_LOG_INFO_NOFORMAT(\"no SRV or A records found; using SIP domain as fallback\");\n\t\t\tif (type == SIPE_TRANSPORT_AUTO)\n\t\t\t\ttype = SIPE_TRANSPORT_TLS;\n\n\t\t\tsipe_server_register(sipe_private, type,\n\t\t\t\t\t     g_strdup(sipe_private->public.sip_domain),\n\t\t\t\t\t     0);\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/* Try to resolve next address */\n\thostname = g_strdup_printf(\"%s.%s\",\n\t\t\t\t   sipe_private->address_data->prefix,\n\t\t\t\t   sipe_private->public.sip_domain);\n\tsipe_private->dns_query = sipe_backend_dns_query_a(\n\t\t\t\t\tSIPE_CORE_PUBLIC,\n\t\t\t\t\thostname,\n\t\t\t\t\tsipe_private->address_data->port,\n\t\t\t\t\t(sipe_dns_resolved_cb) sipe_core_dns_resolved,\n\t\t\t\t\tSIPE_CORE_PUBLIC);\n\tg_free(hostname);\n}\n\nstatic void lync_autodiscover_cb(struct sipe_core_private *sipe_private,\n\t\t\t\t GSList *servers,\n\t\t\t\t SIPE_UNUSED_PARAMETER gpointer callback_data)\n{\n\tif (servers) {\n\t\t/* Lync Autodiscover succeeded */\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"lync_autodiscover_cb: got server list\");\n\n\t\tsipe_private->lync_autodiscover_servers = servers;\n\t\tresolve_next_lync(sipe_private);\n\t}\n}\n\n/*\n * NOTE: this function can be called before sipe_core_allocate()!\n */\ngboolean sipe_core_transport_sip_requires_password(guint authentication,\n\t\t\t\t\t\t   gboolean sso)\n{\n\treturn(sip_sec_requires_password(authentication, sso));\n}\n\nvoid sipe_core_transport_sip_connect(struct sipe_core_public *sipe_public,\n\t\t\t\t     guint transport,\n\t\t\t\t     guint authentication,\n\t\t\t\t     const gchar *server,\n\t\t\t\t     const gchar *port)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\n\t/* backend initialization is complete */\n\tsipe_core_backend_initialized(sipe_private, authentication);\n\n\t/*\n\t * Initializing the certificate sub-system will trigger the generation\n\t * of a cryptographic key pair which takes time. If we do this after we\n\t * have connected to the server then there is a risk that we run into a\n\t * SIP connection timeout. So let's get this out of the way now...\n\t *\n\t * This is currently only needed if the user has selected TLS-DSK.\n\t */\n\tif (sipe_private->authentication_type == SIPE_AUTHENTICATION_TYPE_TLS_DSK)\n\t\tsipe_certificate_init(sipe_private);\n\n\tif (server) {\n\t\t/* Use user specified server[:port] */\n\t\tint port_number = 0;\n\n\t\tif (port)\n\t\t\tport_number = atoi(port);\n\n\t\tSIPE_LOG_INFO(\"sipe_core_connect: user specified SIP server %s:%d\",\n\t\t\t      server, port_number);\n\n\t\tsipe_server_register(sipe_private, transport,\n\t\t\t\t     g_strdup(server), port_number);\n\t} else {\n\t\t/* Server auto-discovery */\n\n\t\t/* Remember user specified transport type */\n\t\tsipe_private->transport_type = transport;\n\n\t\t/* Start with Lync Autodiscover first */\n\t\tsipe_lync_autodiscover_start(sipe_private,\n\t\t\t\t\t     lync_autodiscover_cb,\n\t\t\t\t\t     NULL);\n\t}\n}\n\nconst gchar *sipe_core_transport_sip_server_name(struct sipe_core_public *sipe_public)\n{\n\tstruct sip_transport *transport = SIPE_CORE_PRIVATE->transport;\n\treturn(transport ? transport->server_name : NULL);\n}\n\nint sip_transaction_cseq(struct transaction *trans)\n{\n\tint cseq;\n\n\tg_return_val_if_fail(trans && trans->key, 0);\n\n\tsscanf(trans->key, \"<%*[a-zA-Z0-9]><%d INVITE>\", &cseq);\n\treturn cseq;\n}\n\nconst gchar *sip_transport_epid(struct sipe_core_private *sipe_private)\n{\n\treturn(sipe_private->transport ?\n\t       sipe_private->transport->epid :\n\t       \"0123456789ab\");\n}\n\nconst gchar *sip_transport_ip_address(struct sipe_core_private *sipe_private)\n{\n\treturn(sipe_private->transport ?\n\t       sipe_private->transport->ip_address :\n\t       \"0.0.0.0\");\n}\n\nconst gchar *sip_transport_sdp_address_marker(struct sipe_core_private *sipe_private)\n{\n\treturn(sipe_private->transport ?\n\t       sipe_private->transport->sdp_marker :\n\t       \"IP4\");\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sip-transport.h",
    "content": "/**\n * @file sip-transport.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipmsg;\nstruct sip_dialog;\nstruct sipe_core_private;\nstruct transaction;\n\n/* Transaction that can be associated with a SIP request */\ntypedef gboolean (*TransCallback) (struct sipe_core_private *,\n\t\t\t\t   struct sipmsg *,\n\t\t\t\t   struct transaction *);\n\nstruct transaction_payload {\n\tGDestroyNotify destroy;\n\tvoid *data;\n};\n\nstruct transaction {\n\tTransCallback callback;\n\tTransCallback timeout_callback;\n\n\t/** Not yet perfect, but surely better then plain CSeq\n\t * Format is: <Call-ID><CSeq>\n\t * (RFC3261 17.2.3 for matching server transactions: Request-URI, To tag, From tag, Call-ID, CSeq, and top Via)\n\t */\n\tgchar *key;\n\tgchar *timeout_key;\n        struct sipmsg *msg;\n\tstruct transaction_payload *payload;\n};\n\n/* Send SIP response */\nvoid sip_transport_response(struct sipe_core_private *sipe_private,\n\t\t\t    struct sipmsg *msg,\n\t\t\t    guint code,\n\t\t\t    const char *text,\n\t\t\t    const char *body);\n\n/* Send SIP request */\nstruct transaction *sip_transport_request(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  const gchar *method,\n\t\t\t\t\t  const gchar *url,\n\t\t\t\t\t  const gchar *to,\n\t\t\t\t\t  const gchar *addheaders,\n\t\t\t\t\t  const gchar *body,\n\t\t\t\t\t  struct sip_dialog *dialog,\n\t\t\t\t\t  TransCallback callback);\n\n/* Send SIP request with timeout [in seconds] */\nstruct transaction *sip_transport_request_timeout(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t  const gchar *method,\n\t\t\t\t\t\t  const gchar *url,\n\t\t\t\t\t\t  const gchar *to,\n\t\t\t\t\t\t  const gchar *addheaders,\n\t\t\t\t\t\t  const gchar *body,\n\t\t\t\t\t\t  struct sip_dialog *dialog,\n\t\t\t\t\t\t  TransCallback callback,\n\t\t\t\t\t\t  guint timeout,\n\t\t\t\t\t\t  TransCallback timeout_callback);\n\n/* Common SIP request types */\nvoid sip_transport_ack(struct sipe_core_private *sipe_private,\n\t\t       struct sip_dialog *dialog);\nvoid sip_transport_bye(struct sipe_core_private *sipe_private,\n\t\t       struct sip_dialog *dialog);\nstruct transaction *sip_transport_info(struct sipe_core_private *sipe_private,\n\t\t\t\t       const gchar *addheaders,\n\t\t\t\t       const gchar *body,\n\t\t\t\t       struct sip_dialog *dialog,\n\t\t\t\t       TransCallback callback);\nstruct transaction *sip_transport_invite(struct sipe_core_private *sipe_private,\n\t\t\t\t\t const gchar *addheaders,\n\t\t\t\t\t const gchar *body,\n\t\t\t\t\t struct sip_dialog *dialog,\n\t\t\t\t\t TransCallback callback);\nstruct transaction *sip_transport_service(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  const gchar *uri,\n\t\t\t\t\t  const gchar *addheaders,\n\t\t\t\t\t  const gchar *body,\n\t\t\t\t\t  TransCallback callback);\nvoid sip_transport_subscribe(struct sipe_core_private *sipe_private,\n\t\t\t     const gchar *uri,\n\t\t\t     const gchar *addheaders,\n\t\t\t     const gchar *body,\n\t\t\t     struct sip_dialog *dialog,\n\t\t\t     TransCallback callback);\nvoid sip_transport_update(struct sipe_core_private *sipe_private,\n\t\t\t  struct sip_dialog *dialog,\n\t\t\t  TransCallback callback);\n\n/* Misc. SIP transport stuff */\nguint sip_transport_port(struct sipe_core_private *sipe_private);\nvoid sip_transport_deregister(struct sipe_core_private *sipe_private);\nvoid sip_transport_drop(struct sipe_core_private *sipe_private);\nvoid sip_transport_authentication_completed(struct sipe_core_private *sipe_private);\n\nint sip_transaction_cseq(struct transaction *trans);\n\nconst gchar *sip_transport_epid(struct sipe_core_private *sipe_private);\nconst gchar *sip_transport_ip_address(struct sipe_core_private *sipe_private);\nconst gchar *sip_transport_sdp_address_marker(struct sipe_core_private *sipe_private);\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-appshare-client.h",
    "content": "/**\n * @file sipe-appshare-client.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\nstruct sipe_media_stream;\nstruct sipmsg;\n\nstruct sipe_rdp_client {\n\tgchar *cmdline;\n\tvoid *client_data;\n\n\tGSocketAddress *(*get_listen_address_cb)(struct sipe_rdp_client *client);\n\tgboolean (*launch_cb)(struct sipe_rdp_client *client,\n\t\t\t      GSocketAddress *listen_address,\n\t\t\t      struct sipe_media_stream *stream);\n\tvoid (*free_cb)(struct sipe_rdp_client *client);\n};\n\n/* Client implementations */\nvoid sipe_appshare_remmina_init(struct sipe_rdp_client *client);\nvoid sipe_appshare_xfreerdp_init(struct sipe_rdp_client *client);\n"
  },
  {
    "path": "src/core/sipe-appshare-remmina.c",
    "content": "/**\n * @file sipe-appshare-remmina.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2014-2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <glib.h>\n#include <glib/gstdio.h>\n\n#include <gio/gio.h>\n\n#include <string.h>\n\n#include \"sipe-appshare-client.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-buddy.h\"\n#include \"sipe-common.h\"\n#include \"sipe-media.h\"\n\nstruct remmina_data {\n\tgchar *config_file;\n};\n\nstatic GSocketAddress *\nremmina_get_listen_address(SIPE_UNUSED_PARAMETER struct sipe_rdp_client *client)\n{\n\tGInetAddress *loopback;\n\tGSocketAddress *address;\n\n\tloopback = g_inet_address_new_loopback(G_SOCKET_FAMILY_IPV4);\n\taddress = g_inet_socket_address_new(loopback, 0);\n\tg_object_unref(loopback);\n\n\treturn address;\n}\n\nstatic gboolean\nremmina_launch(struct sipe_rdp_client *client, GSocketAddress *listen_address,\n\t       struct sipe_media_stream *stream)\n{\n\tstruct remmina_data *client_data = client->client_data;\n\tstruct sipe_core_private *sipe_private;\n\tGInetAddress *address;\n\tgchar *address_string;\n\tgchar *alias;\n\tgchar *config_file;\n\tgchar *cmdline;\n\tguint16 port;\n\tGError *error = NULL;\n\n\tsipe_private = sipe_media_get_sipe_core_private(stream->call);\n\n\taddress = g_inet_socket_address_get_address(G_INET_SOCKET_ADDRESS(listen_address));\n\taddress_string = g_inet_address_to_string(address);\n\n\tport = g_inet_socket_address_get_port(G_INET_SOCKET_ADDRESS(listen_address));\n\n\talias = sipe_buddy_get_alias(sipe_private, stream->call->with);\n\n\tconfig_file = g_strdup_printf(\"[remmina]\\n\"\n\t\t\t\t      \"name=%s (Sipe desktop)\\n\"\n\t\t\t\t      \"protocol=RDP\\n\"\n\t\t\t\t      \"server=%s:%u\\n\"\n\t\t\t\t      \"security=rdp\\n\"\n\t\t\t\t      \"scale=1\\n\"\n\t\t\t\t      \"aspectscale=1\\n\"\n\t\t\t\t      \"viewmode=1\\n\"\n\t\t\t\t      \"colordepth=0\\n\"\n\t\t\t\t      \"disableautoreconnect=1\\n\",\n\t\t\t\t      alias ? alias : stream->call->with,\n\t\t\t\t      address_string,\n\t\t\t\t      port);\n\n\tg_free(alias);\n\tg_free(address_string);\n\n\tclient_data->config_file =\n\t\t\tg_strdup_printf(\"%s/sipe-appshare-%u-%p.remmina\",\n\t\t\t\t\tg_get_user_runtime_dir(), getpid(),\n\t\t\t\t\tclient);\n\n\tg_file_set_contents(client_data->config_file, config_file,\n\t\t\t    strlen(config_file), &error);\n\tSIPE_DEBUG_INFO(\"Written .remmina file %s:\\n%s\",\n\t\t\tclient_data->config_file, config_file);\n\tg_free(config_file);\n\tif (error) {\n\t\tSIPE_DEBUG_ERROR(\"Couldn't write remmina config file: %s\",\n\t\t\t\t error->message);\n\t\tg_error_free(error);\n\t\treturn FALSE;\n\t}\n\n\tcmdline = g_strdup_printf(\"%s -c %s\",\n\t\t\t\t  client->cmdline,\n\t\t\t\t  client_data->config_file);\n\n\tSIPE_DEBUG_INFO(\"Launching remmina: %s\", cmdline);\n\n\tg_spawn_command_line_async(cmdline, &error);\n\tg_free(cmdline);\n\tif (error) {\n\t\tSIPE_DEBUG_ERROR(\"Couldn't launch remmina: %s\", error->message);\n\t\tg_error_free(error);\n\t\treturn FALSE;\n\t}\n\n\treturn TRUE;\n}\n\nstatic void\nremmina_free(struct sipe_rdp_client *client)\n{\n\tstruct remmina_data *client_data = client->client_data;\n\n\tif (client_data->config_file) {\n\t\tg_unlink(client_data->config_file);\n\t\tg_free(client_data->config_file);\n\t}\n\n\tg_free(client_data);\n}\n\nvoid\nsipe_appshare_remmina_init(struct sipe_rdp_client *client)\n{\n\tclient->client_data = g_new0(struct remmina_data, 1);\n\n\tclient->get_listen_address_cb = remmina_get_listen_address;\n\tclient->launch_cb = remmina_launch;\n\tclient->free_cb = remmina_free;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-appshare-xfreerdp.c",
    "content": "/**\n * @file sipe-appshare-xfreerdp.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2014-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <string.h>\n\n#include <glib.h>\n#include <glib/gstdio.h>\n\n#include <gio/gio.h>\n\n#include <sys/socket.h>\n#include <sys/un.h>\n\n#include \"sipe-appshare-client.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n\nstruct xfreerdp_data {\n\tgchar *socket_path;\n};\n\nstatic GSocketAddress *\nxfreerdp_get_listen_address(struct sipe_rdp_client *client)\n{\n\tstruct xfreerdp_data *data = client->client_data;\n\tstruct sockaddr_un address;\n\n\tdata->socket_path = g_strdup_printf(\"%s/sipe-appshare-%u-%p\",\n\t\t\t\t\t    g_get_user_runtime_dir(), getpid(),\n\t\t\t\t\t    client);\n\n\tg_unlink(data->socket_path);\n\n\taddress.sun_family = AF_LOCAL;\n\tstrncpy(address.sun_path, data->socket_path, sizeof (address.sun_path) - 1);\n\taddress.sun_path[sizeof (address.sun_path) - 1] = '\\0';\n\n\treturn g_socket_address_new_from_native(&address, sizeof (address));\n}\n\nstatic gboolean\nxfreerdp_launch(struct sipe_rdp_client *client,\n\t\tSIPE_UNUSED_PARAMETER GSocketAddress *listen_address,\n\t\tSIPE_UNUSED_PARAMETER struct sipe_media_stream *stream)\n{\n\tstruct xfreerdp_data *client_data = client->client_data;\n\tgchar *cmdline;\n\tGError *error = NULL;\n\n\t/* This assumes FreeRDP 2.x.x */\n\tcmdline = g_strdup_printf(\"%s /v:%s /sec:rdp\",\n\t\t\t\t  client->cmdline,\n\t\t\t\t  client_data->socket_path);\n\n\tg_spawn_command_line_async(cmdline, &error);\n\tg_free(cmdline);\n\tif (error) {\n\t\tSIPE_DEBUG_ERROR(\"Can't launch xfreerdp: %s\", error->message);\n\t\tg_error_free(error);\n\t\treturn FALSE;\n\t}\n\n\treturn TRUE;\n}\n\nstatic void\nxfreerdp_free(struct sipe_rdp_client *client)\n{\n\tstruct xfreerdp_data *client_data = client->client_data;\n\n\tif (client_data->socket_path) {\n\t\tg_unlink(client_data->socket_path);\n\t\tg_free(client_data->socket_path);\n\t}\n\n\tg_free(client_data);\n}\n\nvoid\nsipe_appshare_xfreerdp_init(struct sipe_rdp_client *client)\n{\n\tclient->client_data = g_new0(struct xfreerdp_data, 1);\n\n\tclient->get_listen_address_cb = xfreerdp_get_listen_address;\n\tclient->launch_cb = xfreerdp_launch;\n\tclient->free_cb = xfreerdp_free;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-appshare.c",
    "content": "/**\n * @file sipe-appshare.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2014-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n#include <string.h>\n\n#include <gio/gio.h>\n\n#ifdef HAVE_APPSHARE_SERVER\n#include <glib/gstdio.h>\n\n#include <sys/socket.h>\n#include <sys/un.h>\n\n#include <freerdp/server/shadow.h>\n#endif // HAVE_APPSHARE_SERVER\n\n#include \"sipmsg.h\"\n#include \"sipe-appshare-client.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-buddy.h\"\n#include \"sipe-chat.h\"\n#include \"sipe-common.h\"\n#include \"sipe-conf.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-appshare.h\"\n#include \"sipe-media.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-schedule.h\"\n#include \"sipe-user.h\"\n#include \"sipe-utils.h\"\n#include \"sdpmsg.h\"\n\nstruct sipe_appshare {\n\tstruct sipe_media_stream *stream;\n\tGSocket *socket;\n\tGIOChannel *channel;\n\tguint rdp_channel_readable_watch_id;\n\tguint rdp_channel_writable_watch_id;\n\tguint monitor_id;\n\tstruct sipe_user_ask_ctx *ask_ctx;\n\n\tgchar rdp_channel_buffer[0x800];\n\tgchar *rdp_channel_buffer_pos;\n\tgsize rdp_channel_buffer_len;\n\n\tstruct sipe_rdp_client client;\n\n#ifdef HAVE_APPSHARE_SERVER\n\trdpShadowServer *server;\n#endif // HAVE_APPSHARE_SERVER\n};\n\nstatic void\nsipe_appshare_free(struct sipe_appshare *appshare)\n{\n\tif (appshare->rdp_channel_readable_watch_id != 0) {\n\t\tg_source_destroy(g_main_context_find_source_by_id(NULL,\n\t\t\t\tappshare->rdp_channel_readable_watch_id));\n\t}\n\n\tif (appshare->rdp_channel_writable_watch_id != 0) {\n\t\tg_source_destroy(g_main_context_find_source_by_id(NULL,\n\t\t\t\tappshare->rdp_channel_writable_watch_id));\n\t}\n\n\tif (appshare->channel) {\n\t\tGError *error = NULL;\n\n\t\tg_io_channel_shutdown(appshare->channel, TRUE, &error);\n\t\tif (error) {\n\t\t\tSIPE_DEBUG_ERROR(\"Error shutting down RDP channel: %s\",\n\t\t\t\t\t error->message);\n\t\t\tg_error_free(error);\n\t\t}\n\t\tg_io_channel_unref(appshare->channel);\n\t}\n\n\tif (appshare->socket) {\n\t\tg_object_unref(appshare->socket);\n\t}\n\n#ifdef HAVE_APPSHARE_SERVER\n\tif (appshare->server) {\n\t\tif (appshare->server->ipcSocket) {\n\t\t\tg_unlink(appshare->server->ipcSocket);\n\t\t}\n\n\t\tshadow_server_stop(appshare->server);\n\t\tshadow_server_uninit(appshare->server);\n\t\tshadow_server_free(appshare->server);\n\t}\n#endif // HAVE_APPSHARE_SERVER\n\n\tif (appshare->ask_ctx) {\n\t\tsipe_user_close_ask(appshare->ask_ctx);\n\t}\n\n\tg_free(appshare->client.cmdline);\n\tif (appshare->client.free_cb) {\n\t\tappshare->client.free_cb(&appshare->client);\n\t}\n\n\tg_free(appshare);\n}\n\nstatic gboolean\nrdp_channel_readable_cb(GIOChannel *channel,\n\t\t\tGIOCondition condition,\n\t\t\tgpointer data)\n{\n\tstruct sipe_appshare *appshare = data;\n\tGError *error = NULL;\n\tgchar *buffer;\n\tgsize bytes_read;\n\n\tif (condition & G_IO_HUP) {\n\t\tstruct sipe_media_call *call = appshare->stream->call;\n\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"Received HUP from RDP client.\");\n\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\treturn FALSE;\n\t}\n\n\tbuffer = g_malloc(2048);\n\twhile (sipe_media_stream_is_writable(appshare->stream)) {\n\t\tGIOStatus status;\n\n\t\tstatus = g_io_channel_read_chars(channel,\n\t\t\t\t\t\t buffer, 2048,\n\t\t\t\t\t\t &bytes_read, &error);\n\t\tif (error) {\n\t\t\tstruct sipe_media_call *call = appshare->stream->call;\n\n\t\t\tSIPE_DEBUG_ERROR(\"Error reading from RDP channel: %s\",\n\t\t\t\t\t error->message);\n\t\t\tg_error_free(error);\n\t\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\t\tg_free(buffer);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (status == G_IO_STATUS_EOF) {\n\t\t\tstruct sipe_media_call *call = appshare->stream->call;\n\n\t\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\t\tg_free(buffer);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (bytes_read == 0) {\n\t\t\tbreak;\n\t\t}\n\n\t\tsipe_media_stream_write(appshare->stream, (guint8 *)buffer,\n\t\t\t\t\tbytes_read);\n\t\tSIPE_DEBUG_INFO(\"Written: %\" G_GSIZE_FORMAT \"\\n\", bytes_read);\n\t}\n\tg_free(buffer);\n\n\treturn TRUE;\n}\n\nstatic gboolean\nsocket_connect_cb(SIPE_UNUSED_PARAMETER GIOChannel *channel,\n\t\t  SIPE_UNUSED_PARAMETER GIOCondition condition,\n\t\t  gpointer data)\n{\n\tstruct sipe_appshare *appshare = data;\n\tGError *error = NULL;\n\tGSocket *data_socket;\n\tint fd;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"RDP client has connected.\");\n\n\tdata_socket = g_socket_accept(appshare->socket, NULL, &error);\n\tif (error) {\n\t\tstruct sipe_media_call *call = appshare->stream->call;\n\n\t\tSIPE_DEBUG_ERROR(\"Error accepting RDP client connection: %s\",\n\t\t\t\t error->message);\n\t\tg_error_free(error);\n\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\treturn FALSE;\n\t}\n\n\tg_io_channel_shutdown(appshare->channel, TRUE, &error);\n\tif (error) {\n\t\tstruct sipe_media_call *call = appshare->stream->call;\n\n\t\tSIPE_DEBUG_ERROR(\"Error shutting down RDP channel: %s\",\n\t\t\t\t error->message);\n\t\tg_error_free(error);\n\t\tg_object_unref(data_socket);\n\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\treturn FALSE;\n\t}\n\tg_io_channel_unref(appshare->channel);\n\n\tg_object_unref(appshare->socket);\n\tappshare->socket = data_socket;\n\n\tfd = g_socket_get_fd(appshare->socket);\n\tif (fd < 0) {\n\t\tstruct sipe_media_call *call = appshare->stream->call;\n\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"Invalid file descriptor for RDP client connection socket\");\n\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\treturn FALSE;\n\t}\n\tappshare->channel = g_io_channel_unix_new(fd);\n\n\t// No encoding for binary data\n\tg_io_channel_set_encoding(appshare->channel, NULL, &error);\n\tif (error) {\n\t\tstruct sipe_media_call *call = appshare->stream->call;\n\n\t\tSIPE_DEBUG_ERROR(\"Error setting RDP channel encoding: %s\",\n\t\t\t\t error->message);\n\t\tg_error_free(error);\n\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\treturn FALSE;\n\t}\n\n\tappshare->rdp_channel_readable_watch_id =\n\t\t\tg_io_add_watch(appshare->channel, G_IO_IN | G_IO_HUP,\n\t\t\t\t       rdp_channel_readable_cb, appshare);\n\n\treturn FALSE;\n}\n\nstatic void\nlaunch_rdp_client(struct sipe_appshare *appshare)\n{\n\tstruct sipe_rdp_client *client = &appshare->client;\n\tstruct sipe_media_call *call = appshare->stream->call;\n\tGSocketAddress *address;\n\tGError *error = NULL;\n\tint fd;\n\n\taddress = client->get_listen_address_cb(client);\n\tif (!address) {\n\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\treturn;\n\t}\n\n\tappshare->socket = g_socket_new(g_socket_address_get_family(address),\n\t\t\t\t\tG_SOCKET_TYPE_STREAM,\n\t\t\t\t\tG_SOCKET_PROTOCOL_DEFAULT,\n\t\t\t\t\t&error);\n\tif (error) {\n\t\tSIPE_DEBUG_ERROR(\"Can't create RDP client listen socket: %s\",\n\t\t\t\t error->message);\n\t\tg_error_free(error);\n\t\tg_object_unref(address);\n\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\treturn;\n\t}\n\n\tg_socket_set_blocking(appshare->socket, FALSE);\n\n\tg_socket_bind(appshare->socket, address, TRUE, &error);\n\tg_object_unref(address);\n\tif (error) {\n\t\tSIPE_DEBUG_ERROR(\"Can't bind to RDP client socket: %s\",\n\t\t\t\t error->message);\n\t\tg_error_free(error);\n\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\treturn;\n\t}\n\n\tg_socket_listen(appshare->socket, &error);\n\tif (error) {\n\t\tSIPE_DEBUG_ERROR(\"Can't listen on RDP client socket: %s\",\n\t\t\t\t error->message);\n\t\tg_error_free(error);\n\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\treturn;\n\t}\n\n\tfd = g_socket_get_fd(appshare->socket);\n\tif (fd < 0) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"Invalid file descriptor for RDP client listen socket\");\n\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\treturn;\n\t}\n\tappshare->channel = g_io_channel_unix_new(fd);\n\n\tappshare->rdp_channel_readable_watch_id =\n\t\t\tg_io_add_watch(appshare->channel, G_IO_IN,\n\t\t\t\t       socket_connect_cb, appshare);\n\n\taddress = g_socket_get_local_address(appshare->socket, &error);\n\tif (error) {\n\t\tSIPE_DEBUG_ERROR(\"Couldn't get appshare socket address: %s\",\n\t\t\t\t error->message);\n\t\tg_error_free(error);\n\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\treturn;\n\t}\n\n\tif (!client->launch_cb(client, address, appshare->stream)) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"Failed to launch RDP client.\");\n\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t}\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"RDP client launched.\");\n\n\tg_object_unref(address);\n}\n\nstatic gssize\nrdp_client_channel_write(struct sipe_appshare *appshare)\n{\n\tgsize bytes_written;\n\tGError *error = NULL;\n\n\tg_io_channel_write_chars(appshare->channel,\n\t\t\t\t appshare->rdp_channel_buffer_pos,\n\t\t\t\t appshare->rdp_channel_buffer_len,\n\t\t\t\t &bytes_written, &error);\n\tif (error) {\n\t\tSIPE_DEBUG_ERROR(\"Couldn't write data to RDP client: %s\",\n\t\t\t\t error->message);\n\t\tg_error_free(error);\n\t\treturn -1;\n\t}\n\n\tg_io_channel_flush(appshare->channel, &error);\n\tif (error) {\n\t\tif (g_error_matches(error, G_IO_CHANNEL_ERROR,\n\t\t\t\t    G_IO_CHANNEL_ERROR_PIPE)) {\n\t\t\t/* Ignore broken pipe here and wait for the call to be\n\t\t\t * hung up upon G_IO_HUP in client_channel_cb(). */\n\t\t\tg_error_free(error);\n\t\t\treturn 0;\n\t\t}\n\n\t\tSIPE_DEBUG_ERROR(\"Couldn't flush RDP channel: %s\",\n\t\t\t\t error->message);\n\t\tg_error_free(error);\n\t\treturn -1;\n\t}\n\n\tappshare->rdp_channel_buffer_pos += bytes_written;\n\tappshare->rdp_channel_buffer_len -= bytes_written;\n\n\treturn bytes_written;\n}\n\nstatic void\ndelayed_hangup_cb(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private,\n\t\t  gpointer data)\n{\n\tstruct sipe_media_call *call = data;\n\n\tsipe_backend_media_hangup(call->backend_private, TRUE);\n}\n\nstatic gboolean\nrdp_channel_writable_cb(SIPE_UNUSED_PARAMETER GIOChannel *channel,\n\t\t\tSIPE_UNUSED_PARAMETER GIOCondition condition,\n\t\t\tgpointer data)\n{\n\tstruct sipe_appshare *appshare = data;\n\tstruct sipe_media_call *call = appshare->stream->call;\n\n\tif (rdp_client_channel_write(appshare) < 0) {\n\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\treturn FALSE;\n\t}\n\n\tif (appshare->rdp_channel_buffer_len == 0) {\n\t\t// Writing done, disconnect writable watch.\n\t\tappshare->rdp_channel_writable_watch_id = 0;\n\t\treturn FALSE;\n\t}\n\n\treturn TRUE;\n}\n\nstatic void\nread_cb(struct sipe_media_stream *stream)\n{\n\tstruct sipe_appshare *appshare = sipe_media_stream_get_data(stream);\n\tgint bytes_read = 0;\n\tgssize bytes_written = 0;\n\n\tif (appshare->rdp_channel_writable_watch_id != 0) {\n\t\t// Data still in the buffer. Let the client read it first.\n\t\treturn;\n\t}\n\n\twhile (bytes_read == (gint)bytes_written) {\n\t\tbytes_read = sipe_backend_media_stream_read(stream,\n\t\t\t\t(guint8 *)appshare->rdp_channel_buffer,\n\t\t\t\tsizeof (appshare->rdp_channel_buffer));\n\t\tif (bytes_read == 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tappshare->rdp_channel_buffer_pos = appshare->rdp_channel_buffer;\n\t\tappshare->rdp_channel_buffer_len = bytes_read;\n\n\t\tbytes_written = rdp_client_channel_write(appshare);\n\n\t\tif (bytes_written < 0) {\n\t\t\t/* Don't deallocate stream while in its read callback.\n\t\t\t * Schedule call hangup to be executed after we're back\n\t\t\t * in the message loop. */\n\t\t\tsipe_schedule_seconds(sipe_media_get_sipe_core_private(stream->call),\n\t\t\t\t\t      \"appshare delayed hangup\",\n\t\t\t\t\t      stream->call->backend_private,\n\t\t\t\t\t      0,\n\t\t\t\t\t      delayed_hangup_cb,\n\t\t\t\t\t      NULL);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (bytes_read != (gint)bytes_written) {\n\t\t/* Schedule writing of the buffer's remainder to when\n\t\t * RDP channel becomes writable again. */\n\t\tappshare->rdp_channel_writable_watch_id =\n\t\t\t\tg_io_add_watch(appshare->channel, G_IO_OUT,\n\t\t\t\t\t       rdp_channel_writable_cb,\n\t\t\t\t\t       appshare);\n\t}\n}\n\nstatic void\nwritable_cb(struct sipe_media_stream *stream)\n{\n\tstruct sipe_appshare *appshare = sipe_media_stream_get_data(stream);\n\n\tif (!appshare->socket) {\n\t\tlaunch_rdp_client(appshare);\n\t}\n}\n\nstatic void\naccept_cb(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private,\n\t  gpointer data)\n{\n\tstruct sipe_appshare *appshare = data;\n\tappshare->ask_ctx = NULL;\n\n\tsipe_backend_media_accept(appshare->stream->call->backend_private, TRUE);\n}\n\nstatic void\ndecline_cb(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private,\n\t  gpointer data)\n{\n\tstruct sipe_appshare *appshare = data;\n\tappshare->ask_ctx = NULL;\n\n\tsipe_backend_media_hangup(appshare->stream->call->backend_private, TRUE);\n}\n\nstatic struct sipe_user_ask_ctx *\nask_accept_applicationsharing(struct sipe_core_private *sipe_private,\n\t\t\t      const gchar *from,\n\t\t\t      SipeUserAskCb accept_cb,\n\t\t\t      SipeUserAskCb decline_cb,\n\t\t\t      gpointer user_data)\n{\n\tstruct sipe_user_ask_ctx *ctx;\n\tgchar *alias = sipe_buddy_get_alias(sipe_private, from);\n\tgchar *ask_msg = g_strdup_printf(_(\"%s wants to start presenting\"),\n\t\t\t\t\t alias ? alias : from);\n\n\tctx = sipe_user_ask(sipe_private, ask_msg,\n\t\t\t     _(\"Accept\"), accept_cb,\n\t\t\t     _(\"Decline\"), decline_cb,\n\t\t\t     user_data);\n\n\tg_free(ask_msg);\n\tg_free(alias);\n\n\treturn ctx;\n}\n\nstatic struct sipe_appshare *\ninitialize_appshare(struct sipe_media_stream *stream)\n{\n\tstruct sipe_appshare *appshare;\n\tstruct sipe_media_call *call;\n\tstruct sipe_core_private *sipe_private;\n\tconst gchar *cmdline;\n\n\tcall = stream->call;\n\tsipe_private = sipe_media_get_sipe_core_private(call);\n\n\tappshare = g_new0(struct sipe_appshare, 1);\n\tappshare->stream = stream;\n\n\tsipe_media_stream_set_data(stream, appshare,\n\t\t\t\t   (GDestroyNotify)sipe_appshare_free);\n\n\tcmdline = sipe_backend_setting(SIPE_CORE_PUBLIC,\n\t\t\t\t       SIPE_SETTING_RDP_CLIENT);\n\tif (is_empty(cmdline))\n\t\tcmdline = \"remmina\";\n\tappshare->client.cmdline = g_strdup(cmdline);\n\n\tif (strstr(cmdline, \"xfreerdp\")) {\n\t\tsipe_appshare_xfreerdp_init(&appshare->client);\n\t} else if (strstr(cmdline, \"remmina\")) {\n\t\tsipe_appshare_remmina_init(&appshare->client);\n\t} else {\n\t\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t  _(\"Application sharing error\"),\n\t\t\t\t\t  _(\"Unknown remote desktop client configured.\"));\n\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\treturn NULL;\n\t}\n\n\tsipe_media_stream_add_extra_attribute(stream,\n\t\t\t\"x-applicationsharing-session-id\", \"1\");\n\tsipe_media_stream_add_extra_attribute(stream,\n\t\t\t\"x-applicationsharing-role\", \"viewer\");\n\tsipe_media_stream_add_extra_attribute(stream,\n\t\t\t\"x-applicationsharing-media-type\", \"rdp\");\n\n\tstream->read_cb = read_cb;\n\tstream->writable_cb = writable_cb;\n\n\treturn appshare;\n}\n\nvoid\nprocess_incoming_invite_appshare(struct sipe_core_private *sipe_private,\n\t\t\t\t struct sipmsg *msg)\n{\n\tstruct sipe_media_call *call;\n\tstruct sipe_media_stream *stream;\n\tstruct sipe_appshare *appshare;\n\tstruct sdpmsg *sdpmsg;\n\tGSList *i;\n\n\tsdpmsg = sdpmsg_parse_msg(msg->body);\n\n\t/* Skype for Business compatibility - ignore desktop video. */\n\ti = sdpmsg->media;\n\twhile (i) {\n\t\tstruct sdpmedia *media = i->data;\n\t\tconst gchar *label;\n\n\t\ti = i->next;\n\n\t\tlabel = sipe_utils_nameval_find(media->attributes, \"label\");\n\n\t\tif (sipe_strequal(media->name, \"video\") &&\n\t\t    sipe_strequal(label, \"applicationsharing-video\")) {\n\t\t\tsdpmsg->media = g_slist_remove(sdpmsg->media, media);\n\t\t\tsdpmedia_free(media);\n\t\t}\n\t}\n\n\tcall = process_incoming_invite_call_parsed_sdp(sipe_private,\n\t\t\t\t\t\t       msg,\n\t\t\t\t\t\t       sdpmsg);\n\tif (!call) {\n\t\treturn;\n\t}\n\n\tstream = sipe_core_media_get_stream_by_id(call, \"applicationsharing\");\n\tif (!stream) {\n\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\treturn;\n\t}\n\n\tappshare = initialize_appshare(stream);\n\n\tif (appshare) {\n\t\tgchar *from = sipmsg_parse_from_address(msg);\n\t\tappshare->ask_ctx = ask_accept_applicationsharing(sipe_private, from,\n\t\t\t\t\t\t\t\t  accept_cb,\n\t\t\t\t\t\t\t\t  decline_cb,\n\t\t\t\t\t\t\t\t  appshare);\n\t\tg_free(from);\n\t}\n}\n\nstatic void\nconnect_conference(struct sipe_core_private *sipe_private,\n\t\t   struct sipe_chat_session *chat_session)\n{\n\tstruct sipe_media_call *call;\n\tstruct sipe_media_stream *stream;\n\tgchar * uri;\n\n\tchat_session->appshare_ask_ctx = NULL;\n\n\turi = sipe_conf_build_uri(chat_session->id, \"applicationsharing\");\n\n\tcall = sipe_media_call_new(sipe_private, uri, NULL,\n\t\t\t\t   SIPE_ICE_RFC_5245,\n\t\t\t\t   SIPE_MEDIA_CALL_NO_UI);\n\n\tg_free(uri);\n\n\tstream = sipe_media_stream_add(call, \"applicationsharing\",\n\t\t\t\t       SIPE_MEDIA_APPLICATION,\n\t\t\t\t       SIPE_ICE_RFC_5245, TRUE, 0);\n\tif (!stream) {\n\t\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t  _(\"Application sharing error\"),\n\t\t\t\t\t  _(\"Couldn't connect application sharing\"));\n\t\tsipe_backend_media_hangup(call->backend_private, FALSE);\n\t}\n\n\tsipe_media_stream_add_extra_attribute(stream, \"connection\", \"new\");\n\tsipe_media_stream_add_extra_attribute(stream, \"setup\", \"active\");\n\n\tinitialize_appshare(stream);\n}\n\nvoid\nsipe_core_appshare_connect_conference(struct sipe_core_public *sipe_public,\n\t\t\t\t      struct sipe_chat_session *chat_session,\n\t\t\t\t      gboolean user_must_accept)\n{\n\tif (user_must_accept) {\n\t\tconst gchar *from;\n\n\t\tif (chat_session->appshare_ask_ctx) {\n\t\t\t// Accept dialog already opened.\n\t\t\treturn;\n\t\t}\n\n\t\tif (chat_session->title) {\n\t\t\tfrom = chat_session->title;\n\t\t} else if (chat_session->organizer) {\n\t\t\tfrom = chat_session->organizer;\n\t\t} else {\n\t\t\tfrom = chat_session->id;\n\t\t}\n\n\t\tchat_session->appshare_ask_ctx =\n\t\t\t\task_accept_applicationsharing(SIPE_CORE_PRIVATE,\n\t\t\t\t\t\t\t      from,\n\t\t\t\t\t\t\t      (SipeUserAskCb)connect_conference,\n\t\t\t\t\t\t\t      NULL,\n\t\t\t\t\t\t\t      chat_session);\n\t} else {\n\t\tconnect_conference(SIPE_CORE_PRIVATE, chat_session);\n\t}\n}\n\nsipe_appshare_role\nsipe_appshare_get_role(struct sipe_media_call *call)\n{\n\tstruct sipe_media_stream *stream;\n\n\tg_return_val_if_fail(call, SIPE_APPSHARE_ROLE_NONE);\n\n\tstream = sipe_core_media_get_stream_by_id(call, \"applicationsharing\");\n\n\tif (stream) {\n\t\tstruct sipe_appshare *appshare;\n\n\t\tappshare = sipe_media_stream_get_data(stream);\n\t\tif (appshare) {\n#ifdef HAVE_APPSHARE_SERVER\n\t\t\treturn appshare->server ? SIPE_APPSHARE_ROLE_PRESENTER :\n\t\t\t\t\t\t  SIPE_APPSHARE_ROLE_VIEWER;\n#else\n\t\t\treturn SIPE_APPSHARE_ROLE_VIEWER;\n#endif // HAVE_APPSHARE_SERVER\n\t\t}\n\t}\n\n\treturn SIPE_APPSHARE_ROLE_NONE;\n}\n\n#ifdef HAVE_APPSHARE_SERVER\n\n/* Limit shared screen size to 2160p. Screen updates of larger monitors might\n * not fit into MultifragMaxRequestSize. */\n#define APPSHARE_MAX_SCREEN_WIDTH 3840\n#define APPSHARE_MAX_SCREEN_HEIGHT 2160\n\nstatic void\nset_shared_display_area(rdpShadowServer *server, guint monitor_id)\n{\n\tMONITOR_DEF monitors[16];\n\tMONITOR_DEF *monitor;\n\tUINT32 monitor_count;\n\n\tmonitor_count = shadow_enum_monitors(monitors, 16);\n\n\tif (monitor_id >= monitor_count) {\n\t\tserver->selectedMonitor = 0;\n\t\treturn;\n\t}\n\n\tserver->selectedMonitor = monitor_id;\n\n\tmonitor = &monitors[monitor_id];\n\tif ((monitor->right - monitor->left) > APPSHARE_MAX_SCREEN_WIDTH ||\n\t    (monitor->bottom - monitor->top) > APPSHARE_MAX_SCREEN_HEIGHT) {\n\t\tserver->subRect.top = 0;\n\t\tserver->subRect.left = 0;\n\t\tserver->subRect.right = MIN(monitor->right - monitor->left,\n\t\t\t\t\t    APPSHARE_MAX_SCREEN_WIDTH);\n\t\tserver->subRect.bottom = MIN(monitor->bottom - monitor->top,\n\t\t\t\t\t     APPSHARE_MAX_SCREEN_HEIGHT);\n\t\tserver->shareSubRect = TRUE;\n\n\t\tSIPE_DEBUG_INFO(\"Cropping the shared screen to %dx%d\",\n\t\t\t\tserver->subRect.right, server->subRect.bottom);\n\t}\n}\n\nstatic void\ncandidate_pairs_established_cb(struct sipe_media_stream *stream)\n{\n\tstruct sipe_appshare *appshare;\n\tGSocketAddress *address;\n\tGError *error = NULL;\n\tstruct sockaddr_un native;\n\trdpShadowServer* server;\n\tconst gchar *server_error = NULL;\n\n\tg_return_if_fail(sipe_strequal(stream->id, \"applicationsharing\"));\n\n\tappshare = sipe_media_stream_get_data(stream);\n\n\tserver = shadow_server_new();\n\tif(!server) {\n\t\tserver_error = _(\"Could not create RDP server.\");\n\t} else {\n\t\tserver->ipcSocket = g_strdup_printf(\"%s/sipe-appshare-%u-%p\",\n\t\t\t\t\t\t    g_get_user_runtime_dir(),\n\t\t\t\t\t\t    getpid(), stream);\n\t\tserver->authentication = FALSE;\n\t\tserver->mayInteract = FALSE;\n\t\tset_shared_display_area(server, appshare->monitor_id);\n\n\t\t/* Experimentally determined cap on multifrag max request size\n\t\t * Lync client would accept. Higher values result in a black\n\t\t * screen being displayed on the remote end.\n\t\t *\n\t\t * See related https://github.com/FreeRDP/FreeRDP/pull/3669. */\n\t\tserver->settings->MultifragMaxRequestSize = 0x3EFFFF;\n\n\t\tif(shadow_server_init(server) < 0) {\n\t\t\tserver_error = _(\"Could not initialize RDP server.\");\n\t\t} else if(shadow_server_start(server) < 0) {\n\t\t\tserver_error = _(\"Could not start RDP server.\");\n\t\t}\n\t}\n\tif (server_error) {\n\t\tstruct sipe_core_private *sipe_private;\n\n\t\tsipe_private = sipe_media_get_sipe_core_private(stream->call);\n\t\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t  _(\"Application sharing error\"),\n\t\t\t\t\t  server_error);\n\t\tsipe_backend_media_hangup(stream->call->backend_private, TRUE);\n\t\tif (server) {\n\t\t\tshadow_server_uninit(server);\n\t\t\tshadow_server_free(server);\n\t\t}\n\t\treturn;\n\t}\n\n\tappshare->server = server;\n\tappshare->socket = g_socket_new(G_SOCKET_FAMILY_UNIX,\n\t\t\t\t\tG_SOCKET_TYPE_STREAM,\n\t\t\t\t\tG_SOCKET_PROTOCOL_DEFAULT,\n\t\t\t\t\t&error);\n\tif (error) {\n\t\tSIPE_DEBUG_ERROR(\"Can't create RDP server socket: %s\",\n\t\t\t\t error->message);\n\t\tg_error_free(error);\n\t\tsipe_backend_media_hangup(stream->call->backend_private, TRUE);\n\t\treturn;\n\t}\n\n\tg_socket_set_blocking(appshare->socket, FALSE);\n\n\tnative.sun_family = AF_LOCAL;\n\tstrncpy(native.sun_path, server->ipcSocket, sizeof (native.sun_path) - 1);\n\tnative.sun_path[sizeof (native.sun_path) - 1] = '\\0';\n\taddress = g_socket_address_new_from_native(&native, sizeof native);\n\n\tg_socket_connect(appshare->socket, address, NULL, &error);\n\tif (error) {\n\t\tSIPE_DEBUG_ERROR(\"Can't connect to RDP server: %s\", error->message);\n\t\tg_error_free(error);\n\t\tsipe_backend_media_hangup(stream->call->backend_private, TRUE);\n\t\treturn;\n\t}\n\n\tappshare->channel = g_io_channel_unix_new(g_socket_get_fd(appshare->socket));\n\n\t// No encoding for binary data\n\tg_io_channel_set_encoding(appshare->channel, NULL, &error);\n\tif (error) {\n\t\tSIPE_DEBUG_ERROR(\"Error setting RDP channel encoding: %s\",\n\t\t\t\t error->message);\n\t\tg_error_free(error);\n\t\tsipe_backend_media_hangup(stream->call->backend_private, TRUE);\n\t\treturn;\n\t}\n\n\tappshare->rdp_channel_readable_watch_id =\n\t\t\tg_io_add_watch(appshare->channel, G_IO_IN | G_IO_HUP,\n\t\t\t\t       rdp_channel_readable_cb, appshare);\n\n\t// Appshare structure initialized; don't call this again.\n\tstream->candidate_pairs_established_cb = NULL;\n}\n\nstatic void\nstop_presenting_cb(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private,\n\t\t   struct sipe_media_call *call)\n{\n\tstruct sipe_media_stream *stream;\n\n\tstream = sipe_core_media_get_stream_by_id(call, \"applicationsharing\");\n\tif (stream) {\n\t\tstruct sipe_appshare *appshare;\n\n\t\tappshare = sipe_media_stream_get_data(stream);\n\t\tif (appshare) {\n\t\t\tappshare->ask_ctx = NULL;\n\t\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\t}\n\t}\n}\n\nstatic struct sipe_user_ask_ctx *\nask_end_presentation(struct sipe_core_private *sipe_private,\n\t\t     const gchar *with,\n\t\t     struct sipe_media_call *call)\n{\n\tstruct sipe_user_ask_ctx *ctx;\n\tgchar *alias = sipe_buddy_get_alias(sipe_private, with);\n\tgchar *ask_msg = g_strdup_printf(_(\"Sharing desktop with %s\"),\n\t\t\t\t\t alias ? alias : with);\n\n\tctx = sipe_user_ask(sipe_private, ask_msg,\n\t\t\t     _(\"Stop presenting\"),\n\t\t\t     (SipeUserAskCb)stop_presenting_cb,\n\t\t\t     NULL,\n\t\t\t     NULL,\n\t\t\t     call);\n\n\tg_free(ask_msg);\n\tg_free(alias);\n\n\treturn ctx;\n}\n\nstatic void\nmonitor_selected_cb(struct sipe_core_private *sipe_private, gchar *with,\n\t\t    guint monitor_id)\n{\n\tstruct sipe_media_call *call;\n\tstruct sipe_media_stream *stream;\n\tstruct sipe_appshare *appshare;\n\n\tif (monitor_id == SIPE_CHOICE_CANCELLED) {\n\t\tg_free(with);\n\t\treturn;\n\t}\n\n\tcall = sipe_media_call_new(sipe_private, with, NULL, SIPE_ICE_RFC_5245,\n\t\t\t\t   SIPE_MEDIA_CALL_INITIATOR |\n\t\t\t\t   SIPE_MEDIA_CALL_NO_UI);\n\n\tstream = sipe_media_stream_add(call, \"applicationsharing\",\n\t\t\t\t       SIPE_MEDIA_APPLICATION,\n\t\t\t\t       SIPE_ICE_RFC_5245, TRUE, 0);\n\tif (!stream) {\n\t\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t_(\"Application sharing error\"),\n\t\t\t\t_(\"Couldn't initialize application sharing\"));\n\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\tg_free(with);\n\t\treturn;\n\t}\n\n\tstream->candidate_pairs_established_cb = candidate_pairs_established_cb;\n\tstream->read_cb = read_cb;\n\n\tsipe_media_stream_add_extra_attribute(stream,\n\t\t\t\t\t      \"mid\",\n\t\t\t\t\t      \"1\");\n\tsipe_media_stream_add_extra_attribute(stream,\n\t\t\t\t\t      \"x-applicationsharing-session-id\",\n\t\t\t\t\t      \"1\");\n\tsipe_media_stream_add_extra_attribute(stream,\n\t\t\t\t\t      \"x-applicationsharing-role\",\n\t\t\t\t\t      \"sharer\");\n\tsipe_media_stream_add_extra_attribute(stream,\n\t\t\t\t\t      \"x-applicationsharing-media-type\",\n\t\t\t\t\t      \"rdp\");\n\n\t// These attributes are mandatory when sharing with a conference.\n\tsipe_media_stream_add_extra_attribute(stream,\n\t\t\t\t\t      \"setup\",\n\t\t\t\t\t      \"active\");\n\tsipe_media_stream_add_extra_attribute(stream,\n\t\t\t\t\t      \"connection\",\n\t\t\t\t\t      \"new\");\n\n\tappshare = g_new0(struct sipe_appshare, 1);\n\tappshare->stream = stream;\n\tappshare->monitor_id = monitor_id;\n\n\tappshare->ask_ctx = ask_end_presentation(sipe_private, with, call);\n\n\tsipe_media_stream_set_data(stream, appshare,\n\t\t\t\t   (GDestroyNotify)sipe_appshare_free);\n\n\tg_free(with);\n}\n\nstatic void\npresent_monitor_choice(struct sipe_core_public *sipe_public, const gchar *who)\n{\n\tMONITOR_DEF monitors[16];\n\tint monitor_count;\n\n\tshadow_subsystem_set_entry_builtin(\"X11\");\n\tmonitor_count = shadow_enum_monitors(monitors, 16);\n\n\tif (monitor_count == 1) {\n\t\t// Skip the choice, use the first (only) display right away.\n\t\tmonitor_selected_cb(SIPE_CORE_PRIVATE, g_strdup(who), 0);\n\t} else {\n\t\tGSList *choices = NULL;\n\t\tint i;\n\n\t\tfor (i = 0; i != monitor_count; ++i) {\n\t\t\tMONITOR_DEF *mon = &monitors[i];\n\t\t\tgchar *str = g_strdup_printf(\"%dx%d @ [%d, %d]\",\n\t\t\t\t\t\t     mon->right - mon->left,\n\t\t\t\t\t\t     mon->bottom - mon->top,\n\t\t\t\t\t\t     mon->left,\n\t\t\t\t\t\t     mon->top);\n\n\t\t\tchoices = g_slist_append(choices, str);\n\t\t}\n\n\t\tsipe_user_ask_choice(SIPE_CORE_PRIVATE, _(\"Monitor to share\"),\n\t\t\t\t     choices,\n\t\t\t\t     (SipeUserAskChoiceCb)monitor_selected_cb,\n\t\t\t\t     g_strdup(who));\n\n\t\tg_slist_free_full(choices, g_free);\n\t}\n}\n\nvoid\nsipe_core_appshare_share_desktop(struct sipe_core_public *sipe_public,\n\t\t\t\t const gchar *with)\n{\n\tpresent_monitor_choice(sipe_public, with);\n}\n\nvoid\nsipe_core_conf_share_desktop(struct sipe_core_public *sipe_public,\n\t\t\t     struct sipe_chat_session *chat_session)\n{\n\tgchar * uri;\n\n\tswitch (sipe_core_conf_get_appshare_role(sipe_public, chat_session)) {\n\t\tcase SIPE_APPSHARE_ROLE_PRESENTER:\n\t\t\t// We are already the presenting.\n\t\t\treturn;\n\t\tcase SIPE_APPSHARE_ROLE_VIEWER: {\n\t\t\t// Close RDP viewer before we start our own presentation.\n\t\t\tgchar *mcu_uri;\n\t\t\tstruct sipe_media_call *call;\n\n\t\t\tmcu_uri = sipe_conf_build_uri(chat_session->id,\n\t\t\t\t\t\t      \"applicationsharing\");\n\t\t\tcall = sipe_media_call_find(SIPE_CORE_PRIVATE, mcu_uri);\n\t\t\tg_free(mcu_uri);\n\n\t\t\tsipe_backend_media_hangup(call->backend_private, TRUE);\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\turi = sipe_conf_build_uri(chat_session->id, \"applicationsharing\");\n\tsipe_core_appshare_share_desktop(sipe_public, uri);\n\n\tg_free(uri);\n}\n\nvoid\nsipe_core_appshare_set_remote_control(struct sipe_media_call * call, gboolean enabled)\n{\n\tstruct sipe_media_stream *stream;\n\n\tstream = sipe_core_media_get_stream_by_id(call, \"applicationsharing\");\n\tif (stream) {\n\t\tstruct sipe_appshare *appshare;\n\n\t\tappshare = sipe_media_stream_get_data(stream);\n\n\t\tif(appshare && appshare->server) {\n\t\t\trdpShadowServer *server = appshare->server;\n\t\t\tint i;\n\n\t\t\tserver->mayInteract = enabled;\n\n\t\t\tArrayList_Lock(server->clients);\n\t\t\tfor (i = 0; i < ArrayList_Count(server->clients); i++) {\n\t\t\t\trdpShadowClient *client;\n\n\t\t\t\tclient = ArrayList_GetItem(server->clients, i);\n\t\t\t\tclient->mayInteract = enabled;\n\t\t\t}\n\t\t\tArrayList_Unlock(server->clients);\n\t\t}\n\t}\n}\n\ngboolean\nsipe_core_appshare_get_remote_control(struct sipe_media_call * call)\n{\n\tstruct sipe_media_stream *stream;\n\n\tstream = sipe_core_media_get_stream_by_id(call, \"applicationsharing\");\n\tif (stream) {\n\t\tstruct sipe_appshare *appshare;\n\n\t\tappshare = sipe_media_stream_get_data(stream);\n\n\t\tif(appshare && appshare->server) {\n\t\t\treturn appshare->server->mayInteract;\n\t\t}\n\t}\n\n\treturn FALSE;\n}\n#endif // HAVE_APPSHARE_SERVER\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-appshare.h",
    "content": "/**\n * @file sipe-appshare.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2014-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\nstruct sipe_media_call;\nstruct sipmsg;\n\nvoid process_incoming_invite_appshare(struct sipe_core_private *sipe_private,\n\t\t\t\t      struct sipmsg *msg);\n\nsipe_appshare_role sipe_appshare_get_role(struct sipe_media_call *call);\n"
  },
  {
    "path": "src/core/sipe-buddy.c",
    "content": "/**\n * @file sipe-buddy.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n * GetUserPhoto operation\n *  <http://msdn.microsoft.com/en-us/library/office/jj900502.aspx>\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipmsg.h\"\n#include \"sip-csta.h\"\n#include \"sip-soap.h\"\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-buddy.h\"\n#include \"sipe-cal.h\"\n#include \"sipe-chat.h\"\n#include \"sipe-conf.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-appshare.h\"\n#include \"sipe-digest.h\"\n#include \"sipe-group.h\"\n#include \"sipe-http.h\"\n#include \"sipe-im.h\"\n#include \"sipe-media.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-ocs2005.h\"\n#include \"sipe-ocs2007.h\"\n#include \"sipe-schedule.h\"\n#include \"sipe-session.h\"\n#include \"sipe-status.h\"\n#include \"sipe-subscriptions.h\"\n#include \"sipe-svc.h\"\n#include \"sipe-ucs.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-webticket.h\"\n#include \"sipe-xml.h\"\n\nstruct sipe_buddies {\n\tGHashTable *uri;\n\tGHashTable *exchange_key;\n\n\t/* Pending photo download HTTP requests */\n\tGSList *pending_photo_requests;\n};\n\nstruct buddy_group_data {\n\tconst struct sipe_group *group;\n\tgboolean is_obsolete;\n};\n\nstruct photo_response_data {\n\tgchar *who;\n\tgchar *photo_hash;\n\tstruct sipe_http_request *request;\n};\n\nstatic void buddy_fetch_photo(struct sipe_core_private *sipe_private,\n\t\t\t      const gchar *uri);\nstatic void photo_response_data_free(struct photo_response_data *data);\n\nvoid sipe_buddy_add_keys(struct sipe_core_private *sipe_private,\n\t\t\t struct sipe_buddy *buddy,\n\t\t\t const gchar *exchange_key,\n\t\t\t const gchar *change_key)\n{\n\tif (exchange_key) {\n\t\tbuddy->exchange_key = g_strdup(exchange_key);\n\t\tg_hash_table_insert(sipe_private->buddies->exchange_key,\n\t\t\t\t    buddy->exchange_key,\n\t\t\t\t    buddy);\n\t}\n\tif (change_key)\n\t\tbuddy->change_key = g_strdup(change_key);\n}\n\nstruct sipe_buddy *sipe_buddy_add(struct sipe_core_private *sipe_private,\n\t\t\t\t  const gchar *uri,\n\t\t\t\t  const gchar *exchange_key,\n\t\t\t\t  const gchar *change_key)\n{\n\t/* Buddy name must be lower case as we use purple_normalize_nocase() to compare */\n\tgchar *normalized_uri = g_ascii_strdown(uri, -1);\n\tstruct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private,\n\t\t\t\t\t\t\t  normalized_uri);\n\n\tif (!buddy) {\n\t\tbuddy = g_new0(struct sipe_buddy, 1);\n\t\tbuddy->name = normalized_uri;\n\t\tg_hash_table_insert(sipe_private->buddies->uri,\n\t\t\t\t    buddy->name,\n\t\t\t\t    buddy);\n\n\t\tsipe_buddy_add_keys(sipe_private,\n\t\t\t\t    buddy,\n\t\t\t\t    exchange_key,\n\t\t\t\t    change_key);\n\n\t\tSIPE_DEBUG_INFO(\"sipe_buddy_add: Added buddy %s\", normalized_uri);\n\n\t\tif (SIPE_CORE_PRIVATE_FLAG_IS(SUBSCRIBED_BUDDIES)) {\n\t\t\tbuddy->just_added = TRUE;\n\t\t\tsipe_subscribe_presence_single_cb(sipe_private,\n\t\t\t\t\t\t\t  buddy->name);\n\t\t}\n\n\t\tbuddy_fetch_photo(sipe_private, normalized_uri);\n\n\t\tnormalized_uri = NULL; /* buddy takes ownership */\n\t} else {\n\t\tSIPE_DEBUG_INFO(\"sipe_buddy_add: Buddy %s already exists\", normalized_uri);\n\t\tbuddy->is_obsolete = FALSE;\n\t}\n\tg_free(normalized_uri);\n\n\treturn(buddy);\n}\n\nstatic gboolean is_buddy_in_group(struct sipe_buddy *buddy,\n\t\t\t\t  const gchar *name)\n{\n\tif (buddy) {\n\t\tGSList *entry = buddy->groups;\n\n\t\twhile (entry) {\n\t\t\tstruct buddy_group_data *bgd = entry->data;\n\t\t\tif (sipe_strequal(bgd->group->name, name)) {\n\t\t\t\tbgd->is_obsolete = FALSE;\n\t\t\t\treturn(TRUE);\n\t\t\t}\n\t\t\tentry = entry->next;\n\t\t}\n\t}\n\n\treturn(FALSE);\n}\n\nvoid sipe_buddy_add_to_group(struct sipe_core_private *sipe_private,\n\t\t\t     struct sipe_buddy *buddy,\n\t\t\t     struct sipe_group *group,\n\t\t\t     const gchar *alias)\n{\n\tconst gchar *uri = buddy->name;\n\tconst gchar *group_name = group->name;\n\tsipe_backend_buddy bb = sipe_backend_buddy_find(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\turi,\n\t\t\t\t\t\t\tgroup_name);\n\n\tif (!bb) {\n\t\tbb = sipe_backend_buddy_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t    uri,\n\t\t\t\t\t    alias,\n\t\t\t\t\t    group_name);\n\t\tSIPE_DEBUG_INFO(\"sipe_buddy_add_to_group: created backend buddy '%s' with alias '%s'\",\n\t\t\t\turi, alias ? alias : \"<NONE>\");\n\t}\n\n\n\tif (!is_empty(alias)) {\n\t\tgchar *old_alias = sipe_backend_buddy_get_alias(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\tbb);\n\n\t\tif (sipe_strcase_equal(sipe_get_no_sip_uri(uri),\n\t\t\t\t       old_alias)) {\n\t\t\tsipe_backend_buddy_set_alias(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t     bb,\n\t\t\t\t\t\t     alias);\n\t\t\tSIPE_DEBUG_INFO(\"sipe_buddy_add_to_group: replaced alias for buddy '%s': old '%s' new '%s'\",\n\t\t\t\t\turi, old_alias, alias);\n\t\t}\n\t\tg_free(old_alias);\n\t}\n\n\tif (!is_buddy_in_group(buddy, group_name)) {\n\t\tsipe_buddy_insert_group(buddy, group);\n\t\tSIPE_DEBUG_INFO(\"sipe_buddy_add_to_group: added buddy %s to group %s\",\n\t\t\t\turi, group_name);\n\t}\n}\n\nstatic gint buddy_group_compare(gconstpointer a, gconstpointer b)\n{\n\treturn(((const struct buddy_group_data *)a)->group->id -\n\t       ((const struct buddy_group_data *)b)->group->id);\n}\n\nvoid sipe_buddy_insert_group(struct sipe_buddy *buddy,\n\t\t\t     struct sipe_group *group)\n{\n\tstruct buddy_group_data *bgd = g_new0(struct buddy_group_data, 1);\n\n\tbgd->group = group;\n\n\tbuddy->groups = sipe_utils_slist_insert_unique_sorted(buddy->groups,\n\t\t\t\t\t\t\t      bgd,\n\t\t\t\t\t\t\t      buddy_group_compare,\n\t\t\t\t\t\t\t      NULL);\n}\n\nstatic void buddy_group_free(gpointer data)\n{\n\tg_free(data);\n}\n\nstatic void buddy_group_remove(struct sipe_buddy *buddy,\n\t\t\t       struct buddy_group_data *bgd)\n{\n\tbuddy->groups = g_slist_remove(buddy->groups, bgd);\n\tbuddy_group_free(bgd);\n}\n\nstatic void sipe_buddy_remove_group(struct sipe_buddy *buddy,\n\t\t\t\t    const struct sipe_group *group)\n{\n\tGSList *entry = buddy->groups;\n\tstruct buddy_group_data *bgd = NULL;\n\n\twhile (entry) {\n\t\tbgd = entry->data;\n\t\tif (bgd->group == group)\n\t\t\tbreak;\n\t\tentry = entry->next;\n\t}\n\n\tbuddy_group_remove(buddy, bgd);\n}\n\nvoid sipe_buddy_update_groups(struct sipe_core_private *sipe_private,\n\t\t\t      struct sipe_buddy *buddy,\n\t\t\t      GSList *new_groups)\n{\n\tconst gchar *uri = buddy->name;\n\tGSList *entry = buddy->groups;\n\n\twhile (entry) {\n\t\tstruct buddy_group_data *bgd = entry->data;\n\t\tconst struct sipe_group *group = bgd->group;\n\n\t\t/* next buddy group */\n\t\tentry = entry->next;\n\n\t\t/* old group NOT found in new list? */\n\t\tif (g_slist_find(new_groups, group) == NULL) {\n\t\t\tsipe_backend_buddy oldb = sipe_backend_buddy_find(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\t  uri,\n\t\t\t\t\t\t\t\t\t  group->name);\n\t\t\tSIPE_DEBUG_INFO(\"sipe_buddy_update_groups: removing buddy %s from group '%s'\",\n\t\t\t\t\turi, group->name);\n\t\t\t/* this should never be NULL */\n\t\t\tif (oldb)\n\t\t\t\tsipe_backend_buddy_remove(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t  oldb);\n\t\t\tbuddy_group_remove(buddy, bgd);\n\t\t}\n\t}\n}\n\ngchar *sipe_buddy_groups_string(struct sipe_buddy *buddy)\n{\n\tguint i = 0;\n\tgchar *string;\n\t/* creating array from GList, converting guint to gchar * */\n\tgchar **ids_arr = g_new(gchar *, g_slist_length(buddy->groups) + 1);\n\tGSList *entry = buddy->groups;\n\n\tif (!ids_arr)\n\t\treturn(NULL);\n\n\twhile (entry) {\n\t\tconst struct sipe_group *group = ((struct buddy_group_data *) entry->data)->group;\n\t\tids_arr[i] = g_strdup_printf(\"%u\", group->id);\n\t\tentry = entry->next;\n\t\ti++;\n\t}\n\tids_arr[i] = NULL;\n\n\tstring = g_strjoinv(\" \", ids_arr);\n\tg_strfreev(ids_arr);\n\n\treturn(string);\n}\n\nvoid sipe_buddy_cleanup_local_list(struct sipe_core_private *sipe_private)\n{\n\tGSList *buddies = sipe_backend_buddy_find_all(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t      NULL,\n\t\t\t\t\t\t      NULL);\n\tGSList *entry = buddies;\n\n\tSIPE_DEBUG_INFO(\"sipe_buddy_cleanup_local_list: overall %d backend buddies (including clones)\",\n\t\t\tg_slist_length(buddies));\n\tSIPE_DEBUG_INFO(\"sipe_buddy_cleanup_local_list: %d sipe buddies (unique)\",\n\t\t\tsipe_buddy_count(sipe_private));\n\twhile (entry) {\n\t\tsipe_backend_buddy bb = entry->data;\n\t\tgchar *bname = sipe_backend_buddy_get_name(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t   bb);\n\t\tgchar *gname = sipe_backend_buddy_get_group_name(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t bb);\n\t\tstruct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private,\n\t\t\t\t\t\t\t\t  bname);\n\n\t\tif (!is_buddy_in_group(buddy, gname)) {\n\t\t\tSIPE_DEBUG_INFO(\"sipe_buddy_cleanup_local_list: REMOVING '%s' from local group '%s', as buddy is not in that group on remote contact list\",\n\t\t\t\t\tbname, gname);\n\t\t\tsipe_backend_buddy_remove(SIPE_CORE_PUBLIC, bb);\n\t\t}\n\n\t\tg_free(gname);\n\t\tg_free(bname);\n\n\t\tentry = entry->next;\n\t}\n\n\tg_slist_free(buddies);\n}\n\nstruct sipe_buddy *sipe_buddy_find_by_uri(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  const gchar *uri)\n{\n\tif (!uri) return(NULL);\n\treturn(g_hash_table_lookup(sipe_private->buddies->uri, uri));\n}\n\nstruct sipe_buddy *sipe_buddy_find_by_exchange_key(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t   const gchar *exchange_key)\n{\n\treturn(g_hash_table_lookup(sipe_private->buddies->exchange_key,\n\t\t\t\t   exchange_key));\n}\n\nvoid sipe_buddy_foreach(struct sipe_core_private *sipe_private,\n\t\t\tGHFunc callback,\n\t\t\tgpointer callback_data)\n{\n\tg_hash_table_foreach(sipe_private->buddies->uri,\n\t\t\t     callback,\n\t\t\t     callback_data);\n}\n\nstatic void buddy_free(struct sipe_buddy *buddy)\n{\n#ifndef _WIN32\n\t /*\n\t  * We are calling g_hash_table_foreach_steal(). That means that no\n\t  * key/value deallocation functions are called. Therefore the glib\n\t  * hash code does not touch the key (buddy->name) or value (buddy)\n\t  * of the to-be-deleted hash node at all. It follows that we\n\t  *\n\t  *   - MUST free the memory for the key ourselves and\n\t  *   - ARE allowed to do it in this function\n\t  *\n\t  * Conclusion: glib must be broken on the Windows platform if sipe\n\t  *             crashes with SIGTRAP when closing. You'll have to live\n\t  *             with the memory leak until this is fixed.\n\t  */\n\tg_free(buddy->name);\n#endif\n\tg_free(buddy->exchange_key);\n\tg_free(buddy->change_key);\n\tg_free(buddy->activity);\n\tg_free(buddy->meeting_subject);\n\tg_free(buddy->meeting_location);\n\tg_free(buddy->note);\n\n\tg_free(buddy->cal_start_time);\n\tg_free(buddy->cal_free_busy_base64);\n\tg_free(buddy->cal_free_busy);\n\tg_free(buddy->last_non_cal_activity);\n\n\tsipe_cal_free_working_hours(buddy->cal_working_hours);\n\n\tg_free(buddy->device_name);\n\tsipe_utils_slist_free_full(buddy->groups, buddy_group_free);\n\tg_free(buddy);\n}\n\nstatic gboolean buddy_free_cb(SIPE_UNUSED_PARAMETER gpointer key,\n\t\t\t      gpointer buddy,\n\t\t\t      SIPE_UNUSED_PARAMETER gpointer user_data)\n{\n\tbuddy_free(buddy);\n\t/* We must return TRUE as the key/value have already been deleted */\n\treturn(TRUE);\n}\n\nvoid sipe_buddy_free(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_buddies *buddies = sipe_private->buddies;\n\n\tg_hash_table_foreach_steal(buddies->uri,\n\t\t\t\t   buddy_free_cb,\n\t\t\t\t   NULL);\n\n\t/* core is being deallocated, remove all its pending photo requests */\n\twhile (buddies->pending_photo_requests) {\n\t\tstruct photo_response_data *data =\n\t\t\tbuddies->pending_photo_requests->data;\n\t\tbuddies->pending_photo_requests =\n\t\t\tg_slist_remove(buddies->pending_photo_requests, data);\n\t\tphoto_response_data_free(data);\n\t}\n\n\tg_hash_table_destroy(buddies->uri);\n\tg_hash_table_destroy(buddies->exchange_key);\n\tg_free(buddies);\n\tsipe_private->buddies = NULL;\n}\n\nstatic void buddy_set_obsolete_flag(SIPE_UNUSED_PARAMETER gpointer key,\n\t\t\t\t    gpointer value,\n\t\t\t\t    SIPE_UNUSED_PARAMETER gpointer user_data)\n{\n\tstruct sipe_buddy *buddy = value;\n\tGSList *entry = buddy->groups;\n\n\tbuddy->is_obsolete = TRUE;\n\twhile (entry) {\n\t\t((struct buddy_group_data *) entry->data)->is_obsolete = TRUE;\n\t\tentry = entry->next;\n\t}\n}\n\nvoid sipe_buddy_update_start(struct sipe_core_private *sipe_private)\n{\n\tg_hash_table_foreach(sipe_private->buddies->uri,\n\t\t\t     buddy_set_obsolete_flag,\n\t\t\t     NULL);\n}\n\nstatic gboolean buddy_check_obsolete_flag(SIPE_UNUSED_PARAMETER gpointer key,\n\t\t\t\t\t  gpointer value,\n\t\t\t\t\t  gpointer user_data)\n{\n\tstruct sipe_core_private *sipe_private = user_data;\n\tstruct sipe_buddy *buddy = value;\n\tconst gchar *uri = buddy->name;\n\n\tif (buddy->is_obsolete) {\n\t\t/* all backend buddies in different groups */\n\t\tGSList *buddies = sipe_backend_buddy_find_all(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t      uri,\n\t\t\t\t\t\t\t      NULL);\n\t\tGSList *entry = buddies;\n\n\t\tSIPE_DEBUG_INFO(\"buddy_check_obsolete_flag: REMOVING %d backend buddies for '%s'\",\n\t\t\t\tg_slist_length(buddies),\n\t\t\t\turi);\n\n\t\twhile (entry) {\n\t\t\tsipe_backend_buddy_remove(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t  entry->data);\n\t\t\tentry = entry->next;\n\t\t}\n\t\tg_slist_free(buddies);\n\n\t\tbuddy_free(buddy);\n\t\t/* return TRUE as the key/value have already been deleted */\n\t\treturn(TRUE);\n\n\t} else {\n\t\tGSList *entry = buddy->groups;\n\n\t\twhile (entry) {\n\t\t\tstruct buddy_group_data *bgd = entry->data;\n\n\t\t\t/* next buddy group */\n\t\t\tentry = entry->next;\n\n\t\t\tif (bgd->is_obsolete) {\n\t\t\t\tconst struct sipe_group *group = bgd->group;\n\t\t\t\tsipe_backend_buddy oldb = sipe_backend_buddy_find(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\t\t  uri,\n\t\t\t\t\t\t\t\t\t\t  group->name);\n\t\t\t\tSIPE_DEBUG_INFO(\"buddy_check_obsolete_flag: removing buddy '%s' from group '%s'\",\n\t\t\t\t\t\turi, group->name);\n\t\t\t\t/* this should never be NULL */\n\t\t\t\tif (oldb)\n\t\t\t\t\tsipe_backend_buddy_remove(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t  oldb);\n\t\t\t\tbuddy_group_remove(buddy, bgd);\n\t\t\t}\n\t\t}\n\t\treturn(FALSE);\n\t}\n}\n\nvoid sipe_buddy_update_finish(struct sipe_core_private *sipe_private)\n{\n\tg_hash_table_foreach_remove(sipe_private->buddies->uri,\n\t\t\t\t    buddy_check_obsolete_flag,\n\t\t\t\t    sipe_private);\n}\n\ngchar *sipe_core_buddy_status(struct sipe_core_public *sipe_public,\n\t\t\t      const gchar *uri,\n\t\t\t      guint activity,\n\t\t\t      const gchar *status_text)\n{\n\tstruct sipe_buddy *sbuddy;\n\tGString *status;\n\n\tif (!sipe_public) return NULL; /* happens on pidgin exit */\n\n\tsbuddy = sipe_buddy_find_by_uri(SIPE_CORE_PRIVATE, uri);\n\tif (!sbuddy) return NULL;\n\n\tstatus = g_string_new(sbuddy->activity ? sbuddy->activity :\n\t\t\t      (activity == SIPE_ACTIVITY_BUSY) || (activity == SIPE_ACTIVITY_BRB) ?\n\t\t\t      status_text : NULL);\n\n\tif (sbuddy->is_mobile) {\n\t\tif (status->len)\n\t\t\tg_string_append(status, \" - \");\n\t\tg_string_append(status, _(\"Mobile\"));\n\t}\n\n\tif (sbuddy->note) {\n\t\tif (status->len)\n\t\t\tg_string_append(status, \" - \");\n\t\tg_string_append(status, sbuddy->note);\n\t}\n\n\t/* return NULL instead of empty status text */\n\treturn(g_string_free(status, status->len ? FALSE : TRUE));\n}\n\ngchar *sipe_buddy_get_alias(struct sipe_core_private *sipe_private,\n\t\t\t    const gchar *with)\n{\n\tsipe_backend_buddy pbuddy;\n\tgchar *alias = NULL;\n\tif ((pbuddy = sipe_backend_buddy_find(SIPE_CORE_PUBLIC, with, NULL))) {\n\t\talias = sipe_backend_buddy_get_alias(SIPE_CORE_PUBLIC, pbuddy);\n\t}\n\treturn alias;\n}\n\nvoid sipe_core_buddy_group(struct sipe_core_public *sipe_public,\n\t\t\t   const gchar *who,\n\t\t\t   const gchar *old_group_name,\n\t\t\t   const gchar *new_group_name)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tstruct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private,\n\t\t\t\t\t\t\t  who);\n\tstruct sipe_group *old_group = NULL;\n\tstruct sipe_group *new_group;\n\tstruct sipe_ucs_transaction *ucs_trans = NULL;\n\n\tSIPE_DEBUG_INFO(\"sipe_core_buddy_group: buddy '%s' old group '%s' new group '%s'\",\n\t\t\twho ? who : \"\",\n\t\t\told_group_name ? old_group_name : \"<UNDEFINED>\",\n\t\t\tnew_group_name ? new_group_name : \"<UNDEFINED>\");\n\n\tif (!buddy)\n\t\t/* buddy not in roaming list */\n\t\treturn;\n\n\told_group = sipe_group_find_by_name(sipe_private, old_group_name);\n\tif (old_group) {\n\t\tsipe_buddy_remove_group(buddy, old_group);\n\t\tSIPE_DEBUG_INFO(\"sipe_core_buddy_group: buddy '%s' removed from old group '%s'\",\n\t\t\t\twho, old_group_name);\n\t}\n\n\tnew_group = sipe_group_find_by_name(sipe_private, new_group_name);\n\tif (new_group) {\n\t\tsipe_buddy_insert_group(buddy, new_group);\n\t\tSIPE_DEBUG_INFO(\"sipe_core_buddy_group: buddy '%s' added to new group '%s'\",\n\t\t\t\twho, new_group_name);\n\t}\n\n\tif (sipe_ucs_is_migrated(sipe_private)) {\n\n\t\t/* UCS handling */\n\t\tucs_trans = sipe_ucs_transaction(sipe_private);\n\n\t\tif (new_group) {\n\t\t\t/*\n\t\t\t * 1. new buddy added to existing group\n\t\t\t * 2. existing buddy moved from old to existing group\n\t\t\t */\n\t\t\tsipe_ucs_group_add_buddy(sipe_private,\n\t\t\t\t\t\t ucs_trans,\n\t\t\t\t\t\t new_group,\n\t\t\t\t\t\t buddy,\n\t\t\t\t\t\t buddy->name);\n\t\t\tif (old_group)\n\t\t\t\tsipe_ucs_group_remove_buddy(sipe_private,\n\t\t\t\t\t\t\t    ucs_trans,\n\t\t\t\t\t\t\t    old_group,\n\t\t\t\t\t\t\t    buddy);\n\n\t\t} else if (old_group) {\n\t\t\t/*\n\t\t\t * 3. existing buddy removed from one of its groups\n\t\t\t * 4. existing buddy removed from last group\n\t\t\t */\n\t\t\tsipe_ucs_group_remove_buddy(sipe_private,\n\t\t\t\t\t\t    ucs_trans,\n\t\t\t\t\t\t    old_group,\n\t\t\t\t\t\t    buddy);\n\t\t\tif (g_slist_length(buddy->groups) < 1)\n\t\t\t\tsipe_buddy_remove(sipe_private,\n\t\t\t\t\t\t  buddy);\n\t\t\t\t/* buddy no longer valid */\n\t\t}\n\n\t/* non-UCS handling */\n\t} else if (new_group)\n\t\tsipe_group_update_buddy(sipe_private, buddy);\n\n\t/* 5. buddy added to new group */\n\tif (!new_group)\n\t\tsipe_group_create(sipe_private,\n\t\t\t\t  ucs_trans,\n\t\t\t\t  new_group_name,\n\t\t\t\t  who);\n}\n\nvoid sipe_core_buddy_add(struct sipe_core_public *sipe_public,\n\t\t\t const gchar *uri,\n\t\t\t const gchar *group_name)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\n\tif (!sipe_buddy_find_by_uri(sipe_private, uri))\n\t\tsipe_buddy_add(sipe_private,\n\t\t\t       uri,\n\t\t\t       NULL,\n\t\t\t       NULL);\n\telse\n\t\tSIPE_DEBUG_INFO(\"sipe_core_buddy_add: buddy %s already in internal list\",\n\t\t\t\turi);\n\n\tsipe_core_buddy_group(sipe_public,\n\t\t\t      uri,\n\t\t\t      NULL,\n\t\t\t      group_name);\n}\n\nvoid sipe_buddy_remove(struct sipe_core_private *sipe_private,\n\t\t       struct sipe_buddy *buddy)\n{\n\tstruct sipe_buddies *buddies = sipe_private->buddies;\n\tconst gchar *uri = buddy->name;\n\tGSList *entry = buddy->groups;\n\tgchar *action_name = sipe_utils_presence_key(uri);\n\n\tsipe_schedule_cancel(sipe_private, action_name);\n\tg_free(action_name);\n\n\t/* If the buddy still has groups, we need to delete backend buddies */\n\twhile (entry) {\n\t\tconst struct sipe_group *group = ((struct buddy_group_data *) entry->data)->group;\n\t\tsipe_backend_buddy oldb = sipe_backend_buddy_find(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t  uri,\n\t\t\t\t\t\t\t\t  group->name);\n\t\t/* this should never be NULL */\n\t\tif (oldb)\n\t\t\tsipe_backend_buddy_remove(SIPE_CORE_PUBLIC, oldb);\n\n\t\tentry = entry->next;\n\t}\n\n\tg_hash_table_remove(buddies->uri, uri);\n\tif (buddy->exchange_key)\n\t\tg_hash_table_remove(buddies->exchange_key,\n\t\t\t\t    buddy->exchange_key);\n\n\tbuddy_free(buddy);\n}\n\n/**\n * Unassociates buddy from group first.\n * Then see if no groups left, removes buddy completely.\n * Otherwise updates buddy groups on server.\n */\nvoid sipe_core_buddy_remove(struct sipe_core_public *sipe_public,\n\t\t\t    const gchar *uri,\n\t\t\t    const gchar *group_name)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tstruct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private,\n\t\t\t\t\t\t\t  uri);\n\tstruct sipe_group *group = NULL;\n\n\tif (!buddy) return;\n\n\tif (group_name) {\n\t\tgroup = sipe_group_find_by_name(sipe_private, group_name);\n\t\tif (group) {\n\t\t\tsipe_buddy_remove_group(buddy, group);\n\t\t\tSIPE_DEBUG_INFO(\"sipe_core_buddy_remove: buddy '%s' removed from group '%s'\",\n\t\t\t\t\turi, group->name);\n\t\t}\n\t}\n\n\tif (g_slist_length(buddy->groups) < 1) {\n\n\t\tif (sipe_ucs_is_migrated(sipe_private)) {\n\t\t\tsipe_ucs_group_remove_buddy(sipe_private,\n\t\t\t\t\t\t    NULL,\n\t\t\t\t\t\t    group,\n\t\t\t\t\t\t    buddy);\n\t\t} else {\n\t\t\tgchar *request = g_strdup_printf(\"<m:URI>%s</m:URI>\",\n\t\t\t\t\t\t\t buddy->name);\n\t\t\tsip_soap_request(sipe_private,\n\t\t\t\t\t \"deleteContact\",\n\t\t\t\t\t request);\n\t\t\tg_free(request);\n\t\t}\n\n\t\tsipe_buddy_remove(sipe_private, buddy);\n\t} else {\n\t\tif (sipe_ucs_is_migrated(sipe_private)) {\n\t\t\tsipe_ucs_group_remove_buddy(sipe_private,\n\t\t\t\t\t\t    NULL,\n\t\t\t\t\t\t    group,\n\t\t\t\t\t\t    buddy);\n\t\t} else\n\t\t\t/* updates groups on server */\n\t\t\tsipe_group_update_buddy(sipe_private, buddy);\n\t}\n}\n\nvoid sipe_core_buddy_got_status(struct sipe_core_public *sipe_public,\n\t\t\t\tconst gchar *uri,\n\t\t\t\tguint activity,\n\t                        time_t last_active)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tstruct sipe_buddy *sbuddy = sipe_buddy_find_by_uri(sipe_private,\n\t\t\t\t\t\t\t   uri);\n\n\tif (!sbuddy) return;\n\n\t/* Check if on 2005 system contact's calendar,\n\t * then set/preserve it.\n\t */\n\tif (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {\n\t\tsipe_backend_buddy_set_status(sipe_public,\n\t\t\t\t\t      uri,\n\t\t\t\t\t      activity,\n\t\t\t                      last_active);\n\t} else {\n\t\tsipe_ocs2005_apply_calendar_status(sipe_private,\n\t\t\t\t\t\t   sbuddy,\n\t\t\t\t\t\t   sipe_status_activity_to_token(activity));\n\t}\n}\n\nvoid sipe_core_buddy_tooltip_info(struct sipe_core_public *sipe_public,\n\t\t\t\t  const gchar *uri,\n\t\t\t\t  const gchar *status_name,\n\t\t\t\t  gboolean is_online,\n\t\t\t\t  struct sipe_backend_buddy_tooltip *tooltip)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tgchar *note = NULL;\n\tgboolean is_oof_note = FALSE;\n\tconst gchar *activity = NULL;\n\tgchar *calendar = NULL;\n\tconst gchar *meeting_subject = NULL;\n\tconst gchar *meeting_location = NULL;\n\tgchar *access_text = NULL;\n\n#define SIPE_ADD_BUDDY_INFO(l, t) \\\n\t{ \\\n\t\tgchar *tmp = g_markup_escape_text((t), -1); \\\n\t\tsipe_backend_buddy_tooltip_add(sipe_public, tooltip, (l), tmp); \\\n\t\tg_free(tmp); \\\n\t}\n#define SIPE_ADD_BUDDY_INFO_NOESCAPE(l, t) \\\n\tsipe_backend_buddy_tooltip_add(sipe_public, tooltip, (l), (t))\n\n\tif (sipe_public) { /* happens on pidgin exit */\n\t\tstruct sipe_buddy *sbuddy = sipe_buddy_find_by_uri(sipe_private,\n\t\t\t\t\t\t\t\t   uri);\n\t\tif (sbuddy) {\n\t\t\tnote = sbuddy->note;\n\t\t\tis_oof_note = sbuddy->is_oof_note;\n\t\t\tactivity = sbuddy->activity;\n\t\t\tcalendar = sipe_cal_get_description(sbuddy);\n\t\t\tmeeting_subject = sbuddy->meeting_subject;\n\t\t\tmeeting_location = sbuddy->meeting_location;\n\t\t}\n\t\tif (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {\n\t\t\tgboolean is_group_access = FALSE;\n\t\t\tconst int container_id = sipe_ocs2007_find_access_level(sipe_private,\n\t\t\t\t\t\t\t\t\t\t\"user\",\n\t\t\t\t\t\t\t\t\t\tsipe_get_no_sip_uri(uri),\n\t\t\t\t\t\t\t\t\t\t&is_group_access);\n\t\t\tconst char *access_level = sipe_ocs2007_access_level_name(container_id);\n\t\t\taccess_text = is_group_access ?\n\t\t\t\tg_strdup(access_level) :\n\t\t\t\tg_strdup_printf(SIPE_OCS2007_INDENT_MARKED_FMT,\n\t\t\t\t\t\taccess_level);\n\t\t}\n\t}\n\n\tif (is_online) {\n\t\tconst gchar *status_str = activity ? activity : status_name;\n\n\t\tSIPE_ADD_BUDDY_INFO(_(\"Status\"), status_str);\n\t}\n\tif (is_online && !is_empty(calendar)) {\n\t\tSIPE_ADD_BUDDY_INFO(_(\"Calendar\"), calendar);\n\t}\n\tg_free(calendar);\n\tif (!is_empty(meeting_location)) {\n\t\tSIPE_DEBUG_INFO(\"sipe_tooltip_text: %s meeting location: '%s'\", uri, meeting_location);\n\t\tSIPE_ADD_BUDDY_INFO(_(\"Meeting in\"), meeting_location);\n\t}\n\tif (!is_empty(meeting_subject)) {\n\t\tSIPE_DEBUG_INFO(\"sipe_tooltip_text: %s meeting subject: '%s'\", uri, meeting_subject);\n\t\tSIPE_ADD_BUDDY_INFO(_(\"Meeting about\"), meeting_subject);\n\t}\n\tif (note) {\n\t\tgchar *note_italics = g_strdup_printf(\"<i>%s</i>\", note);\n\t\tSIPE_DEBUG_INFO(\"sipe_tooltip_text: %s note: '%s'\", uri, note);\n\t\tSIPE_ADD_BUDDY_INFO_NOESCAPE(is_oof_note ? _(\"Out of office note\") : _(\"Note\"),\n\t\t\t\t\t     note_italics);\n\t\tg_free(note_italics);\n\t}\n\tif (access_text) {\n\t\tSIPE_ADD_BUDDY_INFO(_(\"Access level\"), access_text);\n\t\tg_free(access_text);\n\t}\n}\n\nvoid sipe_buddy_update_property(struct sipe_core_private *sipe_private,\n\t\t\t\tconst char *uri,\n\t\t\t\tsipe_buddy_info_fields propkey,\n\t\t\t\tchar *property_value)\n{\n\tGSList *buddies, *entry;\n\n\tif (property_value)\n\t\tproperty_value = g_strstrip(property_value);\n\n\tentry = buddies = sipe_backend_buddy_find_all(SIPE_CORE_PUBLIC, uri, NULL); /* all buddies in different groups */\n\twhile (entry) {\n\t\tgchar *prop_str;\n\t\tsipe_backend_buddy p_buddy = entry->data;\n\n\t\t/* for Display Name */\n\t\tif (propkey == SIPE_BUDDY_INFO_DISPLAY_NAME) {\n\t\t\tgchar *alias;\n\t\t\talias = sipe_backend_buddy_get_alias(SIPE_CORE_PUBLIC, p_buddy);\n\t\t\tif (property_value && sipe_is_bad_alias(uri, alias)) {\n\t\t\t\tSIPE_DEBUG_INFO(\"Replacing alias for %s with %s\", uri, property_value);\n\t\t\t\tsipe_backend_buddy_set_alias(SIPE_CORE_PUBLIC, p_buddy, property_value);\n\t\t\t}\n\t\t\tg_free(alias);\n\n\t\t\talias = sipe_backend_buddy_get_server_alias(SIPE_CORE_PUBLIC, p_buddy);\n\t\t\tif (!is_empty(property_value) &&\n\t\t\t   (!sipe_strequal(property_value, alias) || is_empty(alias)) )\n\t\t\t{\n\t\t\t\tSIPE_DEBUG_INFO(\"Replacing service alias for %s with %s\", uri, property_value);\n\t\t\t\tsipe_backend_buddy_set_server_alias(SIPE_CORE_PUBLIC, p_buddy, property_value);\n\t\t\t}\n\t\t\tg_free(alias);\n\t\t}\n\t\t/* for other properties */\n\t\telse {\n\t\t\tif (!is_empty(property_value)) {\n\t\t\t\tprop_str = sipe_backend_buddy_get_string(SIPE_CORE_PUBLIC, p_buddy, propkey);\n\t\t\t\tif (!prop_str || !sipe_strcase_equal(prop_str, property_value)) {\n\t\t\t\t\tsipe_backend_buddy_set_string(SIPE_CORE_PUBLIC, p_buddy, propkey, property_value);\n\t\t\t\t}\n\t\t\t\tg_free(prop_str);\n\t\t\t}\n\t\t}\n\n\t\tentry = entry->next;\n\t}\n\tg_slist_free(buddies);\n}\n\n\nstruct ms_dlx_data;\nstruct ms_dlx_data {\n\tGSList *search_rows;\n\tgchar  *other;\n\tguint   max_returns;\n\tsipe_svc_callback *callback;\n\tstruct sipe_svc_session *session;\n\tgchar *wsse_security;\n\tstruct sipe_backend_search_token *token;\n\t/* must call ms_dlx_free() */\n\tvoid (*failed_callback)(struct sipe_core_private *sipe_private,\n\t\t\t\tstruct ms_dlx_data *mdd);\n};\n\nstatic void free_search_rows(GSList *search_rows)\n{\n\tsipe_utils_slist_free_full(search_rows, g_free);\n}\n\nstatic void ms_dlx_free(struct ms_dlx_data *mdd)\n{\n\tfree_search_rows(mdd->search_rows);\n\tsipe_svc_session_close(mdd->session);\n\tg_free(mdd->other);\n\tg_free(mdd->wsse_security);\n\tg_free(mdd);\n}\n\n#define SIPE_SOAP_SEARCH_ROW \"<m:row m:attrib=\\\"%s\\\" m:value=\\\"%s\\\"/>\"\n#define DLX_SEARCH_ITEM\t\t\t\t\t\t\t\\\n\t\"<AbEntryRequest.ChangeSearchQuery>\"\t\t\t\t\\\n\t\" <SearchOn>%s</SearchOn>\"\t\t\t\t\t\\\n\t\" <Value>%s</Value>\"\t\t\t\t\t\t\\\n\t\"</AbEntryRequest.ChangeSearchQuery>\"\n\nstatic gchar * prepare_buddy_search_query(GSList *query_rows, gboolean use_dlx) {\n\tgchar **attrs = g_new(gchar *, (g_slist_length(query_rows) / 2) + 1);\n\tguint i = 0;\n\tgchar *query = NULL;\n\n\twhile (query_rows) {\n\t\tconst gchar *attr;\n\t\tgchar *value;\n\t\tgchar *tmp = NULL;\n\n\t\tattr = query_rows->data;\n\t\tquery_rows = g_slist_next(query_rows);\n\t\tvalue = query_rows->data;\n\t\tquery_rows = g_slist_next(query_rows);\n\n\t\tif (!value)\n\t\t\tbreak;\n\n\t\t/*\n\t\t * Special value for SIP ID\n\t\t *\n\t\t * Active Directory seems only to be able to search for\n\t\t * SIP URIs. Make sure search string starts with \"sip:\".\n\t\t */\n\t\tif (!attr) {\n\t\t\tattr = \"msRTCSIP-PrimaryUserAddress\";\n\t\t\tif (!use_dlx)\n\t\t\t\tvalue = tmp = sip_uri(value);\n\t\t}\n\n\t\tattrs[i++] = g_markup_printf_escaped(use_dlx ? DLX_SEARCH_ITEM : SIPE_SOAP_SEARCH_ROW,\n\t\t\t\t\t\t     attr, value);\n\t\tg_free(tmp);\n\t}\n\tattrs[i] = NULL;\n\n\tif (i) {\n\t\tquery = g_strjoinv(NULL, attrs);\n\t\tSIPE_DEBUG_INFO(\"prepare_buddy_search_query: rows:\\n%s\",\n\t\t\t\tquery ? query : \"\");\n\t}\n\n\tg_strfreev(attrs);\n\n\treturn query;\n}\n\nstatic void ms_dlx_webticket(struct sipe_core_private *sipe_private,\n\t\t\t     const gchar *base_uri,\n\t\t\t     const gchar *auth_uri,\n\t\t\t     const gchar *wsse_security,\n\t\t\t     SIPE_UNUSED_PARAMETER const gchar *failure_msg,\n\t\t\t     gpointer callback_data)\n{\n\tstruct ms_dlx_data *mdd = callback_data;\n\n\tif (wsse_security) {\n\t\tguint length = g_slist_length(mdd->search_rows);\n\t\tgchar *search;\n\n\t\tSIPE_DEBUG_INFO(\"ms_dlx_webticket: got ticket for %s\",\n\t\t\t\tbase_uri);\n\n\t\tif (length > 0) {\n\t\t\t/* complex search */\n\t\t\tgchar *query = prepare_buddy_search_query(mdd->search_rows, TRUE);\n\t\t\tsearch = g_strdup_printf(\"<ChangeSearch xmlns:q1=\\\"DistributionListExpander\\\" soapenc:arrayType=\\\"q1:AbEntryRequest.ChangeSearchQuery[%d]\\\">\"\n\t\t\t\t\t\t \" %s\"\n\t\t\t\t\t\t \"</ChangeSearch>\",\n\t\t\t\t\t\t length / 2,\n\t\t\t\t\t\t query);\n\t\t\tg_free(query);\n\t\t} else {\n\t\t\t/* simple search */\n\t\t\tsearch = g_strdup_printf(\"<BasicSearch>\"\n\t\t\t\t\t\t \" <SearchList>c,company,displayName,givenName,mail,mailNickname,msRTCSIP-PrimaryUserAddress,sn</SearchList>\"\n\t\t\t\t\t\t \" <Value>%s</Value>\"\n\t\t\t\t\t\t \" <Verb>BeginsWith</Verb>\"\n\t\t\t\t\t\t \"</BasicSearch>\",\n\t\t\t\t\t\t mdd->other);\n\t\t}\n\n\t\tif (sipe_svc_ab_entry_request(sipe_private,\n\t\t\t\t\t      mdd->session,\n\t\t\t\t\t      auth_uri,\n\t\t\t\t\t      wsse_security,\n\t\t\t\t\t      search,\n\t\t\t\t\t      mdd->max_returns,\n\t\t\t\t\t      mdd->callback,\n\t\t\t\t\t      mdd)) {\n\n\t\t\t/* keep webticket security token for potential further use */\n\t\t\tg_free(mdd->wsse_security);\n\t\t\tmdd->wsse_security = g_strdup(wsse_security);\n\n\t\t\t/* callback data passed down the line */\n\t\t\tmdd = NULL;\n\t\t}\n\t\tg_free(search);\n\n\t} else {\n\t\t/* no ticket: this will show the minmum information */\n\t\tSIPE_DEBUG_ERROR(\"ms_dlx_webticket: no web ticket for %s\",\n\t\t\t\t base_uri);\n\t}\n\n\tif (mdd)\n\t\tmdd->failed_callback(sipe_private, mdd);\n}\n\nstatic void ms_dlx_webticket_request(struct sipe_core_private *sipe_private,\n\t\t\t\t     struct ms_dlx_data *mdd)\n{\n\tif (!sipe_webticket_request_with_port(sipe_private,\n\t\t\t\t\t      mdd->session,\n\t\t\t\t\t      sipe_private->dlx_uri,\n\t\t\t\t\t      \"AddressBookWebTicketBearer\",\n\t\t\t\t\t      ms_dlx_webticket,\n\t\t\t\t\t      mdd)) {\n\t\tSIPE_DEBUG_ERROR(\"ms_dlx_webticket_request: couldn't request webticket for %s\",\n\t\t\t\t sipe_private->dlx_uri);\n\t\tmdd->failed_callback(sipe_private, mdd);\n\t}\n}\n\nvoid sipe_buddy_search_contacts_finalize(struct sipe_core_private *sipe_private,\n\t\t\t\t\t struct sipe_backend_search_results *results,\n\t\t\t\t\t guint match_count,\n\t\t\t\t\t gboolean more)\n{\n\tgchar *secondary = g_strdup_printf(\n\t\tdngettext(PACKAGE_NAME,\n\t\t\t  \"Found %d contact%s:\",\n\t\t\t  \"Found %d contacts%s:\", match_count),\n\t\tmatch_count, more ? _(\" (more matched your query)\") : \"\");\n\n\tsipe_backend_search_results_finalize(SIPE_CORE_PUBLIC,\n\t\t\t\t\t     results,\n\t\t\t\t\t     secondary,\n\t\t\t\t\t     more);\n\tg_free(secondary);\n}\n\nstatic void search_ab_entry_response(struct sipe_core_private *sipe_private,\n\t\t\t\t     const gchar *uri,\n\t\t\t\t     SIPE_UNUSED_PARAMETER const gchar *raw,\n\t\t\t\t     sipe_xml *soap_body,\n\t\t\t\t     gpointer callback_data)\n{\n\tstruct ms_dlx_data *mdd = callback_data;\n\n\tif (soap_body) {\n\t\tconst sipe_xml *node;\n\t\tstruct sipe_backend_search_results *results;\n\t\tGHashTable *found;\n\n\t\tSIPE_DEBUG_INFO(\"search_ab_entry_response: received valid SOAP message from service %s\",\n\t\t\t\turi);\n\n\t\t/* any matches? */\n\t\tnode = sipe_xml_child(soap_body, \"Body/SearchAbEntryResponse/SearchAbEntryResult/Items/AbEntry\");\n\t\tif (!node) {\n\t\t\t/* try again with simple search, if possible */\n\t\t\tif (mdd->other && mdd->search_rows) {\n\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"search_ab_entry_response: no matches, retrying with simple search\");\n\n\t\t\t\t/* throw away original search query */\n\t\t\t\tfree_search_rows(mdd->search_rows);\n\t\t\t\tmdd->search_rows = NULL;\n\n\t\t\t\tms_dlx_webticket_request(sipe_private, mdd);\n\n\t\t\t\t/* callback data passed down the line */\n\t\t\t\treturn;\n\n\t\t\t} else {\n\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"search_ab_entry_response: no matches\");\n\n\t\t\t\tsipe_backend_search_failed(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t   mdd->token,\n\t\t\t\t\t\t\t   _(\"No contacts found\"));\n\t\t\t\tms_dlx_free(mdd);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t/* OK, we found something - show the results to the user */\n\t\tresults = sipe_backend_search_results_start(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t    mdd->token);\n\t\tif (!results) {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"search_ab_entry_response: Unable to display the search results.\");\n\t\t\tsipe_backend_search_failed(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t   mdd->token,\n\t\t\t\t\t\t   _(\"Unable to display the search results\"));\n\t\t\tms_dlx_free(mdd);\n\t\t\treturn;\n\t\t}\n\n\t\t/* SearchAbEntryResult can contain duplicates */\n\t\tfound = g_hash_table_new_full(g_str_hash, g_str_equal,\n\t\t\t\t\t      g_free, NULL);\n\n\t\tfor (/* initialized above */ ; node; node = sipe_xml_twin(node)) {\n\t\t\tconst sipe_xml *attrs;\n\t\t\tgchar *sip_uri     = NULL;\n\t\t\tgchar *displayname = NULL;\n\t\t\tgchar *company     = NULL;\n\t\t\tgchar *country     = NULL;\n\t\t\tgchar *email       = NULL;\n\n\t\t\tfor (attrs = sipe_xml_child(node, \"Attributes/Attribute\");\n\t\t\t     attrs;\n\t\t\t     attrs = sipe_xml_twin(attrs)) {\n\t\t\t\tgchar *name  = sipe_xml_data(sipe_xml_child(attrs,\n\t\t\t\t\t\t\t\t\t    \"Name\"));\n\t\t\t\tgchar *value = sipe_xml_data(sipe_xml_child(attrs,\n\t\t\t\t\t\t\t\t\t    \"Value\"));\n\n\t\t\t\tif (!is_empty(value)) {\n\t\t\t\t\tif (sipe_strcase_equal(name, \"msrtcsip-primaryuseraddress\")) {\n\t\t\t\t\t\tg_free(sip_uri);\n\t\t\t\t\t        sip_uri = value;\n\t\t\t\t\t\tvalue = NULL;\n\t\t\t\t\t} else if (sipe_strcase_equal(name, \"displayname\")) {\n\t\t\t\t\t\tg_free(displayname);\n\t\t\t\t\t\tdisplayname = value;\n\t\t\t\t\t\tvalue = NULL;\n\t\t\t\t\t} else if (sipe_strcase_equal(name, \"mail\")) {\n\t\t\t\t\t\tg_free(email);\n\t\t\t\t\t\temail = value;\n\t\t\t\t\t\tvalue = NULL;\n\t\t\t\t\t} else if (sipe_strcase_equal(name, \"company\")) {\n\t\t\t\t\t\tg_free(company);\n\t\t\t\t\t\tcompany = value;\n\t\t\t\t\t\tvalue = NULL;\n\t\t\t\t\t} else if (sipe_strcase_equal(name, \"country\")) {\n\t\t\t\t\t\tg_free(country);\n\t\t\t\t\t\tcountry = value;\n\t\t\t\t\t\tvalue = NULL;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tg_free(value);\n\t\t\t\tg_free(name);\n\t\t\t}\n\n\t\t\tif (sip_uri && !g_hash_table_lookup(found, sip_uri)) {\n\t\t\t\tgchar **uri_parts = g_strsplit(sip_uri, \":\", 2);\n\t\t\t\tsipe_backend_search_results_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\tresults,\n\t\t\t\t\t\t\t\turi_parts[1],\n\t\t\t\t\t\t\t\tdisplayname,\n\t\t\t\t\t\t\t\tcompany,\n\t\t\t\t\t\t\t\tcountry,\n\t\t\t\t\t\t\t\temail);\n\t\t\t\tg_strfreev(uri_parts);\n\n\t\t\t\tg_hash_table_insert(found, sip_uri, (gpointer) TRUE);\n\t\t\t\tsip_uri = NULL;\n\t\t\t}\n\n\t\t\tg_free(email);\n\t\t\tg_free(country);\n\t\t\tg_free(company);\n\t\t\tg_free(displayname);\n\t\t\tg_free(sip_uri);\n\t\t}\n\n\t\tsipe_buddy_search_contacts_finalize(sipe_private, results,\n\t\t\t\t\t\t    g_hash_table_size(found),\n\t\t\t\t\t\t    FALSE);\n\t\tg_hash_table_destroy(found);\n\t\tms_dlx_free(mdd);\n\n\t} else {\n\t\tmdd->failed_callback(sipe_private, mdd);\n\t}\n}\n\nstatic gboolean process_search_contact_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\tstruct sipmsg *msg,\n\t\t\t\t\t\tstruct transaction *trans)\n{\n\tstruct sipe_backend_search_token *token = trans->payload->data;\n\tstruct sipe_backend_search_results *results;\n\tsipe_xml *searchResults;\n\tconst sipe_xml *mrow;\n\tguint match_count = 0;\n\tgboolean more = FALSE;\n\n\t/* valid response? */\n\tif (msg->response != 200) {\n\t\tSIPE_DEBUG_ERROR(\"process_search_contact_response: request failed (%d)\",\n\t\t\t\t msg->response);\n\t\tsipe_backend_search_failed(SIPE_CORE_PUBLIC,\n\t\t\t\t\t   token,\n\t\t\t\t\t   _(\"Contact search failed\"));\n\t\treturn(FALSE);\n\t}\n\n\tSIPE_DEBUG_INFO(\"process_search_contact_response: body:\\n%s\", msg->body ? msg->body : \"\");\n\n\t/* valid XML? */\n\tsearchResults = sipe_xml_parse(msg->body, msg->bodylen);\n\tif (!searchResults) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_search_contact_response: no parseable searchResults\");\n\t\tsipe_backend_search_failed(SIPE_CORE_PUBLIC,\n\t\t\t\t\t   token,\n\t\t\t\t\t   _(\"Contact search failed\"));\n\t\treturn(FALSE);\n\t}\n\n\t/* any matches? */\n\tmrow = sipe_xml_child(searchResults, \"Body/Array/row\");\n\tif (!mrow) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"process_search_contact_response: no matches\");\n\t\tsipe_backend_search_failed(SIPE_CORE_PUBLIC,\n\t\t\t\t\t   token,\n\t\t\t\t\t   _(\"No contacts found\"));\n\n\t\tsipe_xml_free(searchResults);\n\t\treturn(FALSE);\n\t}\n\n\t/* OK, we found something - show the results to the user */\n\tresults = sipe_backend_search_results_start(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t    trans->payload->data);\n\tif (!results) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"process_search_contact_response: Unable to display the search results.\");\n\t\tsipe_backend_search_failed(SIPE_CORE_PUBLIC,\n\t\t\t\t\t   token,\n\t\t\t\t\t   _(\"Unable to display the search results\"));\n\n\t\tsipe_xml_free(searchResults);\n\t\treturn FALSE;\n\t}\n\n\tfor (/* initialized above */ ; mrow; mrow = sipe_xml_twin(mrow)) {\n\t\tgchar **uri_parts = g_strsplit(sipe_xml_attribute(mrow, \"uri\"), \":\", 2);\n\t\tsipe_backend_search_results_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\tresults,\n\t\t\t\t\t\turi_parts[1],\n\t\t\t\t\t\tsipe_xml_attribute(mrow, \"displayName\"),\n\t\t\t\t\t\tsipe_xml_attribute(mrow, \"company\"),\n\t\t\t\t\t\tsipe_xml_attribute(mrow, \"country\"),\n\t\t\t\t\t\tsipe_xml_attribute(mrow, \"email\"));\n\t\tg_strfreev(uri_parts);\n\t\tmatch_count++;\n\t}\n\n\tif ((mrow = sipe_xml_child(searchResults, \"Body/directorySearch/moreAvailable\")) != NULL) {\n\t\tchar *data = sipe_xml_data(mrow);\n\t\tmore = (g_ascii_strcasecmp(data, \"true\") == 0);\n\t\tg_free(data);\n\t}\n\n\tsipe_buddy_search_contacts_finalize(sipe_private, results, match_count, more);\n\tsipe_xml_free(searchResults);\n\n\treturn(TRUE);\n}\n\nstatic void search_soap_request(struct sipe_core_private *sipe_private,\n\t\t\t\tGDestroyNotify destroy,\n\t\t\t\tvoid *data,\n\t\t\t\tguint max,\n\t\t\t\tSoapTransCallback callback,\n\t\t\t\tGSList *search_rows)\n{\n\tgchar *query = prepare_buddy_search_query(search_rows, FALSE);\n\tstruct transaction_payload *payload = g_new0(struct transaction_payload, 1);\n\n\tpayload->destroy = destroy;\n\tpayload->data    = data;\n\n\tsip_soap_directory_search(sipe_private,\n\t\t\t\t  max,\n\t\t\t\t  query,\n\t\t\t\t  callback,\n\t\t\t\t  payload);\n\tg_free(query);\n}\n\nstatic void search_ab_entry_failed(struct sipe_core_private *sipe_private,\n\t\t\t\t   struct ms_dlx_data *mdd)\n{\n\t/* error using [MS-DLX] server, retry using Active Directory */\n\tif (mdd->search_rows)\n\t\tsearch_soap_request(sipe_private,\n\t\t\t\t    NULL,\n\t\t\t\t    mdd->token,\n\t\t\t\t    100,\n\t\t\t\t    process_search_contact_response,\n\t\t\t\t    mdd->search_rows);\n\tms_dlx_free(mdd);\n}\n\nvoid sipe_core_buddy_search(struct sipe_core_public *sipe_public,\n\t\t\t    struct sipe_backend_search_token *token,\n\t\t\t    const gchar *given_name,\n\t\t\t    const gchar *surname,\n\t\t\t    const gchar *email,\n\t\t\t    const gchar *sipid,\n\t\t\t    const gchar *company,\n\t\t\t    const gchar *country)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\n\t/* Lync 2013 or newer: use UCS if contacts are migrated */\n\tif (SIPE_CORE_PRIVATE_FLAG_IS(LYNC2013) &&\n\t    sipe_ucs_is_migrated(sipe_private)) {\n\n\t\tsipe_ucs_search(sipe_private,\n\t\t\t\ttoken,\n\t\t\t\tgiven_name,\n\t\t\t\tsurname,\n\t\t\t\temail,\n\t\t\t\tsipid,\n\t\t\t\tcompany,\n\t\t\t\tcountry);\n\n\t} else {\n\t\tGSList *query_rows  = NULL;\n\t\tguint count         = 0;\n\t\tconst gchar *simple = NULL;\n\n#define ADD_QUERY_ROW(attr, val)                                                 \\\n\t\tif (val) {                                                       \\\n\t\t\tquery_rows = g_slist_append(query_rows, g_strdup(attr)); \\\n\t\t\tquery_rows = g_slist_append(query_rows, g_strdup(val));  \\\n\t\t\tsimple = val;                                            \\\n\t\t\tcount++;                                                 \\\n\t\t}\n\n\t\tADD_QUERY_ROW(\"givenName\", given_name);\n\t\tADD_QUERY_ROW(\"sn\",        surname);\n\t\tADD_QUERY_ROW(\"mail\",      email);\n\t\t/* prepare_buddy_search_query() interprets NULL as SIP ID */\n\t\tADD_QUERY_ROW(NULL,        sipid);\n\t\tADD_QUERY_ROW(\"company\",   company);\n\t\tADD_QUERY_ROW(\"c\",         country);\n\n\t\tif (query_rows) {\n\t\t\tif (sipe_private->dlx_uri != NULL) {\n\t\t\t\tstruct ms_dlx_data *mdd = g_new0(struct ms_dlx_data, 1);\n\n\t\t\t\tmdd->search_rows     = query_rows;\n\t\t\t\t/* user entered only one search string, remember that one */\n\t\t\t\tif (count == 1)\n\t\t\t\t\tmdd->other   = g_strdup(simple);\n\t\t\t\tmdd->max_returns     = 100;\n\t\t\t\tmdd->callback        = search_ab_entry_response;\n\t\t\t\tmdd->failed_callback = search_ab_entry_failed;\n\t\t\t\tmdd->session         = sipe_svc_session_start();\n\t\t\t\tmdd->token           = token;\n\n\t\t\t\tms_dlx_webticket_request(sipe_private, mdd);\n\n\t\t\t} else {\n\t\t\t\t/* no [MS-DLX] server, use Active Directory search instead */\n\t\t\t\tsearch_soap_request(sipe_private,\n\t\t\t\t\t\t    NULL,\n\t\t\t\t\t\t    token,\n\t\t\t\t\t\t    100,\n\t\t\t\t\t\t    process_search_contact_response,\n\t\t\t\t\t\t    query_rows);\n\t\t\t\tfree_search_rows(query_rows);\n\t\t\t}\n\t\t} else\n\t\t\tsipe_backend_search_failed(sipe_public,\n\t\t\t\t\t\t   token,\n\t\t\t\t\t\t   _(\"Invalid contact search query\"));\n\t}\n}\n\nstatic void get_info_finalize(struct sipe_core_private *sipe_private,\n\t\t\t      struct sipe_backend_buddy_info *info,\n\t\t\t      const gchar *uri,\n\t\t\t      const gchar *server_alias,\n\t\t\t      const gchar *email)\n{\n\tsipe_backend_buddy bbuddy;\n\tstruct sipe_buddy *sbuddy;\n\tgchar *alias;\n\tgchar *value;\n\n\tif (!info) {\n\t\tinfo = sipe_backend_buddy_info_start(SIPE_CORE_PUBLIC);\n\t} else {\n\t\tsipe_backend_buddy_info_break(SIPE_CORE_PUBLIC, info);\n\t}\n\tif (!info)\n\t\treturn;\n\n\tbbuddy = sipe_backend_buddy_find(SIPE_CORE_PUBLIC, uri, NULL);\n\n\tif (is_empty(server_alias)) {\n\t\tvalue = sipe_backend_buddy_get_server_alias(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t    bbuddy);\n\t\tif (value) {\n\t\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t    info,\n\t\t\t\t\t\t    SIPE_BUDDY_INFO_DISPLAY_NAME,\n\t\t\t\t\t\t    value);\n\t\t}\n\t} else {\n\t\tvalue = g_strdup(server_alias);\n\t}\n\n\t/* present alias if it differs from server alias */\n\talias = sipe_backend_buddy_get_local_alias(SIPE_CORE_PUBLIC, bbuddy);\n\tif (alias && !sipe_strequal(alias, value))\n\t{\n\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t     info,\n\t\t\t\t\t     SIPE_BUDDY_INFO_ALIAS,\n\t\t\t\t\t     alias);\n\t}\n\tg_free(alias);\n\tg_free(value);\n\n\tif (is_empty(email)) {\n\t\tvalue = sipe_backend_buddy_get_string(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t      bbuddy,\n\t\t\t\t\t\t      SIPE_BUDDY_INFO_EMAIL);\n\t\tif (value) {\n\t\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t    info,\n\t\t\t\t\t\t    SIPE_BUDDY_INFO_EMAIL,\n\t\t\t\t\t\t    value);\n\t\t\tg_free(value);\n\t\t}\n\t}\n\n\tvalue = sipe_backend_buddy_get_string(SIPE_CORE_PUBLIC,\n\t\t\t\t\t      bbuddy,\n\t\t\t\t\t      SIPE_BUDDY_INFO_SITE);\n\tif (value) {\n\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t    info,\n\t\t\t\t\t    SIPE_BUDDY_INFO_SITE,\n\t\t\t\t\t    value);\n\t\tg_free(value);\n\t}\n\n\tsbuddy = sipe_buddy_find_by_uri(sipe_private, uri);\n\tif (sbuddy && sbuddy->device_name) {\n\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t    info,\n\t\t\t\t\t    SIPE_BUDDY_INFO_DEVICE,\n\t\t\t\t\t    sbuddy->device_name);\n\t}\n\n\tsipe_backend_buddy_info_finalize(SIPE_CORE_PUBLIC, info, uri);\n}\n\n\nstatic void get_info_ab_entry_response(struct sipe_core_private *sipe_private,\n\t\t\t\t       const gchar *uri,\n\t\t\t\t       SIPE_UNUSED_PARAMETER const gchar *raw,\n\t\t\t\t       sipe_xml *soap_body,\n\t\t\t\t       gpointer callback_data)\n{\n\tstruct ms_dlx_data *mdd = callback_data;\n\tstruct sipe_backend_buddy_info *info = NULL;\n\tgchar *server_alias = NULL;\n\tgchar *email        = NULL;\n\n\tif (soap_body) {\n\t\tconst sipe_xml *node;\n\n\t\tSIPE_DEBUG_INFO(\"get_info_ab_entry_response: received valid SOAP message from service %s\",\n\t\t\t\turi);\n\n\t\tinfo = sipe_backend_buddy_info_start(SIPE_CORE_PUBLIC);\n\n\t\tfor (node = sipe_xml_child(soap_body, \"Body/SearchAbEntryResponse/SearchAbEntryResult/Items/AbEntry/Attributes/Attribute\");\n\t\t     node;\n\t\t     node = sipe_xml_twin(node)) {\n\t\t\tgchar *name  = sipe_xml_data(sipe_xml_child(node,\n\t\t\t\t\t\t\t\t    \"Name\"));\n\t\t\tgchar *value = sipe_xml_data(sipe_xml_child(node,\n\t\t\t\t\t\t\t\t    \"Value\"));\n\t\t\tconst sipe_xml *values = sipe_xml_child(node,\n\t\t\t\t\t\t\t\t\"Values\");\n\n\t\t\t/* Single value entries */\n\t\t\tif (!is_empty(value)) {\n\n\t\t\t\tif (sipe_strcase_equal(name, \"displayname\")) {\n\t\t\t\t\tg_free(server_alias);\n\t\t\t\t\tserver_alias = value;\n\t\t\t\t\tvalue = NULL;\n\t\t\t\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t    info,\n\t\t\t\t\t\t\t\t    SIPE_BUDDY_INFO_DISPLAY_NAME,\n\t\t\t\t\t\t\t\t    server_alias);\n\t\t\t\t} else if (sipe_strcase_equal(name, \"mail\")) {\n\t\t\t\t\tg_free(email);\n\t\t\t\t\temail = value;\n\t\t\t\t\tvalue = NULL;\n\t\t\t\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t    info,\n\t\t\t\t\t\t\t\t    SIPE_BUDDY_INFO_EMAIL,\n\t\t\t\t\t\t\t\t    email);\n\t\t\t\t} else if (sipe_strcase_equal(name, \"title\")) {\n\t\t\t\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t    info,\n\t\t\t\t\t\t\t\t    SIPE_BUDDY_INFO_JOB_TITLE,\n\t\t\t\t\t\t\t\t    value);\n\t\t\t\t} else if (sipe_strcase_equal(name, \"company\")) {\n\t\t\t\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t    info,\n\t\t\t\t\t\t\t\t    SIPE_BUDDY_INFO_COMPANY,\n\t\t\t\t\t\t\t\t    value);\n\t\t\t\t} else if (sipe_strcase_equal(name, \"country\")) {\n\t\t\t\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t    info,\n\t\t\t\t\t\t\t\t    SIPE_BUDDY_INFO_COUNTRY,\n\t\t\t\t\t\t\t\t    value);\n\t\t\t\t}\n\n\t\t\t} else if (values) {\n\t\t\t\tgchar *first = sipe_xml_data(sipe_xml_child(values,\n\t\t\t\t\t\t\t\t\t    \"string\"));\n\n\t\t\t\tif (sipe_strcase_equal(name, \"telephonenumber\")) {\n\t\t\t\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t    info,\n\t\t\t\t\t\t\t\t    SIPE_BUDDY_INFO_WORK_PHONE,\n\t\t\t\t\t\t\t\t    first);\n\t\t\t\t}\n\n\t\t\t\tg_free(first);\n\t\t\t}\n\n\t\t\tg_free(value);\n\t\t\tg_free(name);\n\t\t}\n\t}\n\n\t/* this will show the minmum information */\n\tget_info_finalize(sipe_private,\n\t\t\t  info,\n\t\t\t  mdd->other,\n\t\t\t  server_alias,\n\t\t\t  email);\n\n\tg_free(email);\n\tg_free(server_alias);\n\tms_dlx_free(mdd);\n}\n\nstatic gboolean process_get_info_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  struct sipmsg *msg,\n\t\t\t\t\t  struct transaction *trans)\n{\n\tconst gchar *uri = trans->payload->data;\n\tstruct sipe_backend_buddy_info *info = NULL;\n\tgchar *server_alias = NULL;\n\tgchar *email        = NULL;\n\n\tSIPE_DEBUG_INFO(\"Fetching %s's user info for %s\",\n\t\t\turi, sipe_private->username);\n\n\tif (msg->response != 200) {\n\t\tSIPE_DEBUG_INFO(\"process_get_info_response: SERVICE response is %d\", msg->response);\n\t} else {\n\t\tsipe_xml *searchResults;\n\t\tconst sipe_xml *mrow;\n\n\t\tSIPE_DEBUG_INFO(\"process_get_info_response: body:\\n%s\",\n\t\t\t\tmsg->body ? msg->body : \"\");\n\n\t\tsearchResults = sipe_xml_parse(msg->body, msg->bodylen);\n\t\tif (!searchResults) {\n\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_get_info_response: no parseable searchResults\");\n\n\t\t} else if ((mrow = sipe_xml_child(searchResults, \"Body/Array/row\"))) {\n\t\t\tconst gchar *value;\n\t\t\tgchar *phone_number;\n\n\t\t\tinfo = sipe_backend_buddy_info_start(SIPE_CORE_PUBLIC);\n\n\t\t\tserver_alias = g_strdup(sipe_xml_attribute(mrow, \"displayName\"));\n\t\t\temail = g_strdup(sipe_xml_attribute(mrow, \"email\"));\n\t\t\tphone_number = g_strdup(sipe_xml_attribute(mrow, \"phone\"));\n\n\t\t\t/*\n\t\t\t * For 2007 system we will take this from ContactCard -\n\t\t\t * it has cleaner tel: URIs at least\n\t\t\t */\n\t\t\tif (!SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {\n\t\t\t\tchar *tel_uri = sip_to_tel_uri(phone_number);\n\t\t\t\t/* trims its parameters, so call first */\n\t\t\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_DISPLAY_NAME, server_alias);\n\t\t\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_EMAIL, email);\n\t\t\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_WORK_PHONE, tel_uri);\n\t\t\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY, phone_number);\n\t\t\t\tg_free(tel_uri);\n\n\t\t\t\tsipe_backend_buddy_refresh_properties(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t      uri);\n\t\t\t}\n\n\t\t\tif (!is_empty(server_alias)) {\n\t\t\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t     info,\n\t\t\t\t\t\t\t     SIPE_BUDDY_INFO_DISPLAY_NAME,\n\t\t\t\t\t\t\t     server_alias);\n\t\t\t}\n\t\t\tif ((value = sipe_xml_attribute(mrow, \"title\")) && strlen(value) > 0) {\n\t\t\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t     info,\n\t\t\t\t\t\t\t     SIPE_BUDDY_INFO_JOB_TITLE,\n\t\t\t\t\t\t\t     value);\n\t\t\t}\n\t\t\tif ((value = sipe_xml_attribute(mrow, \"office\")) && strlen(value) > 0) {\n\t\t\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t     info,\n\t\t\t\t\t\t\t     SIPE_BUDDY_INFO_OFFICE,\n\t\t\t\t\t\t\t     value);\n\t\t\t}\n\t\t\tif (!is_empty(phone_number)) {\n\t\t\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t     info,\n\t\t\t\t\t\t\t     SIPE_BUDDY_INFO_WORK_PHONE,\n\t\t\t\t\t\t\t     phone_number);\n\t\t\t}\n\t\t\tg_free(phone_number);\n\t\t\tif ((value = sipe_xml_attribute(mrow, \"company\")) && strlen(value) > 0) {\n\t\t\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t     info,\n\t\t\t\t\t\t\t     SIPE_BUDDY_INFO_COMPANY,\n\t\t\t\t\t\t\t     value);\n\t\t\t}\n\t\t\tif ((value = sipe_xml_attribute(mrow, \"city\")) && strlen(value) > 0) {\n\t\t\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t     info,\n\t\t\t\t\t\t\t     SIPE_BUDDY_INFO_CITY,\n\t\t\t\t\t\t\t     value);\n\t\t\t}\n\t\t\tif ((value = sipe_xml_attribute(mrow, \"state\")) && strlen(value) > 0) {\n\t\t\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t     info,\n\t\t\t\t\t\t\t     SIPE_BUDDY_INFO_STATE,\n\t\t\t\t\t\t\t     value);\n\t\t\t}\n\t\t\tif ((value = sipe_xml_attribute(mrow, \"country\")) && strlen(value) > 0) {\n\t\t\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t     info,\n\t\t\t\t\t\t\t     SIPE_BUDDY_INFO_COUNTRY,\n\t\t\t\t\t\t\t     value);\n\t\t\t}\n\t\t\tif (!is_empty(email)) {\n\t\t\t\tsipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t     info,\n\t\t\t\t\t\t\t     SIPE_BUDDY_INFO_EMAIL,\n\t\t\t\t\t\t\t     email);\n\t\t\t}\n\t\t}\n\t\tsipe_xml_free(searchResults);\n\t}\n\n\t/* this will show the minmum information */\n\tget_info_finalize(sipe_private,\n\t\t\t  info,\n\t\t\t  uri,\n\t\t\t  server_alias,\n\t\t\t  email);\n\n\tg_free(server_alias);\n\tg_free(email);\n\n\treturn TRUE;\n}\n\nstatic void get_info_ab_entry_failed(struct sipe_core_private *sipe_private,\n\t\t\t\t     struct ms_dlx_data *mdd)\n{\n\t/* error using [MS-DLX] server, retry using Active Directory */\n\tsearch_soap_request(sipe_private,\n\t\t\t    g_free,\n\t\t\t    mdd->other,\n\t\t\t    1,\n\t\t\t    process_get_info_response,\n\t\t\t    mdd->search_rows);\n\tmdd->other = NULL;\n\tms_dlx_free(mdd);\n}\n\nstatic GSList *search_rows_for_uri(const gchar *uri)\n{\n\t/* prepare_buddy_search_query() interprets NULL as SIP ID */\n\tGSList *l = g_slist_append(NULL, NULL);\n\treturn(g_slist_append(l, g_strdup(uri)));\n}\n\nvoid sipe_core_buddy_get_info(struct sipe_core_public *sipe_public,\n\t\t\t      const gchar *who)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tGSList *search_rows = search_rows_for_uri(who);\n\n\tif (sipe_private->dlx_uri) {\n\t\tstruct ms_dlx_data *mdd = g_new0(struct ms_dlx_data, 1);\n\n\t\tmdd->search_rows     = search_rows;\n\t\tmdd->other           = g_strdup(who);\n\t\tmdd->max_returns     = 1;\n\t\tmdd->callback        = get_info_ab_entry_response;\n\t\tmdd->failed_callback = get_info_ab_entry_failed;\n\t\tmdd->session         = sipe_svc_session_start();\n\n\t\tms_dlx_webticket_request(sipe_private, mdd);\n\n\t} else {\n\t\t/* no [MS-DLX] server, use Active Directory search instead */\n\t\tsearch_soap_request(sipe_private,\n\t\t\t\t    g_free,\n\t\t\t\t    g_strdup(who),\n\t\t\t\t    1,\n\t\t\t\t    process_get_info_response,\n\t\t\t\t    search_rows);\n\t\tfree_search_rows(search_rows);\n\t}\n}\n\nstatic void photo_response_data_free(struct photo_response_data *data)\n{\n\tg_free(data->who);\n\tg_free(data->photo_hash);\n\tif (data->request) {\n\t\tsipe_http_request_cancel(data->request);\n\t}\n\tg_free(data);\n}\n\nstatic void photo_response_data_remove(struct sipe_core_private *sipe_private,\n\t\t\t\t       struct photo_response_data *data)\n{\n\tdata->request = NULL;\n\tsipe_private->buddies->pending_photo_requests =\n\t\tg_slist_remove(sipe_private->buddies->pending_photo_requests, data);\n\tphoto_response_data_free(data);\n}\n\nstatic void process_buddy_photo_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\t guint status,\n\t\t\t\t\t GSList *headers,\n\t\t\t\t\t const char *body,\n\t\t\t\t\t gpointer data)\n{\n\tstruct photo_response_data *rdata = (struct photo_response_data *) data;\n\n\tif (status == SIPE_HTTP_STATUS_OK) {\n\t\tconst gchar *len_str = sipe_utils_nameval_find(headers,\n\t\t\t\t\t\t\t       \"Content-Length\");\n\t\tif (len_str) {\n\t\t\tgsize photo_size = atoi(len_str);\n\t\t\tgpointer photo = g_new(char, photo_size);\n\n\t\t\tif (photo) {\n\t\t\t\tmemcpy(photo, body, photo_size);\n\n\t\t\t\tsipe_backend_buddy_set_photo(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t     rdata->who,\n\t\t\t\t\t\t\t     photo,\n\t\t\t\t\t\t\t     photo_size,\n\t\t\t\t\t\t\t     rdata->photo_hash);\n\t\t\t}\n\t\t}\n\t}\n\n\tphoto_response_data_remove(sipe_private, rdata);\n}\n\nstatic void process_get_user_photo_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\t    guint status,\n\t\t\t\t\t    SIPE_UNUSED_PARAMETER GSList *headers,\n\t\t\t\t\t    const gchar *body,\n\t\t\t\t\t    gpointer data)\n{\n\tstruct photo_response_data *rdata = (struct photo_response_data *) data;\n\n\tif ((status == SIPE_HTTP_STATUS_OK) && body) {\n\t\tsipe_xml *xml = sipe_xml_parse(body, strlen(body));\n\t\tconst sipe_xml *node = sipe_xml_child(xml,\n\t\t\t\t\t\t      \"Body/GetUserPhotoResponse/PictureData\");\n\n\t\tif (node) {\n\t\t\tgchar *base64;\n\t\t\tgsize photo_size;\n\t\t\tguchar *photo;\n\n\t\t\t/* decode photo data */\n\t\t\tbase64 = sipe_xml_data(node);\n\t\t\tphoto = g_base64_decode(base64, &photo_size);\n\t\t\tg_free(base64);\n\n\t\t\t/* EWS doesn't provide a hash -> calculate SHA-1 digest */\n\t\t\tif (!rdata->photo_hash) {\n\t\t\t\tguchar digest[SIPE_DIGEST_SHA1_LENGTH];\n\t\t\t\tsipe_digest_sha1(photo, photo_size, digest);\n\n\t\t\t\t/* rdata takes ownership of digest string */\n\t\t\t\trdata->photo_hash = buff_to_hex_str(digest,\n\t\t\t\t\t\t\t\t    SIPE_DIGEST_SHA1_LENGTH);\n\t\t\t}\n\n\t\t\t/* backend frees \"photo\" */\n\t\t\tsipe_backend_buddy_set_photo(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t     rdata->who,\n\t\t\t\t\t\t     photo,\n\t\t\t\t\t\t     photo_size,\n\t\t\t\t\t\t     rdata->photo_hash);\n\t\t}\n\n\t\tsipe_xml_free(xml);\n\t}\n\n\tphoto_response_data_remove(sipe_private, rdata);\n}\n\nstatic gchar *create_x_ms_webticket_header(const gchar *wsse_security)\n{\n\tgchar *assertion = sipe_xml_extract_raw(wsse_security, \"Assertion\", TRUE);\n\tgchar *wsse_security_base64;\n\tgchar *x_ms_webticket_header;\n\n\tif (!assertion) {\n\t\treturn NULL;\n\t}\n\n\twsse_security_base64 = g_base64_encode((const guchar *)assertion,\n\t\t\tstrlen(assertion));\n\tx_ms_webticket_header = g_strdup_printf(\"X-MS-WebTicket: opaque=%s\\r\\n\",\n\t\t\twsse_security_base64);\n\n\tg_free(assertion);\n\tg_free(wsse_security_base64);\n\n\treturn x_ms_webticket_header;\n}\n\n/* see also sipe_ucs_http_request() */\nstatic struct sipe_http_request *get_user_photo_request(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t\tstruct photo_response_data *data,\n\t\t\t\t\t\t\tconst gchar *ews_url,\n\t\t\t\t\t\t\tconst gchar *email)\n{\n\tgchar *soap = g_strdup_printf(\"<?xml version=\\\"1.0\\\"?>\\r\\n\"\n\t\t\t\t      \"<soap:Envelope\"\n\t\t\t\t      \" xmlns:m=\\\"http://schemas.microsoft.com/exchange/services/2006/messages\\\"\"\n\t\t\t\t      \" xmlns:soap=\\\"http://schemas.xmlsoap.org/soap/envelope/\\\"\"\n\t\t\t\t      \" xmlns:t=\\\"http://schemas.microsoft.com/exchange/services/2006/types\\\"\"\n\t\t\t\t      \" >\"\n\t\t\t\t      \" <soap:Header>\"\n\t\t\t\t      \"  <t:RequestServerVersion Version=\\\"Exchange2013\\\" />\"\n\t\t\t\t      \" </soap:Header>\"\n\t\t\t\t      \" <soap:Body>\"\n\t\t\t\t      \"  <m:GetUserPhoto>\"\n\t\t\t\t      \"   <m:Email>%s</m:Email>\"\n\t\t\t\t      \"   <m:SizeRequested>HR48x48</m:SizeRequested>\"\n\t\t\t\t      \"  </m:GetUserPhoto>\"\n\t\t\t\t      \" </soap:Body>\"\n\t\t\t\t      \"</soap:Envelope>\",\n\t\t\t\t      email);\n\tstruct sipe_http_request *request = sipe_http_request_post(sipe_private,\n\t\t\t\t\t\t\t\t   ews_url,\n\t\t\t\t\t\t\t\t   NULL,\n\t\t\t\t\t\t\t\t   soap,\n\t\t\t\t\t\t\t\t   \"text/xml; charset=UTF-8\",\n\t\t\t\t\t\t\t\t   process_get_user_photo_response,\n\t\t\t\t\t\t\t\t   data);\n\tg_free(soap);\n\n\tif (request) {\n\t\tsipe_core_email_authentication(sipe_private,\n\t\t\t\t\t       request);\n\t\tsipe_http_request_allow_redirect(request);\n\t} else {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"get_user_photo_request: failed to create HTTP connection\");\n\t}\n\n\treturn(request);\n}\n\nstatic void photo_response_data_finalize(struct sipe_core_private *sipe_private,\n\t\t\t\t\t struct photo_response_data *data,\n\t\t\t\t\t const gchar *uri,\n\t\t\t\t\t const gchar *photo_hash)\n{\n\tif (data->request) {\n\t\tdata->who        = g_strdup(uri);\n\t\tdata->photo_hash = g_strdup(photo_hash);\n\n\t\tsipe_private->buddies->pending_photo_requests =\n\t\t\tg_slist_append(sipe_private->buddies->pending_photo_requests, data);\n\t\tsipe_http_request_ready(data->request);\n\t} else {\n\t\tphoto_response_data_free(data);\n\t}\n}\n\nvoid sipe_buddy_update_photo(struct sipe_core_private *sipe_private,\n\t\t\t     const gchar *uri,\n\t\t\t     const gchar *photo_hash,\n\t\t\t     const gchar *photo_url,\n\t\t\t     const gchar *headers)\n{\n\tconst gchar *photo_hash_old =\n\t\tsipe_backend_buddy_get_photo_hash(SIPE_CORE_PUBLIC, uri);\n\n\tif (!sipe_strequal(photo_hash, photo_hash_old)) {\n\t\tstruct photo_response_data *data = g_new0(struct photo_response_data, 1);\n\n\t\tSIPE_DEBUG_INFO(\"sipe_buddy_update_photo: who '%s' url '%s' hash '%s'\",\n\t\t\t\turi, photo_url, photo_hash);\n\n\t\t/* Photo URL is embedded XML? */\n\t\tif (g_str_has_prefix(photo_url, \"<\") &&\n\t\t    g_str_has_suffix(photo_url, \">\")) {\n\t\t\t/* add dummy root to embedded XML string */\n\t\t\tgchar *tmp = g_strdup_printf(\"<r>%s</r>\", photo_url);\n\t\t\tsipe_xml *xml = sipe_xml_parse(tmp, strlen(tmp));\n\t\t\tg_free(tmp);\n\n\t\t\tif (xml) {\n\t\t\t\tgchar *ews_url = sipe_xml_data(sipe_xml_child(xml, \"ewsUrl\"));\n\t\t\t\tgchar *email = sipe_xml_data(sipe_xml_child(xml, \"primarySMTP\"));\n\n\t\t\t\tif (!is_empty(ews_url) && !is_empty(email)) {\n\t\t\t\t\t/*\n\t\t\t\t\t * Workaround for missing Office 365 buddy icons\n\t\t\t\t\t *\n\t\t\t\t\t * (All?) Office 365 contact cards have the following\n\t\t\t\t\t * XML embedded as the photo URI XML node text:\n\t\t\t\t\t *\n\t\t\t\t\t *    <ewsUrl>https://outlook.office365.com/EWS/Exchange.asmx/WSSecurity</ewsUrl>\n\t\t\t\t\t *    <primarySMTP>user@company.com</primarySMTP>\n\t\t\t\t\t *\n\t\t\t\t\t * The simple HTTP request by get_user_photo_request()\n\t\t\t\t\t * is rejected with 401. But the response contains\n\t\t\t\t\t *\n\t\t\t\t\t *    WWW-Authenticate: Basic Realm=\"\"\n\t\t\t\t\t *\n\t\t\t\t\t * to which the HTTP transport answers with a retry\n\t\t\t\t\t * using Basic authentication. That in turn is rejected\n\t\t\t\t\t * with 500 and thus the buddy icon retrieval fails.\n\t\t\t\t\t *\n\t\t\t\t\t * As a quick workaround strip the trailing \"/WSSecurity\"\n\t\t\t\t\t * from the URL. The HTTP request for the buddy icon\n\t\t\t\t\t * retrieval will work with this stripped URL.\n\t\t\t\t\t *\n\t\t\t\t\t * @TODO: this is probably not the correct approach.\n\t\t\t\t\t *        get_user_photo_request() should be updated\n\t\t\t\t\t *        to support also a webticket request.\n\t\t\t\t\t */\n\t\t\t\t\tgchar *tmp = g_strrstr(ews_url, \"/WSSecurity\");\n\t\t\t\t\tif (tmp)\n\t\t\t\t\t\t*tmp = '\\0';\n\n\t\t\t\t\tdata->request = get_user_photo_request(sipe_private,\n\t\t\t\t\t\t\t\t\t       data,\n\t\t\t\t\t\t\t\t\t       ews_url,\n\t\t\t\t\t\t\t\t\t       email);\n\t\t\t\t}\n\n\t\t\t\tg_free(email);\n\t\t\t\tg_free(ews_url);\n\t\t\t\tsipe_xml_free(xml);\n\t\t\t}\n\t\t} else {\n\t\t\tdata->request = sipe_http_request_get(sipe_private,\n\t\t\t\t\t\t\t      photo_url,\n\t\t\t\t\t\t\t      headers,\n\t\t\t\t\t\t\t      process_buddy_photo_response,\n\t\t\t\t\t\t\t      data);\n\t\t}\n\n\t\tphoto_response_data_finalize(sipe_private,\n\t\t\t\t\t     data,\n\t\t\t\t\t     uri,\n\t\t\t\t\t     photo_hash);\n\t}\n}\n\nstatic void get_photo_ab_entry_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\tconst gchar *uri,\n\t\t\t\t\tSIPE_UNUSED_PARAMETER const gchar *raw,\n\t\t\t\t\tsipe_xml *soap_body,\n\t\t\t\t\tgpointer callback_data)\n{\n\tstruct ms_dlx_data *mdd = callback_data;\n\tgchar *photo_rel_path = NULL;\n\tgchar *photo_hash = NULL;\n\n\tif (soap_body) {\n\t\tconst sipe_xml *node;\n\n\t\tSIPE_DEBUG_INFO(\"get_photo_ab_entry_response: received valid SOAP message from service %s\",\n\t\t\t\turi);\n\n\t\tfor (node = sipe_xml_child(soap_body, \"Body/SearchAbEntryResponse/SearchAbEntryResult/Items/AbEntry/Attributes/Attribute\");\n\t\t     node;\n\t\t     node = sipe_xml_twin(node)) {\n\t\t\tgchar *name  = sipe_xml_data(sipe_xml_child(node, \"Name\"));\n\t\t\tgchar *value = sipe_xml_data(sipe_xml_child(node, \"Value\"));\n\n\t\t\tif (!is_empty(value)) {\n\t\t\t\tif (sipe_strcase_equal(name, \"PhotoRelPath\")) {\n\t\t\t\t\tg_free(photo_rel_path);\n\t\t\t\t\tphoto_rel_path = value;\n\t\t\t\t\tvalue = NULL;\n\t\t\t\t} else if (sipe_strcase_equal(name, \"PhotoHash\")) {\n\t\t\t\t\tg_free(photo_hash);\n\t\t\t\t\tphoto_hash = value;\n\t\t\t\t\tvalue = NULL;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tg_free(value);\n\t\t\tg_free(name);\n\t\t}\n\t}\n\n\tif (sipe_private->addressbook_uri && photo_rel_path && photo_hash) {\n\t\tgchar *photo_url = g_strdup_printf(\"%s/%s\",\n\t\t\t\tsipe_private->addressbook_uri, photo_rel_path);\n\t\tgchar *x_ms_webticket_header = create_x_ms_webticket_header(mdd->wsse_security);\n\n\t\tsipe_buddy_update_photo(sipe_private,\n\t\t\t\t\tmdd->other,\n\t\t\t\t\tphoto_hash,\n\t\t\t\t\tphoto_url,\n\t\t\t\t\tx_ms_webticket_header);\n\n\t\tg_free(x_ms_webticket_header);\n\t\tg_free(photo_url);\n\t}\n\n\tg_free(photo_rel_path);\n\tg_free(photo_hash);\n\tms_dlx_free(mdd);\n}\n\nstatic void get_photo_ab_entry_failed(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private,\n\t\t\t\t      struct ms_dlx_data *mdd)\n{\n\tms_dlx_free(mdd);\n}\n\nstatic void buddy_fetch_photo(struct sipe_core_private *sipe_private,\n\t\t\t      const gchar *uri)\n{\n        if (sipe_backend_uses_photo()) {\n\n\t\t/* Lync 2013 or newer: use UCS if contacts are migrated */\n\t\tif (SIPE_CORE_PRIVATE_FLAG_IS(LYNC2013) &&\n\t\t    sipe_ucs_is_migrated(sipe_private)) {\n\t\t\tstruct photo_response_data *data = g_new0(struct photo_response_data, 1);\n\n\t\t\tdata->request = get_user_photo_request(sipe_private,\n\t\t\t\t\t\t\t       data,\n\t\t\t\t\t\t\t       sipe_ucs_ews_url(sipe_private),\n\t\t\t\t\t\t\t       sipe_get_no_sip_uri(uri));\n\t\t\tphoto_response_data_finalize(sipe_private,\n\t\t\t\t\t\t     data,\n\t\t\t\t\t\t     uri,\n\t\t\t\t\t\t     /* there is no hash */\n\t\t\t\t\t\t     NULL);\n\n\t\t/* Lync 2010: use [MS-DLX] */\n\t\t} else if (sipe_private->dlx_uri         &&\n\t\t\t   sipe_private->addressbook_uri) {\n\t\t\tstruct ms_dlx_data *mdd = g_new0(struct ms_dlx_data, 1);\n\n\t\t\tmdd->search_rows     = search_rows_for_uri(uri);\n\t\t\tmdd->other           = g_strdup(uri);\n\t\t\tmdd->max_returns     = 1;\n\t\t\tmdd->callback        = get_photo_ab_entry_response;\n\t\t\tmdd->failed_callback = get_photo_ab_entry_failed;\n\t\t\tmdd->session         = sipe_svc_session_start();\n\n\t\t\tms_dlx_webticket_request(sipe_private, mdd);\n\t\t}\n\t}\n}\n\nstatic void buddy_refresh_photos_cb(gpointer uri,\n\t\t\t\t    SIPE_UNUSED_PARAMETER gpointer value,\n\t\t\t\t    gpointer sipe_private)\n{\n\tbuddy_fetch_photo(sipe_private, uri);\n}\n\nvoid sipe_buddy_refresh_photos(struct sipe_core_private *sipe_private)\n{\n\tg_hash_table_foreach(sipe_private->buddies->uri,\n\t\t\t     buddy_refresh_photos_cb,\n\t\t\t     sipe_private);\n}\n\n/* Buddy menu callbacks*/\n\nvoid sipe_core_buddy_new_chat(struct sipe_core_public *sipe_public,\n\t\t\t      const gchar *who)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\n\t/* 2007+ conference */\n\tif (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {\n\t\tsipe_conf_add(sipe_private, who);\n\n\t/* 2005- multiparty chat */\n\t} else {\n\t\tgchar *self = sip_uri_self(sipe_private);\n\t\tstruct sip_session *session;\n\n\t\tsession = sipe_session_add_chat(sipe_private,\n\t\t\t\t\t\tNULL,\n\t\t\t\t\t\tTRUE,\n\t\t\t\t\t\tself);\n\t\tsession->chat_session->backend = sipe_backend_chat_create(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\t  session->chat_session,\n\t\t\t\t\t\t\t\t\t  session->chat_session->title,\n\t\t\t\t\t\t\t\t\t  self);\n\t\tg_free(self);\n\n\t\tsipe_im_invite(sipe_private, session, who,\n\t\t\t       NULL, NULL, NULL, FALSE);\n\t}\n}\n\nvoid sipe_core_buddy_send_email(struct sipe_core_public *sipe_public,\n\t\t\t\tconst gchar *who)\n{\n\tsipe_backend_buddy buddy = sipe_backend_buddy_find(sipe_public,\n\t\t\t\t\t\t\t   who,\n\t\t\t\t\t\t\t   NULL);\n\tgchar *email = sipe_backend_buddy_get_string(sipe_public,\n\t\t\t\t\t\t     buddy,\n\t\t\t\t\t\t     SIPE_BUDDY_INFO_EMAIL);\n\n\tif (email) {\n\t\tgchar *command_line = g_strdup_printf(\n#ifdef _WIN32\n\t\t\t\"cmd /c start\"\n#else\n\t\t\t\"xdg-email\"\n#endif\n\t\t\t\" mailto:%s\", email);\n\t\tg_free(email);\n\n\t\tSIPE_DEBUG_INFO(\"sipe_core_buddy_send_email: going to call email client: %s\",\n\t\t\t\tcommand_line);\n\t\tg_spawn_command_line_async(command_line, NULL);\n\t\tg_free(command_line);\n\n\t} else {\n\t\tSIPE_DEBUG_INFO(\"sipe_core_buddy_send_email: no email address stored for buddy=%s\",\n\t\t\t\twho);\n\t}\n}\n\n/* Buddy menu */\n\nstatic struct sipe_backend_buddy_menu *buddy_menu_phone(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\tstruct sipe_backend_buddy_menu *menu,\n\t\t\t\t\t\t\tsipe_backend_buddy buddy,\n\t\t\t\t\t\t\tsipe_buddy_info_fields id_phone,\n\t\t\t\t\t\t\tsipe_buddy_info_fields id_display,\n\t\t\t\t\t\t\tconst gchar *type)\n{\n\tgchar *phone = sipe_backend_buddy_get_string(sipe_public,\n\t\t\t\t\t\t     buddy,\n\t\t\t\t\t\t     id_phone);\n\tif (phone) {\n\t\tgchar *display = sipe_backend_buddy_get_string(sipe_public,\n\t\t\t\t\t\t\t       buddy,\n\t\t\t\t\t\t\t       id_display);\n\t\tgchar *tmp   = NULL;\n\t\tgchar *label = g_strdup_printf(\"%s %s\",\n\t\t\t\t\t       type,\n\t\t\t\t\t       display ? display :\n\t\t\t\t\t       (tmp = sip_tel_uri_denormalize(phone)));\n\t\tmenu = sipe_backend_buddy_menu_add(sipe_public,\n\t\t\t\t\t\t   menu,\n\t\t\t\t\t\t   label,\n\t\t\t\t\t\t   SIPE_BUDDY_MENU_MAKE_CALL,\n\t\t\t\t\t\t   phone);\n\t\tg_free(tmp);\n\t\tg_free(label);\n\t\tg_free(display);\n\t\tg_free(phone);\n\t}\n\n\treturn(menu);\n}\n\nstruct sipe_backend_buddy_menu *sipe_core_buddy_create_menu(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t    const gchar *buddy_name,\n\t\t\t\t\t\t\t    struct sipe_backend_buddy_menu *menu)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tsipe_backend_buddy buddy = sipe_backend_buddy_find(sipe_public,\n\t\t\t\t\t\t\t   buddy_name,\n\t\t\t\t\t\t\t   NULL);\n\tgchar *self = sip_uri_self(sipe_private);\n\n \tSIPE_SESSION_FOREACH {\n\t\tif (!sipe_strcase_equal(self, buddy_name) && session->chat_session)\n\t\t{\n\t\t\tstruct sipe_chat_session *chat_session = session->chat_session;\n\t\t\tgboolean is_conf = (chat_session->type == SIPE_CHAT_TYPE_CONFERENCE);\n\n\t\t\tif (sipe_backend_chat_find(chat_session->backend, buddy_name))\n\t\t\t{\n\t\t\t\tgboolean conf_op = sipe_backend_chat_is_operator(chat_session->backend, self);\n\n\t\t\t\tif (is_conf &&\n\t\t\t\t    /* Not conf OP */\n\t\t\t\t    !sipe_backend_chat_is_operator(chat_session->backend, buddy_name) &&\n\t\t\t\t    /* We are a conf OP */\n\t\t\t\t    conf_op) {\n\t\t\t\t\tgchar *label = g_strdup_printf(_(\"Make leader of '%s'\"),\n\t\t\t\t\t\t\t\t       chat_session->title);\n\t\t\t\t\tmenu = sipe_backend_buddy_menu_add(sipe_public,\n\t\t\t\t\t\t\t\t\t   menu,\n\t\t\t\t\t\t\t\t\t   label,\n\t\t\t\t\t\t\t\t\t   SIPE_BUDDY_MENU_MAKE_CHAT_LEADER,\n\t\t\t\t\t\t\t\t\t   chat_session);\n\t\t\t\t\tg_free(label);\n\t\t\t\t}\n\n\t\t\t\tif (is_conf &&\n\t\t\t\t    /* We are a conf OP */\n\t\t\t\t    conf_op) {\n\t\t\t\t\tgchar *label = g_strdup_printf(_(\"Remove from '%s'\"),\n\t\t\t\t\t\t\t\t       chat_session->title);\n\t\t\t\t\tmenu = sipe_backend_buddy_menu_add(sipe_public,\n\t\t\t\t\t\t\t\t\t   menu,\n\t\t\t\t\t\t\t\t\t   label,\n\t\t\t\t\t\t\t\t\t   SIPE_BUDDY_MENU_REMOVE_FROM_CHAT,\n\t\t\t\t\t\t\t\t\t   chat_session);\n\t\t\t\t\tg_free(label);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (!is_conf ||\n\t\t\t\t    (is_conf && !session->locked)) {\n\t\t\t\t\tgchar *label = g_strdup_printf(_(\"Invite to '%s'\"),\n\t\t\t\t\t\t\t\t       chat_session->title);\n\t\t\t\t\tmenu = sipe_backend_buddy_menu_add(sipe_public,\n\t\t\t\t\t\t\t\t\t menu,\n\t\t\t\t\t\t\t\t\t label,\n\t\t\t\t\t\t\t\t\t SIPE_BUDDY_MENU_INVITE_TO_CHAT,\n\t\t\t\t\t\t\t\t\t chat_session);\n\t\t\t\t\tg_free(label);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} SIPE_SESSION_FOREACH_END;\n\tg_free(self);\n\n\tmenu = sipe_backend_buddy_menu_add(sipe_public,\n\t\t\t\t\t   menu,\n\t\t\t\t\t   _(\"New chat\"),\n\t\t\t\t\t   SIPE_BUDDY_MENU_NEW_CHAT,\n\t\t\t\t\t   NULL);\n\n\t/* add buddy's phone numbers if we have call control */\n\tif (sip_csta_is_idle(sipe_private)) {\n\n\t\t/* work phone */\n\t\tmenu = buddy_menu_phone(sipe_public,\n\t\t\t\t\tmenu,\n\t\t\t\t\tbuddy,\n\t\t\t\t\tSIPE_BUDDY_INFO_WORK_PHONE,\n\t\t\t\t\tSIPE_BUDDY_INFO_WORK_PHONE_DISPLAY,\n\t\t\t\t\t_(\"Work\"));\n\t\t/* mobile phone */\n\t\tmenu = buddy_menu_phone(sipe_public,\n\t\t\t\t\tmenu,\n\t\t\t\t\tbuddy,\n\t\t\t\t\tSIPE_BUDDY_INFO_MOBILE_PHONE,\n\t\t\t\t\tSIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY,\n\t\t\t\t\t_(\"Mobile\"));\n\n\t\t/* home phone */\n\t\tmenu = buddy_menu_phone(sipe_public,\n\t\t\t\t\tmenu,\n\t\t\t\t\tbuddy,\n\t\t\t\t\tSIPE_BUDDY_INFO_HOME_PHONE,\n\t\t\t\t\tSIPE_BUDDY_INFO_HOME_PHONE_DISPLAY,\n\t\t\t\t\t_(\"Home\"));\n\n\t\t/* other phone */\n\t\tmenu = buddy_menu_phone(sipe_public,\n\t\t\t\t\tmenu,\n\t\t\t\t\tbuddy,\n\t\t\t\t\tSIPE_BUDDY_INFO_OTHER_PHONE,\n\t\t\t\t\tSIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY,\n\t\t\t\t\t_(\"Other\"));\n\n\t\t/* custom1 phone */\n\t\tmenu = buddy_menu_phone(sipe_public,\n\t\t\t\t\tmenu,\n\t\t\t\t\tbuddy,\n\t\t\t\t\tSIPE_BUDDY_INFO_CUSTOM1_PHONE,\n\t\t\t\t\tSIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY,\n\t\t\t\t\t_(\"Custom1\"));\n\t}\n\n\t{\n\t\tgchar *email = sipe_backend_buddy_get_string(sipe_public,\n\t\t\t\t\t\t\t     buddy,\n\t\t\t\t\t\t\t     SIPE_BUDDY_INFO_EMAIL);\n\t\tif (email) {\n\t\t\tmenu = sipe_backend_buddy_menu_add(sipe_public,\n\t\t\t\t\t\t\t   menu,\n\t\t\t\t\t\t\t   _(\"Send email...\"),\n\t\t\t\t\t\t\t   SIPE_BUDDY_MENU_SEND_EMAIL,\n\t\t\t\t\t\t\t   NULL);\n\t\t\tg_free(email);\n\t\t}\n\t}\n\n#ifdef HAVE_APPSHARE_SERVER\n\t{\n\t\tstruct sipe_media_call *call = sipe_media_call_find(SIPE_CORE_PRIVATE,\n\t\t\t\t\t\t\t\t    buddy_name);\n\n\t\tif (call && sipe_appshare_get_role(call) == SIPE_APPSHARE_ROLE_PRESENTER) {\n\t\t\t/* We're already presenting to this buddy. */\n\n\t\t\tif (sipe_core_appshare_get_remote_control(call)) {\n\t\t\t\tmenu = sipe_backend_buddy_menu_add(sipe_public, menu,\n\t\t\t\t\t\t_(\"Take desktop control\"),\n\t\t\t\t\t\tSIPE_BUDDY_MENU_TAKE_DESKTOP_CONTROL,\n\t\t\t\t\t\tcall);\n\t\t\t} else {\n\t\t\t\tmenu = sipe_backend_buddy_menu_add(sipe_public, menu,\n\t\t\t\t\t\t_(\"Give desktop control\"),\n\t\t\t\t\t\tSIPE_BUDDY_MENU_GIVE_DESKTOP_CONTROL,\n\t\t\t\t\t\tcall);\n\t\t\t}\n\t\t} else {\n\t\t\tmenu = sipe_backend_buddy_menu_add(sipe_public, menu,\n\t\t\t\t\t\t\t   _(\"Share my desktop\"),\n\t\t\t\t\t\t\t   SIPE_BUDDY_MENU_SHARE_DESKTOP,\n\t\t\t\t\t\t\t   NULL);\n\t\t}\n\t}\n#endif // HAVE_APPSHARE_SERVER\n\n\t/* access level control */\n\tif (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007))\n\t\tmenu = sipe_backend_buddy_sub_menu_add(sipe_public,\n\t\t\t\t\t\t       menu,\n\t\t\t\t\t\t       _(\"Access level\"),\n\t\t\t\t\t\t       sipe_ocs2007_access_control_menu(sipe_private,\n\t\t\t\t\t\t\t\t\t\t\tbuddy_name));\n\n\treturn(menu);\n}\n\nguint sipe_buddy_count(struct sipe_core_private *sipe_private)\n{\n\treturn(g_hash_table_size(sipe_private->buddies->uri));\n}\n\nstatic guint sipe_ht_hash_nick(const char *nick)\n{\n\tchar *lc = g_utf8_strdown(nick, -1);\n\tguint bucket = g_str_hash(lc);\n\tg_free(lc);\n\n\treturn bucket;\n}\n\nstatic gboolean sipe_ht_equals_nick(const char *nick1, const char *nick2)\n{\n\tchar *nick1_norm = NULL;\n\tchar *nick2_norm = NULL;\n\tgboolean equal;\n\n\tif (nick1 == NULL && nick2 == NULL) return TRUE;\n\tif (nick1 == NULL || nick2 == NULL    ||\n\t    !g_utf8_validate(nick1, -1, NULL) ||\n\t    !g_utf8_validate(nick2, -1, NULL)) return FALSE;\n\n\tnick1_norm = g_utf8_casefold(nick1, -1);\n\tnick2_norm = g_utf8_casefold(nick2, -1);\n\tequal = g_utf8_collate(nick1_norm, nick2_norm) == 0;\n\tg_free(nick2_norm);\n\tg_free(nick1_norm);\n\n\treturn equal;\n}\n\nvoid sipe_buddy_init(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_buddies *buddies = g_new0(struct sipe_buddies, 1);\n\tbuddies->uri          = g_hash_table_new((GHashFunc)  sipe_ht_hash_nick,\n\t\t\t\t\t\t (GEqualFunc) sipe_ht_equals_nick);\n\tbuddies->exchange_key = g_hash_table_new(g_str_hash,\n\t\t\t\t\t\t g_str_equal);\n\tsipe_private->buddies = buddies;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-buddy.h",
    "content": "/**\n * @file sipe-buddy.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipe_backend_search_results;\nstruct sipe_cal_working_hours;\nstruct sipe_core_private;\nstruct sipe_group;\n\nstruct sipe_buddy {\n\tgchar *name;\n\tgchar *exchange_key;\n\tgchar *change_key;\n\tgchar *activity;\n\tgchar *meeting_subject;\n\tgchar *meeting_location;\n\t/* Sipe internal format for Note is HTML.\n\t * All incoming plain text should be html-escaped\n\t * for example by g_markup_escape_text()\n\t */\n\tgchar *note;\n\tgboolean is_oof_note;\n\tgboolean is_mobile;\n\ttime_t note_since;\n\n\t/* Calendar related fields */\n\tgchar *cal_start_time;\n\tint cal_granularity;\n\tgchar *cal_free_busy_base64;\n\tgchar *cal_free_busy;\n\ttime_t cal_free_busy_published;\n\t/* for 2005 systems */\n\tint user_avail;\n\ttime_t user_avail_since;\n\ttime_t activity_since;\n\tconst char *last_non_cal_status_id;\n\tgchar *last_non_cal_activity;\n\n\tstruct sipe_cal_working_hours *cal_working_hours;\n\n\tgchar *device_name;\n\tGSList *groups;\n\t /** flag to control sending 'context' element in 2007 subscriptions */\n\tgboolean just_added;\n\tgboolean is_obsolete;\n};\n\n/**\n * Adds UCS Exchange/Change keys to a @c sipe_buddy structure\n *\n * @param sipe_private SIPE core data\n * @param buddy        sipe_buddy data structure\n * @param exchange_key Exchange key (may be @c NULL)\n * @param change_key   Change key (may be @c NULL)\n */\nvoid sipe_buddy_add_keys(struct sipe_core_private *sipe_private,\n\t\t\t struct sipe_buddy *buddy,\n\t\t\t const gchar *exchange_key,\n\t\t\t const gchar *change_key);\n\n/**\n * Creates @c sipe_buddy structure for a new buddy and adds it into the buddy\n * list of given account. If buddy is already in the list, its existing\n * structure is returned.\n *\n * @param sipe_private SIPE core data\n * @param uri          SIP URI of a buddy\n * @param exchange_key Exchange key (may be @c NULL)\n * @param change_key   Change key (may be @c NULL)\n *\n * @return @c sipe_buddy structure\n */\nstruct sipe_buddy *sipe_buddy_add(struct sipe_core_private *sipe_private,\n\t\t\t\t  const gchar *uri,\n\t\t\t\t  const gchar *exchange_key,\n\t\t\t\t  const gchar *change_key);\n\n/**\n * Add buddy to a group.\n *\n * @param sipe_private SIPE core data\n * @param buddy        sipe_buddy data structure\n * @param group        sipe_group data structure\n * @param alias        alias for the buddy in that group (may be @c NULL)\n */\nvoid sipe_buddy_add_to_group(struct sipe_core_private *sipe_private,\n\t\t\t     struct sipe_buddy *buddy,\n\t\t\t     struct sipe_group *group,\n\t\t\t     const gchar *alias);\n\n/**\n * Insert a group to buddy group list\n *\n * @param buddy        sipe_buddy data structure\n * @param group        sipe_group data structure\n */\nvoid sipe_buddy_insert_group(struct sipe_buddy *buddy,\n\t\t\t     struct sipe_group *group);\n\n/**\n * Update group list for a buddy\n *\n * @param sipe_private SIPE core data\n * @param buddy        sipe_buddy data structure\n * @param group        list with new sipe_group data structures\n */\nvoid sipe_buddy_update_groups(struct sipe_core_private *sipe_private,\n\t\t\t      struct sipe_buddy *buddy,\n\t\t\t      GSList *new_groups);\n\n/**\n * Returns string of group IDs the buddy belongs to, e.g. \"2 4 7 8\"\n *\n * @param buddy sipe_buddy data structure\n *\n * @result group string. Must be @c g_free()'d after use.\n */\ngchar *sipe_buddy_groups_string(struct sipe_buddy *buddy);\n\n/**\n * Remove entries from local buddy list that do not have corresponding entries\n * in the ones in the contact list sent by the server\n *\n * @param sipe_private SIPE core data\n */\nvoid sipe_buddy_cleanup_local_list(struct sipe_core_private *sipe_private);\n\n/**\n * Prepare buddy list for an update\n *\n * @param sipe_private SIPE core data\n */\nvoid sipe_buddy_update_start(struct sipe_core_private *sipe_private);\n\n/**\n * Finish buddy list update. This will remove obsolete buddies.\n *\n * @param sipe_private SIPE core data\n */\nvoid sipe_buddy_update_finish(struct sipe_core_private *sipe_private);\n\n/**\n * Find buddy by URI\n *\n * @param sipe_private SIPE core data\n * @param uri          SIP URI of a buddy (may be @c NULL)\n *\n * @return @c sipe_buddy structure or @c NULL\n */\nstruct sipe_buddy *sipe_buddy_find_by_uri(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  const gchar *uri);\n\n/**\n * Find buddy by Exchange Key\n *\n * @param sipe_private SIPE core data\n * @param uri          Exchange Key of a buddy\n *\n * @return @c sipe_buddy structure\n */\nstruct sipe_buddy *sipe_buddy_find_by_exchange_key(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t   const gchar *exchange_key);\n\n/**\n * Iterate buddy list\n *\n * @param sipe_private SIPE core data\n * @param callback          function to call on each buddy\n * @param callback_data     user data for the callback\n */\nvoid sipe_buddy_foreach(struct sipe_core_private *sipe_private,\n\t\t\tGHFunc callback,\n\t\t\tgpointer callback_data);\n\n/**\n * Cancels buddy subscriptions and then deletes the buddy\n *\n * @param sipe_private SIPE core data\n * @param buddy        @c sipe_buddy structure to remove\n */\nvoid sipe_buddy_remove(struct sipe_core_private *sipe_private,\n\t\t       struct sipe_buddy *buddy);\n\n/**\n * Tries to retrieve a real user's name associated with given SIP URI.\n *\n * Result must be g_free'd after use.\n *\n * @param sipe_private SIPE core data\n * @param with         a SIP URI\n *\n * @return Name of the user if the URI is found in buddy list, otherwise @c NULL\n */\ngchar *sipe_buddy_get_alias(struct sipe_core_private *sipe_private,\n\t\t\t    const gchar *with);\n\n/**\n * Update the value of a buddy property with given SIP URI\n *\n * @param sipe_private   SIPE core data\n * @param uri            a SIP URI\n * @param propkey        property id (see sipe-backend.h)\n * @param property_value new value for the property\n */\nvoid sipe_buddy_update_property(struct sipe_core_private *sipe_private,\n\t\t\t\tconst gchar *uri,\n\t\t\t\tsipe_buddy_info_fields propkey,\n\t\t\t\tgchar *property_value);\n\n/**\n * Update the buddy photo with given SIP URI. If hash is the same\n * as the cached one then the fetching of the photo is skipped.\n *\n * @param sipe_private SIPE core data\n * @param uri          a SIP URI\n * @param photo_hash   hash value for the photo data\n * @param photo_url    HTTP URL where to get the photo data\n * @param headers      additional HTTP headers (may be @c NULL)\n */\nvoid sipe_buddy_update_photo(struct sipe_core_private *sipe_private,\n\t\t\t     const gchar *uri,\n\t\t\t     const gchar *photo_hash,\n\t\t\t     const gchar *photo_url,\n\t\t\t     const gchar *headers);\n\n/**\n * Triggers a download of all buddy photos that were changed on the server.\n *\n * @param sipe_private SIPE core data\n */\nvoid sipe_buddy_refresh_photos(struct sipe_core_private *sipe_private);\n\n/**\n * Finalize the search results and display results to user.\n *\n * @param sipe_private SIPE core data\n * @param results      opaque results handle for backend\n * @param match_count  number of matches found\n * @param more         @c TRUE if there are more matches available\n */\nvoid sipe_buddy_search_contacts_finalize(struct sipe_core_private *sipe_private,\n\t\t\t\t\t struct sipe_backend_search_results *results,\n\t\t\t\t\t guint match_count,\n\t\t\t\t\t gboolean more);\n\n/**\n * Number of buddies\n *\n * @param sipe_private SIPE core data\n */\nguint sipe_buddy_count(struct sipe_core_private *sipe_private);\n\n/**\n * Initialize buddy data\n *\n * @param sipe_private SIPE core data\n */\nvoid sipe_buddy_init(struct sipe_core_private *sipe_private);\n\n/**\n * Free buddy data\n *\n * @param sipe_private SIPE core data\n */\nvoid sipe_buddy_free(struct sipe_core_private *sipe_private);\n"
  },
  {
    "path": "src/core/sipe-cal.c",
    "content": "/**\n * @file sipe-cal.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2018 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2009 pier11 <pier11@operamail.com>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#include <glib.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-buddy.h\"\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-cal.h\"\n#include \"sipe-http.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-ocs2005.h\"\n#include \"sipe-ocs2007.h\"\n#include \"sipe-schedule.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n\n/* Calendar backends */\n#ifdef _WIN32\n#include \"sipe-domino.h\"\n#endif\n#include \"sipe-ews.h\"\n\n#define TIME_NULL   (time_t)-1\n#define IS(time)    (time != TIME_NULL)\n\n/*\nhttp://msdn.microsoft.com/en-us/library/aa565001.aspx\n\n<?xml version=\"1.0\"?>\n<WorkingHours xmlns=\"http://schemas.microsoft.com/exchange/services/2006/types\">\n  <TimeZone>\n    <Bias>480</Bias>\n    <StandardTime>\n      <Bias>0</Bias>\n      <Time>02:00:00</Time>\n      <DayOrder>1</DayOrder>\n      <Month>11</Month>\n      <DayOfWeek>Sunday</DayOfWeek>\n    </StandardTime>\n    <DaylightTime>\n      <Bias>-60</Bias>\n      <Time>02:00:00</Time>\n      <DayOrder>2</DayOrder>\n      <Month>3</Month>\n      <DayOfWeek>Sunday</DayOfWeek>\n    </DaylightTime>\n  </TimeZone>\n  <WorkingPeriodArray>\n    <WorkingPeriod>\n      <DayOfWeek>Monday Tuesday Wednesday Thursday Friday</DayOfWeek>\n      <StartTimeInMinutes>600</StartTimeInMinutes>\n      <EndTimeInMinutes>1140</EndTimeInMinutes>\n    </WorkingPeriod>\n  </WorkingPeriodArray>\n</WorkingHours>\n\nDesc:\n<StandardTime>\n   <Bias>int</Bias>\n   <Time>string</Time>\n   <DayOrder>short</DayOrder>\n   <Month>short</Month>\n   <DayOfWeek>Sunday or Monday or Tuesday or Wednesday or Thursday or Friday or Saturday</DayOfWeek>\n   <Year>string</Year>\n</StandardTime>\n*/\n\nstruct sipe_cal_std_dst {\n\tint bias;           /* Ex.: -60 */\n\tgchar *time;        /* hh:mm:ss, 02:00:00 */\n\tint day_order;      /* 1..5 */\n\tint month;          /* 1..12 */\n\tgchar *day_of_week; /* Sunday or Monday or Tuesday or Wednesday or Thursday or Friday or Saturday */\n\tgchar *year;        /* YYYY */\n\n\ttime_t switch_time;\n};\n\nstruct sipe_cal_working_hours {\n\tint bias;                     /* Ex.: 480 */\n\tstruct sipe_cal_std_dst std;  /* StandardTime */\n\tstruct sipe_cal_std_dst dst;  /* DaylightTime */\n\tgchar *days_of_week;          /* Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday separated by space */\n\tint start_time;               /* 0...1440 */\n\tint end_time;                 /* 0...1440 */\n\n\tgchar *tz;                    /* aggregated timezone string as in TZ environment variable.\n\t                                 Ex.: TST+8TDT+7,M3.2.0/02:00:00,M11.1.0/02:00:00 */\n\t/** separate simple strings for Windows platform as the proper TZ does not work there.\n\t *  anyway, dynamic timezones would't work with just TZ\n\t */\n\tgchar *tz_std;                /* Ex.: TST8 */\n\tgchar *tz_dst;                /* Ex.: TDT7 */\n};\n\n/* not for translation, a part of XML Schema definitions */\nstatic const char *wday_names[] = {\"Sunday\",\n\t\t\t\t   \"Monday\",\n\t\t\t\t   \"Tuesday\",\n\t\t\t\t   \"Wednesday\",\n\t\t\t\t   \"Thursday\",\n\t\t\t\t   \"Friday\",\n\t\t\t\t   \"Saturday\"};\nstatic int\nsipe_cal_get_wday(char *wday_name)\n{\n\tint i;\n\n\tif (!wday_name) return -1;\n\n\tfor (i = 0; i < 7; i++) {\n\t\tif (sipe_strequal(wday_names[i], wday_name)) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\nvoid\nsipe_cal_event_free(struct sipe_cal_event* cal_event)\n{\n\tif (!cal_event) return;\n\n\tg_free(cal_event->subject);\n\tg_free(cal_event->location);\n\tg_free(cal_event);\n}\n\nvoid\nsipe_cal_events_free(GSList *cal_events)\n{\n\tif (!cal_events) return;\n\tsipe_utils_slist_free_full(cal_events,\n\t\t\t\t   (GDestroyNotify) sipe_cal_event_free);\n}\n\nvoid\nsipe_cal_calendar_free(struct sipe_calendar *cal)\n{\n\tif (cal) {\n\t\tg_free(cal->email);\n\t\tg_free(cal->legacy_dn);\n\t\tg_free(cal->as_url);\n\t\tg_free(cal->oof_url);\n\t\tg_free(cal->oab_url);\n\t\tg_free(cal->domino_url);\n\t\tg_free(cal->oof_state);\n\t\tg_free(cal->oof_note);\n\t\tg_free(cal->free_busy);\n\t\tg_free(cal->working_hours_xml_str);\n\n\t\tsipe_cal_events_free(cal->cal_events);\n\n\t\tif (cal->request)\n\t\t\tsipe_http_request_cancel(cal->request);\n\t\tsipe_http_session_close(cal->session);\n\n\t\tg_free(cal);\n\t}\n}\n\nvoid\nsipe_cal_calendar_init(struct sipe_core_private *sipe_private)\n{\n\tif (!sipe_private->calendar) {\n\t\tstruct sipe_calendar *cal;\n\t\tconst char *value;\n\n\t\tsipe_private->calendar = cal = g_new0(struct sipe_calendar, 1);\n\t\tcal->sipe_private = sipe_private;\n\n\t\tcal->email = g_strdup(sipe_private->email);\n\n\t\t/* user specified a service URL? */\n\t\tvalue = sipe_backend_setting(SIPE_CORE_PUBLIC, SIPE_SETTING_EMAIL_URL);\n\t\tif (!is_empty(value)) {\n\t\t\tcal->as_url  = g_strdup(value);\n\t\t\tcal->oof_url = g_strdup(value);\n\t\t\tcal->domino_url  = g_strdup(value);\n\t\t}\n\t}\n\treturn;\n}\n\n\nvoid\nsipe_cal_event_debug(const struct sipe_cal_event *cal_event,\n\t\t     const gchar *label)\n{\n\tGString* str = g_string_new(NULL);\n\tconst gchar *status = \"\";\n\n\tswitch(cal_event->cal_status) {\n\t\tcase SIPE_CAL_FREE:\t\tstatus = \"SIPE_CAL_FREE\";\tbreak;\n\t\tcase SIPE_CAL_TENTATIVE:\tstatus = \"SIPE_CAL_TENTATIVE\";\tbreak;\n\t\tcase SIPE_CAL_BUSY:\t\tstatus = \"SIPE_CAL_BUSY\";\tbreak;\n\t\tcase SIPE_CAL_OOF:\t\tstatus = \"SIPE_CAL_OOF\";\tbreak;\n\t\tcase SIPE_CAL_NO_DATA:\t\tstatus = \"SIPE_CAL_NO_DATA\";\tbreak;\n\t}\n\n\tg_string_append_printf(str, \"\\tstart_time: %s\\n\",\n\t\tIS(cal_event->start_time) ? sipe_utils_time_to_debug_str(localtime(&cal_event->start_time)) : \"\");\n\tg_string_append_printf(str, \"\\tend_time  : %s\\n\",\n\t\tIS(cal_event->end_time) ? sipe_utils_time_to_debug_str(localtime(&cal_event->end_time)) : \"\");\n\tg_string_append_printf(str, \"\\tcal_status: %s\\n\", status);\n\tg_string_append_printf(str, \"\\tsubject   : %s\\n\", cal_event->subject ? cal_event->subject : \"\");\n\tg_string_append_printf(str, \"\\tlocation  : %s\\n\", cal_event->location ? cal_event->location : \"\");\n\t/* last line must have no line break */\n\tg_string_append_printf(str, \"\\tis_meeting: %s\", cal_event->is_meeting ? \"TRUE\" : \"FALSE\");\n\n\tSIPE_DEBUG_INFO(\"%s%s\", label, str->str);\n\tg_string_free(str, TRUE);\n}\n\nchar *\nsipe_cal_event_hash(struct sipe_cal_event* event)\n{\n\t/* no end_time as it dos not get published */\n\t/* no cal_status as it can change on publication */\n\treturn g_strdup_printf(\"<%d><%s><%s><%d>\",\n\t\t\t\t(int)event->start_time,\n\t\t\t\tevent->subject ? event->subject : \"\",\n\t\t\t\tevent->location ? event->location : \"\",\n\t\t\t\tevent->is_meeting);\n}\n\n#define ENVIRONMENT_TIMEZONE \"TZ\"\n\nstatic gchar *\nsipe_switch_tz(const char *tz)\n{\n\tgchar *tz_orig;\n\n\ttz_orig = g_strdup(g_getenv(ENVIRONMENT_TIMEZONE));\n\tg_setenv(ENVIRONMENT_TIMEZONE, tz, TRUE);\n\ttzset();\n\treturn(tz_orig);\n}\n\nstatic void\nsipe_reset_tz(gchar *tz_orig)\n{\n\tif (tz_orig) {\n\t\tg_setenv(ENVIRONMENT_TIMEZONE, tz_orig, TRUE);\n\t\tg_free(tz_orig);\n\t} else {\n\t\tg_unsetenv(ENVIRONMENT_TIMEZONE);\n\t}\n\ttzset();\n}\n\n/**\n * Converts struct tm to Epoch time_t considering timezone.\n *\n * @param tz as defined for TZ environment variable.\n *\n * Reference: see timegm(3) - Linux man page\n */\ntime_t\nsipe_mktime_tz(struct tm *tm,\n\t       const char* tz)\n{\n\ttime_t ret;\n\tgchar *tz_orig;\n\n\ttz_orig = sipe_switch_tz(tz);\n\tret = mktime(tm);\n\tsipe_reset_tz(tz_orig);\n\n\treturn ret;\n}\n\n/**\n * Converts Epoch time_t to struct tm considering timezone.\n *\n * @param tz as defined for TZ environment variable.\n *\n * Reference: see timegm(3) - Linux man page\n */\nstatic struct tm *\nsipe_localtime_tz(const time_t *time,\n\t\t  const char* tz)\n{\n\tstruct tm *ret;\n\tgchar *tz_orig;\n\n\ttz_orig = sipe_switch_tz(tz);\n\tret = localtime(time);\n\tsipe_reset_tz(tz_orig);\n\n\treturn ret;\n}\n\nvoid\nsipe_cal_free_working_hours(struct sipe_cal_working_hours *wh)\n{\n\tif (!wh) return;\n\n\tg_free(wh->std.time);\n\tg_free(wh->std.day_of_week);\n\tg_free(wh->std.year);\n\n\tg_free(wh->dst.time);\n\tg_free(wh->dst.day_of_week);\n\tg_free(wh->dst.year);\n\n\tg_free(wh->days_of_week);\n\tg_free(wh->tz);\n\tg_free(wh->tz_std);\n\tg_free(wh->tz_dst);\n\tg_free(wh);\n}\n\n/**\n * Returns time_t of daylight savings time start/end\n * in the provided timezone or otherwise\n * (time_t)-1 if no daylight savings time.\n */\nstatic time_t\nsipe_cal_get_std_dst_time(time_t now,\n\t\t\t  int bias,\n\t\t\t  struct sipe_cal_std_dst* std_dst,\n\t\t\t  struct sipe_cal_std_dst* dst_std)\n{\n\tstruct tm switch_tm;\n\ttime_t res = TIME_NULL;\n\tstruct tm *gm_now_tm;\n\tgchar **time_arr;\n\n\tif (std_dst->month == 0) return TIME_NULL;\n\n\tgm_now_tm = gmtime(&now);\n\ttime_arr = g_strsplit(std_dst->time, \":\", 0);\n\n\tswitch_tm.tm_sec  = atoi(time_arr[2]);\n\tswitch_tm.tm_min  = atoi(time_arr[1]);\n\tswitch_tm.tm_hour = atoi(time_arr[0]);\n\tg_strfreev(time_arr);\n\tswitch_tm.tm_mday  = std_dst->year ? std_dst->day_order : 1 /* to adjust later */ ;\n\tswitch_tm.tm_mon   = std_dst->month - 1;\n\tswitch_tm.tm_year  = std_dst->year ? atoi(std_dst->year) - 1900 : gm_now_tm->tm_year;\n\tswitch_tm.tm_isdst = 0;\n\t/* to set tm_wday */\n\tres = sipe_mktime_tz(&switch_tm, \"UTC\");\n\n\t/* if not dynamic, calculate right tm_mday */\n\tif (!std_dst->year) {\n\t\tint switch_wday = sipe_cal_get_wday(std_dst->day_of_week);\n\t\tint needed_month;\n\t\t/* get first desired wday in the month */\n\t\tint delta = switch_wday >= switch_tm.tm_wday ? (switch_wday - switch_tm.tm_wday) : (switch_wday + 7 - switch_tm.tm_wday);\n\t\tswitch_tm.tm_mday = 1 + delta;\n\t\t/* try nth order */\n\t\tswitch_tm.tm_mday += (std_dst->day_order - 1) * 7;\n\t\tneeded_month = switch_tm.tm_mon;\n\t\t/* to set settle date if ahead of allowed month dates */\n\t\tres = sipe_mktime_tz(&switch_tm, \"UTC\");\n\t\tif (needed_month != switch_tm.tm_mon) {\n\t\t\t/* moving 1 week back to stay within required month */\n\t\t\tswitch_tm.tm_mday -= 7;\n\t\t\t/* to fix date again */\n\t\t\tres = sipe_mktime_tz(&switch_tm, \"UTC\");\n\t\t}\n\t}\n\t/* note: bias is taken from \"switch to\" structure */\n\treturn res + (bias + dst_std->bias)*60;\n}\n\nstatic void\nsipe_cal_parse_std_dst(const sipe_xml *xn_std_dst_time,\n\t\t       struct sipe_cal_std_dst *std_dst)\n{\n\tconst sipe_xml *node;\n\tgchar *tmp;\n\n\tif (!xn_std_dst_time) return;\n\tif (!std_dst) return;\n/*\n    <StandardTime>\n      <Bias>0</Bias>\n      <Time>02:00:00</Time>\n      <DayOrder>1</DayOrder>\n      <Month>11</Month>\n      <Year>2009</Year>\n      <DayOfWeek>Sunday</DayOfWeek>\n    </StandardTime>\n*/\n\n\tif ((node = sipe_xml_child(xn_std_dst_time, \"Bias\"))) {\n\t\tstd_dst->bias = atoi(tmp = sipe_xml_data(node));\n\t\tg_free(tmp);\n\t}\n\n\tif ((node = sipe_xml_child(xn_std_dst_time, \"Time\"))) {\n\t\tstd_dst->time = sipe_xml_data(node);\n\t}\n\n\tif ((node = sipe_xml_child(xn_std_dst_time, \"DayOrder\"))) {\n\t\tstd_dst->day_order = atoi(tmp = sipe_xml_data(node));\n\t\tg_free(tmp);\n\t}\n\n\tif ((node = sipe_xml_child(xn_std_dst_time, \"Month\"))) {\n\t\tstd_dst->month = atoi(tmp = sipe_xml_data(node));\n\t\tg_free(tmp);\n\t}\n\n\tif ((node = sipe_xml_child(xn_std_dst_time, \"DayOfWeek\"))) {\n\t\tstd_dst->day_of_week = sipe_xml_data(node);\n\t}\n\n\tif ((node = sipe_xml_child(xn_std_dst_time, \"Year\"))) {\n\t\tstd_dst->year = sipe_xml_data(node);\n\t}\n}\n\nvoid\nsipe_cal_parse_working_hours(const sipe_xml *xn_working_hours,\n\t\t\t     struct sipe_buddy *buddy)\n{\n\tconst sipe_xml *xn_bias;\n\tconst sipe_xml *xn_timezone;\n\tconst sipe_xml *xn_working_period;\n\tconst sipe_xml *xn_standard_time;\n\tconst sipe_xml *xn_daylight_time;\n\tgchar *tmp;\n\ttime_t now = time(NULL);\n\tstruct sipe_cal_std_dst* std;\n\tstruct sipe_cal_std_dst* dst;\n\n\tif (!xn_working_hours) return;\n/*\n<WorkingHours xmlns=\"http://schemas.microsoft.com/exchange/services/2006/types\">\n  <TimeZone>\n    <Bias>480</Bias>\n    ...\n  </TimeZone>\n  <WorkingPeriodArray>\n    <WorkingPeriod>\n      <DayOfWeek>Monday Tuesday Wednesday Thursday Friday</DayOfWeek>\n      <StartTimeInMinutes>600</StartTimeInMinutes>\n      <EndTimeInMinutes>1140</EndTimeInMinutes>\n    </WorkingPeriod>\n  </WorkingPeriodArray>\n</WorkingHours>\n*/\n\tsipe_cal_free_working_hours(buddy->cal_working_hours);\n\tbuddy->cal_working_hours = g_new0(struct sipe_cal_working_hours, 1);\n\n\txn_timezone = sipe_xml_child(xn_working_hours, \"TimeZone\");\n\txn_bias = sipe_xml_child(xn_timezone, \"Bias\");\n\tif (xn_bias) {\n\t\tbuddy->cal_working_hours->bias = atoi(tmp = sipe_xml_data(xn_bias));\n\t\tg_free(tmp);\n\t}\n\n\txn_standard_time = sipe_xml_child(xn_timezone, \"StandardTime\");\n\txn_daylight_time = sipe_xml_child(xn_timezone, \"DaylightTime\");\n\n\tstd = &((*buddy->cal_working_hours).std);\n\tdst = &((*buddy->cal_working_hours).dst);\n\tsipe_cal_parse_std_dst(xn_standard_time, std);\n\tsipe_cal_parse_std_dst(xn_daylight_time, dst);\n\n\txn_working_period = sipe_xml_child(xn_working_hours, \"WorkingPeriodArray/WorkingPeriod\");\n\tif (xn_working_period) {\n\t\t/* NOTE: this can be NULL! */\n\t\tbuddy->cal_working_hours->days_of_week =\n\t\t\tsipe_xml_data(sipe_xml_child(xn_working_period, \"DayOfWeek\"));\n\n\t\tbuddy->cal_working_hours->start_time =\n\t\t\tatoi(tmp = sipe_xml_data(sipe_xml_child(xn_working_period, \"StartTimeInMinutes\")));\n\t\tg_free(tmp);\n\n\t\tbuddy->cal_working_hours->end_time =\n\t\t\tatoi(tmp = sipe_xml_data(sipe_xml_child(xn_working_period, \"EndTimeInMinutes\")));\n\t\tg_free(tmp);\n\t}\n\n\tstd->switch_time = sipe_cal_get_std_dst_time(now, buddy->cal_working_hours->bias, std, dst);\n\tdst->switch_time = sipe_cal_get_std_dst_time(now, buddy->cal_working_hours->bias, dst, std);\n\n\t/* TST8TDT7,M3.2.0/02:00:00,M11.1.0/02:00:00 */\n\tbuddy->cal_working_hours->tz =\n\t\tg_strdup_printf(\"TST%dTDT%d,M%d.%d.%d/%s,M%d.%d.%d/%s\",\n\t\t\t\t(buddy->cal_working_hours->bias + buddy->cal_working_hours->std.bias) / 60,\n\t\t\t\t(buddy->cal_working_hours->bias + buddy->cal_working_hours->dst.bias) / 60,\n\n\t\t\t\tbuddy->cal_working_hours->dst.month,\n\t\t\t\tbuddy->cal_working_hours->dst.day_order,\n\t\t\t\tsipe_cal_get_wday(buddy->cal_working_hours->dst.day_of_week),\n\t\t\t\tbuddy->cal_working_hours->dst.time,\n\n\t\t\t\tbuddy->cal_working_hours->std.month,\n\t\t\t\tbuddy->cal_working_hours->std.day_order,\n\t\t\t\tsipe_cal_get_wday(buddy->cal_working_hours->std.day_of_week),\n\t\t\t\tbuddy->cal_working_hours->std.time\n\t\t\t\t);\n\t/* TST8 */\n\tbuddy->cal_working_hours->tz_std =\n\t\tg_strdup_printf(\"TST%d\",\n\t\t\t\t(buddy->cal_working_hours->bias + buddy->cal_working_hours->std.bias) / 60);\n\t/* TDT7 */\n\tbuddy->cal_working_hours->tz_dst =\n\t\tg_strdup_printf(\"TDT%d\",\n\t\t\t\t(buddy->cal_working_hours->bias + buddy->cal_working_hours->dst.bias) / 60);\n}\n\nstruct sipe_cal_event*\nsipe_cal_get_event(GSList *cal_events,\n\t\t   time_t time_in_question)\n{\n\tGSList *entry = cal_events;\n\tstruct sipe_cal_event* cal_event;\n\tstruct sipe_cal_event* res = NULL;\n\n\tif (!cal_events || !IS(time_in_question)) return NULL;\n\n\twhile (entry) {\n\t\tcal_event = entry->data;\n\t\t/* event is in the past or in the future */\n\t\tif (cal_event->start_time >  time_in_question  ||\n\t\t    cal_event->end_time   <= time_in_question)\n\t\t{\n\t\t\tentry = entry->next;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!res) {\n\t\t\tres = cal_event;\n\t\t} else {\n\t\t\tint res_status = (res->cal_status == SIPE_CAL_NO_DATA) ? -1 : res->cal_status;\n\t\t\tint cal_status = (cal_event->cal_status == SIPE_CAL_NO_DATA) ? -1 : cal_event->cal_status;\n\t\t\tif (res_status < cal_status) {\n\t\t\t\tres = cal_event;\n\t\t\t}\n\t\t}\n\t\tentry = entry->next;\n\t}\n\treturn res;\n}\n\nstatic int\nsipe_cal_get_status0(const gchar *free_busy,\n\t\t     time_t cal_start,\n\t\t     int granularity,\n\t\t     time_t time_in_question,\n\t\t     int *index)\n{\n\tint res = SIPE_CAL_NO_DATA;\n\tint shift;\n\ttime_t cal_end = cal_start + strlen(free_busy)*granularity*60 - 1;\n\n\tif (!(time_in_question >= cal_start && time_in_question <= cal_end)) return res;\n\n\tshift = (time_in_question - cal_start) / (granularity*60);\n\tif (index) {\n\t\t*index = shift;\n\t}\n\n\tres = free_busy[shift] - '0';\n\n\treturn res;\n}\n\n/**\n * Returns time when current calendar state started\n */\nstatic time_t\nsipe_cal_get_since_time(const gchar *free_busy,\n\t\t\ttime_t calStart,\n\t\t\tint granularity,\n\t\t\tint index,\n\t\t\tint current_state)\n{\n\tint i;\n\n\tif ((index < 0) || ((size_t)(index + 1) > strlen(free_busy))) return 0;\n\n\tfor (i = index; i >= 0; i--) {\n\t\tint temp_status = free_busy[i] - '0';\n\n\t\tif (current_state != temp_status) {\n\t\t\treturn calStart + (i + 1)*granularity*60;\n\t\t}\n\t}\n\n\treturn calStart;\n}\n\nstatic char*\nsipe_cal_get_free_busy(struct sipe_buddy *buddy);\n\nint\nsipe_cal_get_status(struct sipe_buddy *buddy,\n\t\t    time_t time_in_question,\n\t\t    time_t *since)\n{\n\ttime_t cal_start;\n\tconst char* free_busy;\n\tint ret = SIPE_CAL_NO_DATA;\n\ttime_t state_since;\n\tint index = -1;\n\n\tif (!buddy || !buddy->cal_start_time || !buddy->cal_granularity) {\n\t\tSIPE_DEBUG_INFO(\"sipe_cal_get_status: no calendar data1 for %s, exiting\",\n\t\t\t\t  buddy ? (buddy->name ? buddy->name : \"\") : \"\");\n\t\treturn SIPE_CAL_NO_DATA;\n\t}\n\n\tif (!(free_busy = sipe_cal_get_free_busy(buddy))) {\n\t\tSIPE_DEBUG_INFO(\"sipe_cal_get_status: no calendar data2 for %s, exiting\", buddy->name);\n\t\treturn SIPE_CAL_NO_DATA;\n\t}\n\tSIPE_DEBUG_INFO(\"sipe_cal_get_description: buddy->cal_free_busy=\\n%s\", free_busy);\n\n\tcal_start = sipe_utils_str_to_time(buddy->cal_start_time);\n\n\tret = sipe_cal_get_status0(free_busy,\n\t\t\t\t   cal_start,\n\t\t\t\t   buddy->cal_granularity,\n\t\t\t\t   time_in_question,\n\t\t\t\t   &index);\n\tstate_since = sipe_cal_get_since_time(free_busy,\n\t\t\t\t\t      cal_start,\n\t\t\t\t\t      buddy->cal_granularity,\n\t\t\t\t\t      index,\n\t\t\t\t\t      ret);\n\n\tif (since) *since = state_since;\n\treturn ret;\n}\n\nstatic time_t\nsipe_cal_get_switch_time(const gchar *free_busy,\n\t\t\t time_t calStart,\n\t\t\t int granularity,\n\t\t\t int index,\n\t\t\t int current_state,\n\t\t\t int *to_state)\n{\n\tsize_t i;\n\ttime_t ret = TIME_NULL;\n\n\tif ((index < 0) || ((size_t) (index + 1) > strlen(free_busy))) {\n\t\t*to_state = SIPE_CAL_NO_DATA;\n\t\treturn ret;\n\t}\n\n\tfor (i = index + 1; i < strlen(free_busy); i++) {\n\t\tint temp_status = free_busy[i] - '0';\n\n\t\tif (current_state != temp_status) {\n\t\t\t*to_state = temp_status;\n\t\t\treturn calStart + i*granularity*60;\n\t\t}\n\t}\n\n\treturn ret;\n}\n\nstatic const char*\nsipe_cal_get_tz(struct sipe_cal_working_hours *wh,\n                time_t time_in_question)\n{\n\ttime_t dst_switch_time = (*wh).dst.switch_time;\n\ttime_t std_switch_time = (*wh).std.switch_time;\n\tgboolean is_dst = FALSE;\n\n\t/* No daylight savings */\n\tif (dst_switch_time == TIME_NULL) {\n\t\treturn wh->tz_std;\n\t}\n\n\tif (dst_switch_time < std_switch_time) { /* North hemosphere - Europe, US */\n\t\tif (time_in_question >= dst_switch_time && time_in_question < std_switch_time) {\n\t\t\tis_dst = TRUE;\n\t\t}\n\t} else { /* South hemisphere - Australia */\n\t\tif (time_in_question >= dst_switch_time || time_in_question < std_switch_time) {\n\t\t\tis_dst = TRUE;\n\t\t}\n\t}\n\n\tif (is_dst) {\n\t\treturn wh->tz_dst;\n\t} else {\n\t\treturn wh->tz_std;\n\t}\n}\n\nstatic time_t\nsipe_cal_mktime_of_day(struct tm *sample_today_tm,\n\t\t       const int shift_minutes,\n\t\t       const char *tz)\n{\n\tsample_today_tm->tm_sec  = 0;\n\tsample_today_tm->tm_min  = shift_minutes % 60;\n\tsample_today_tm->tm_hour = shift_minutes / 60;\n\n\treturn sipe_mktime_tz(sample_today_tm, tz);\n}\n\n/**\n * Returns work day start and end in Epoch time\n * considering the initial values are provided\n * in contact's local time zone.\n */\nstatic void\nsipe_cal_get_today_work_hours(struct sipe_cal_working_hours *wh,\n\t\t\t      time_t *start,\n\t\t\t      time_t *end,\n\t\t\t      time_t *next_start)\n{\n\ttime_t now = time(NULL);\n\tconst char *tz = sipe_cal_get_tz(wh, now);\n\tstruct tm *remote_now_tm = sipe_localtime_tz(&now, tz);\n\n\tif (!(wh->days_of_week && strstr(wh->days_of_week, wday_names[remote_now_tm->tm_wday]))) {\n\t\t/* not a work day */\n\t\t*start = TIME_NULL;\n\t\t*end = TIME_NULL;\n\t\t*next_start = TIME_NULL;\n\t\treturn;\n\t}\n\n\t*end = sipe_cal_mktime_of_day(remote_now_tm, wh->end_time, tz);\n\n\tif (now < *end) {\n\t\t*start = sipe_cal_mktime_of_day(remote_now_tm, wh->start_time, tz);\n\t\t*next_start = TIME_NULL;\n\t} else { /* calculate start of tomorrow's work day if any */\n\t\ttime_t tom = now + 24*60*60;\n\t\tstruct tm *remote_tom_tm = sipe_localtime_tz(&tom, sipe_cal_get_tz(wh, tom));\n\n\t\tif (!(wh->days_of_week && strstr(wh->days_of_week, wday_names[remote_tom_tm->tm_wday]))) {\n\t\t\t/* not a work day */\n\t\t\t*next_start = TIME_NULL;\n\t\t}\n\n\t\t*next_start = sipe_cal_mktime_of_day(remote_tom_tm, wh->start_time, sipe_cal_get_tz(wh, tom));\n\t\t*start = TIME_NULL;\n\t}\n}\n\nstatic int\nsipe_cal_is_in_work_hours(const time_t time_in_question,\n\t\t\t  const time_t start,\n\t\t\t  const time_t end)\n{\n\treturn !((time_in_question >= end) || (IS(start) && time_in_question < start));\n}\n\n/**\n * Returns time closest to now. Choses only from times ahead of now.\n * Returns TIME_NULL otherwise.\n */\nstatic time_t\nsipe_cal_get_until(const time_t now,\n\t\t   const time_t switch_time,\n\t\t   const time_t start,\n\t\t   const time_t end,\n\t\t   const time_t next_start)\n{\n\ttime_t ret = TIME_NULL;\n\tint min_diff = now - ret;\n\n\tif (IS(switch_time) && switch_time > now && (switch_time - now) < min_diff) {\n\t\tmin_diff = switch_time - now;\n\t\tret = switch_time;\n\t}\n\tif (IS(start) && start > now && (start - now) < min_diff) {\n\t\tmin_diff = start - now;\n\t\tret = start;\n\t}\n\tif (IS(end) && end > now && (end - now) < min_diff) {\n\t\tmin_diff = end - now;\n\t\tret = end;\n\t}\n\tif (IS(next_start) && next_start > now && (next_start - now) < min_diff) {\n\t\tmin_diff = next_start - now;\n\t\tret = next_start;\n\t}\n\treturn ret;\n}\n\nstatic char*\nsipe_cal_get_free_busy(struct sipe_buddy *buddy)\n{\n/* do lazy decode if necessary */\n\tif (!buddy->cal_free_busy && buddy->cal_free_busy_base64) {\n\t\tgsize cal_dec64_len;\n\t\tguchar *cal_dec64;\n\t\tgsize i;\n\t\tint j = 0;\n\n\t\tcal_dec64 = g_base64_decode(buddy->cal_free_busy_base64, &cal_dec64_len);\n\n\t\tbuddy->cal_free_busy = g_malloc0(cal_dec64_len * 4 + 1);\n/*\n   http://msdn.microsoft.com/en-us/library/dd941537%28office.13%29.aspx\n\t\t00, Free (Fr)\n\t\t01, Tentative (Te)\n\t\t10, Busy (Bu)\n\t\t11, Out of facility (Oo)\n\n   http://msdn.microsoft.com/en-us/library/aa566048.aspx\n\t\t0  Free\n\t\t1  Tentative\n\t\t2  Busy\n\t\t3  Out of Office (OOF)\n\t\t4  No data\n*/\n\t\tfor (i = 0; i < cal_dec64_len; i++) {\n#define TWO_BIT_MASK\t0x03\n\t\t\tchar tmp = cal_dec64[i];\n\t\t\tbuddy->cal_free_busy[j++] = (tmp & TWO_BIT_MASK) + '0';\n\t\t\tbuddy->cal_free_busy[j++] = ((tmp >> 2) & TWO_BIT_MASK) + '0';\n\t\t\tbuddy->cal_free_busy[j++] = ((tmp >> 4) & TWO_BIT_MASK) + '0';\n\t\t\tbuddy->cal_free_busy[j++] = ((tmp >> 6) & TWO_BIT_MASK) + '0';\n\t\t}\n\t\tbuddy->cal_free_busy[j++] = '\\0';\n\t\tg_free(cal_dec64);\n\t}\n\n\treturn buddy->cal_free_busy;\n}\n\nchar *\nsipe_cal_get_freebusy_base64(const char* freebusy_hex)\n{\n\tguint i = 0;\n\tguint j = 0;\n\tguint shift_factor = 0;\n\tguint len, res_len;\n\tguchar *res;\n\tgchar *res_base64;\n\n\tif (!freebusy_hex) return NULL;\n\n\tlen = strlen(freebusy_hex);\n\tres_len = len / 4 + 1;\n\tres = g_malloc0(res_len);\n\twhile (i < len) {\n\t\tres[j] |= (freebusy_hex[i++] - '0') << shift_factor;\n\t\tshift_factor += 2;\n\t\tif (shift_factor == 8) {\n\t\t\tshift_factor = 0;\n\t\t\tj++;\n\t\t}\n\t}\n\n\tres_base64 = g_base64_encode(res, shift_factor ? res_len : res_len - 1);\n\tg_free(res);\n\treturn res_base64;\n}\n\nchar *\nsipe_cal_get_description(struct sipe_buddy *buddy)\n{\n\ttime_t cal_start;\n\ttime_t cal_end;\n\tint current_cal_state;\n\ttime_t now = time(NULL);\n\ttime_t start = TIME_NULL;\n\ttime_t end = TIME_NULL;\n\ttime_t next_start = TIME_NULL;\n\ttime_t switch_time;\n\tint to_state = SIPE_CAL_NO_DATA;\n\ttime_t until = TIME_NULL;\n\tint index = 0;\n\tgboolean has_working_hours = (buddy->cal_working_hours != NULL);\n\tconst char *free_busy;\n\tconst char *cal_states[] = {_(\"Free\"),\n\t\t\t\t    _(\"Tentative\"),\n\t\t\t\t    _(\"Busy\"),\n\t\t\t\t    _(\"Out of office\"),\n\t\t\t\t    _(\"No data\")};\n\n\tif (buddy->cal_granularity != 15) {\n\t\tSIPE_DEBUG_INFO(\"sipe_cal_get_description: granularity %d is unsupported, exiting.\", buddy->cal_granularity);\n\t\treturn NULL;\n\t}\n\n\t/* to lazy load if needed */\n\tfree_busy = sipe_cal_get_free_busy(buddy);\n\tSIPE_DEBUG_INFO(\"sipe_cal_get_description: buddy->cal_free_busy=\\n%s\", free_busy ? free_busy : \"\");\n\n\tif (!buddy->cal_free_busy || !buddy->cal_granularity || !buddy->cal_start_time) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_cal_get_description: no calendar data, exiting\");\n\t\treturn NULL;\n\t}\n\n\tcal_start = sipe_utils_str_to_time(buddy->cal_start_time);\n\tcal_end = cal_start + 60 * (buddy->cal_granularity) * strlen(buddy->cal_free_busy);\n\n\tcurrent_cal_state = sipe_cal_get_status0(free_busy, cal_start, buddy->cal_granularity, time(NULL), &index);\n\tif (current_cal_state == SIPE_CAL_NO_DATA) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_cal_get_description: calendar is undefined for present moment, exiting.\");\n\t\treturn NULL;\n\t}\n\n\tswitch_time = sipe_cal_get_switch_time(free_busy, cal_start, buddy->cal_granularity, index, current_cal_state, &to_state);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"\\n* Calendar *\");\n\tif (buddy->cal_working_hours) {\n\t\tsipe_cal_get_today_work_hours(buddy->cal_working_hours, &start, &end, &next_start);\n\n\t\tSIPE_DEBUG_INFO(\"Remote now timezone : %s\", sipe_cal_get_tz(buddy->cal_working_hours, now));\n\t\tSIPE_DEBUG_INFO(\"std.switch_time(GMT): %s\",\n\t\t\t\tIS((*buddy->cal_working_hours).std.switch_time) ? sipe_utils_time_to_debug_str(gmtime(&((*buddy->cal_working_hours).std.switch_time))) : \"\");\n\t\tSIPE_DEBUG_INFO(\"dst.switch_time(GMT): %s\",\n\t\t\t\tIS((*buddy->cal_working_hours).dst.switch_time) ? sipe_utils_time_to_debug_str(gmtime(&((*buddy->cal_working_hours).dst.switch_time))) : \"\");\n\t\tSIPE_DEBUG_INFO(\"Remote now time     : %s\",\n\t\t\tsipe_utils_time_to_debug_str(sipe_localtime_tz(&now, sipe_cal_get_tz(buddy->cal_working_hours, now))));\n\t\tSIPE_DEBUG_INFO(\"Remote start time   : %s\",\n\t\t\tIS(start) ? sipe_utils_time_to_debug_str(sipe_localtime_tz(&start, sipe_cal_get_tz(buddy->cal_working_hours, start))) : \"\");\n\t\tSIPE_DEBUG_INFO(\"Remote end time     : %s\",\n\t\t\tIS(end) ? sipe_utils_time_to_debug_str(sipe_localtime_tz(&end, sipe_cal_get_tz(buddy->cal_working_hours, end))) : \"\");\n\t\tSIPE_DEBUG_INFO(\"Rem. next_start time: %s\",\n\t\t\tIS(next_start) ? sipe_utils_time_to_debug_str(sipe_localtime_tz(&next_start, sipe_cal_get_tz(buddy->cal_working_hours, next_start))) : \"\");\n\t\tSIPE_DEBUG_INFO(\"Remote switch time  : %s\",\n\t\t\tIS(switch_time) ? sipe_utils_time_to_debug_str(sipe_localtime_tz(&switch_time, sipe_cal_get_tz(buddy->cal_working_hours, switch_time))) : \"\");\n\t} else {\n\t\tSIPE_DEBUG_INFO(\"Local now time      : %s\",\n\t\t\tsipe_utils_time_to_debug_str(localtime(&now)));\n\t\tSIPE_DEBUG_INFO(\"Local switch time   : %s\",\n\t\t\tIS(switch_time) ? sipe_utils_time_to_debug_str(localtime(&switch_time)) : \"\");\n\t}\n\tSIPE_DEBUG_INFO(\"Calendar End (GMT)  : %s\", sipe_utils_time_to_debug_str(gmtime(&cal_end)));\n\tSIPE_DEBUG_INFO(\"current cal state   : %s\", cal_states[current_cal_state]);\n\tSIPE_DEBUG_INFO(\"switch  cal state   : %s\", cal_states[to_state]         );\n\n\t/* Calendar: string calculations */\n\n\t/*\n\tALGORITHM (don't delete)\n\t(c)2009,2010 pier11 <pier11@operamail.com>\n\n\tSOD =  Start of Work Day\n\tEOD =  End of Work Day\n\tNSOD = Start of tomorrow's Work Day\n\tSW =   Calendar status switch time\n\n\tif current_cal_state == Free\n\t\tuntil = min_t of SOD, EOD, NSOD, SW (min_t(x) = min(x-now) where x>now only)\n\telse\n\t\tuntil = SW\n\n\tif (!until && (cal_period_end > now + 8H))\n\t\tuntil = cal_period_end\n\n\tif (!until)\n\t\treturn \"Currently %\", current_cal_state\n\n\tif (until - now > 8H)\n\t\tif (current_cal_state == Free && (work_hours && !in work_hours(now)))\n\t\t\treturn \"Outside of working hours for next 8 hours\"\n\t\telse\n\t\t\treturn \"%s for next 8 hours\", current_cal_state\n\n\tif (current_cal_state == Free)\n\t\tif (work_hours && until !in work_hours(now))\n\t\t\t\"Not working\"\n\t\telse\n\t\t\t\"%s\", current_cal_state\n\t\t\" until %.2d:%.2d\", until\n\telse\n\t\t\"Currently %\", current_cal_state\n\t\tif (work_hours && until !in work_hours(until))\n\t\t\t\". Outside of working hours at at %.2d:%.2d\", until\n\t\telse\n\t\t\t\". %s at %.2d:%.2d\", to_state, until\n\t*/\n\n\tif (current_cal_state < 1) { /* Free */\n\t\tuntil = sipe_cal_get_until(now, switch_time, start, end, next_start);\n\t} else {\n\t\tuntil = switch_time;\n\t}\n\n\tif (!IS(until) && (cal_end - now > 8*60*60))\n\t\tuntil = cal_end;\n\n\tif (!IS(until)) {\n\t\treturn g_strdup_printf(_(\"Currently %s\"), cal_states[current_cal_state]);\n\t}\n\n\tif (until - now > 8*60*60) {\n\t\t/* Free & outside work hours */\n\t\tif (current_cal_state < 1 && has_working_hours && !sipe_cal_is_in_work_hours(now, start, end)) {\n\t\t\treturn g_strdup(_(\"Outside of working hours for next 8 hours\"));\n\t\t} else {\n\t\t\treturn g_strdup_printf(_(\"%s for next 8 hours\"), cal_states[current_cal_state]);\n\t\t}\n\t}\n\n\tif (current_cal_state < 1) { /* Free */\n\t\tconst char *tmp;\n\t\tstruct tm *until_tm = localtime(&until);\n\n\t\tif (has_working_hours && !sipe_cal_is_in_work_hours(now, start, end)) {\n\t\t\ttmp = _(\"Not working\");\n\t\t} else {\n\t\t\ttmp = cal_states[current_cal_state];\n\t\t}\n\t\treturn g_strdup_printf(_(\"%s until %.2d:%.2d\"), tmp, until_tm->tm_hour, until_tm->tm_min);\n\t} else { /* Tentative or Busy or OOF */\n\t\tchar *tmp;\n\t\tchar *res;\n\t\tstruct tm *until_tm = localtime(&until);\n\n\t\ttmp = g_strdup_printf(_(\"Currently %s\"), cal_states[current_cal_state]);\n\t\tif (has_working_hours && !sipe_cal_is_in_work_hours(until, start, end)) {\n\t\t\tres = g_strdup_printf(_(\"%s. Outside of working hours at %.2d:%.2d\"),\n\t\t\t\t\t      tmp, until_tm->tm_hour, until_tm->tm_min);\n\t\t\tg_free(tmp);\n\t\t\treturn res;\n\t\t} else {\n\t\t\tres = g_strdup_printf(_(\"%s. %s at %.2d:%.2d\"), tmp, cal_states[to_state], until_tm->tm_hour, until_tm->tm_min);\n\t\t\tg_free(tmp);\n\t\t\treturn res;\n\t\t}\n\t}\n\t/* End of - Calendar: string calculations */\n}\n\n#define UPDATE_CALENDAR_INTERVAL (15*60) /* 15 min, default granularity for Exchange */\n#define UPDATE_CALENDAR_OFFSET       30  /* 30 seconds before next interval starts */\n\nstatic void sipe_cal_update_cb(struct sipe_core_private *sipe_private,\n\t\t\t       SIPE_UNUSED_PARAMETER gpointer data)\n{\n\tsipe_core_update_calendar(SIPE_CORE_PUBLIC);\n}\n\nvoid sipe_core_update_calendar(struct sipe_core_public *sipe_public)\n{\n\ttime_t now, offset;\n\n\tSIPE_LOG_INFO_NOFORMAT(\"sipe_core_update_calendar: started.\");\n\n\t/* Do in parallel.\n\t * If failed, the branch will be disabled for subsequent calls.\n\t * Can't rely that user turned the functionality on in account settings.\n\t */\n\tsipe_ews_update_calendar(SIPE_CORE_PRIVATE);\n#ifdef _WIN32\n\t/* @TODO: UNIX integration missing */\n\tsipe_domino_update_calendar(SIPE_CORE_PRIVATE);\n#endif\n\n\t/* how long, in seconds, until the next calendar interval starts? */\n\tnow    = time(NULL);\n\toffset = (now / UPDATE_CALENDAR_INTERVAL + 1) * UPDATE_CALENDAR_INTERVAL - now;\n\n\t/* ensure that the update after the initial one is not too soon */\n\tif (offset <= (UPDATE_CALENDAR_INTERVAL / 2))\n\t\toffset += UPDATE_CALENDAR_INTERVAL;\n\n\t/* schedule next update before a new calendar interval starts */\n\tsipe_schedule_seconds(SIPE_CORE_PRIVATE,\n\t\t\t      \"<+update-calendar>\",\n\t\t\t      NULL,\n\t\t\t      offset - UPDATE_CALENDAR_OFFSET,\n\t\t\t      sipe_cal_update_cb,\n\t\t\t      NULL);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_core_update_calendar: finished.\");\n}\n\nvoid sipe_cal_presence_publish(struct sipe_core_private *sipe_private,\n\t\t\t       gboolean do_publish_calendar)\n{\n\tif (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {\n\t\tif (do_publish_calendar)\n\t\t\tsipe_ocs2007_presence_publish(sipe_private, NULL);\n\t\telse\n\t\t\tsipe_ocs2007_category_publish(sipe_private, FALSE);\n\t} else {\n\t\tsipe_ocs2005_presence_publish(sipe_private,\n\t\t\t\t\t      do_publish_calendar);\n\t}\n}\n\nvoid sipe_cal_delayed_calendar_update(struct sipe_core_private *sipe_private)\n{\n#define UPDATE_CALENDAR_DELAY\t\t1*60\t/* 1 min */\n\n\t/* only start periodic calendar updating if user hasn't disabled it */\n\tif (!SIPE_CORE_PUBLIC_FLAG_IS(DONT_PUBLISH))\n\t\tsipe_schedule_seconds(sipe_private,\n\t\t\t\t      \"<+update-calendar>\",\n\t\t\t\t      NULL,\n\t\t\t\t      UPDATE_CALENDAR_DELAY,\n\t\t\t\t      sipe_cal_update_cb,\n\t\t\t\t      NULL);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-cal.h",
    "content": "/**\n * @file sipe-cal.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2015 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2009 pier11 <pier11@operamail.com>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipe_buddy;\nstruct sipe_core_private;\nstruct sipe_http_request;\nstruct sipe_http_session;\nstruct _sipe_xml;\n\n/* Calendar statuses */\n#define SIPE_CAL_FREE       0\n#define SIPE_CAL_TENTATIVE  1\n#define SIPE_CAL_BUSY       2\n#define SIPE_CAL_OOF        3\n#define SIPE_CAL_NO_DATA    4\n\n/* Default granularity of FreeBusy data is 15 minutes */\n#define SIPE_FREE_BUSY_GRANULARITY_SEC\t(15*60)\n/* FreeBusy stream duration in seconds. Defaults to 4 days */\n#define SIPE_FREE_BUSY_PERIOD_SEC\t(4*(24*60*60))\n\nstruct sipe_cal_event {\n\ttime_t start_time;\n\ttime_t end_time;\n\t/* SIPE_CAL_* */\n\tint cal_status;\n\tchar *subject;\n\tchar *location;\n\tint is_meeting;\n};\n\n/** For extracting our Calendar information from\n  * external sources like Exchange, Lotus Domino.\n  */\nstruct sipe_calendar {\n\tstruct sipe_core_private *sipe_private;\n\n\tint state;\n\tchar *email;\n\tchar *legacy_dn;\n\tint is_ews_disabled;\n\tint is_domino_disabled;\n\tint is_updated;\n\tgboolean retry;\n\n\tchar *as_url;\n\tchar *oof_url;\n\tchar *oab_url;\n\tchar *domino_url;\n\n\tchar *oof_state; /* Enabled, Disabled, Scheduled */\n\tchar *oof_note;\n\ttime_t oof_start;\n\ttime_t oof_end;\n\ttime_t updated;\n\tgboolean published;\n\n\tstruct sipe_http_session *session;\n\tstruct sipe_http_request *request;\n\n\ttime_t fb_start;\n\t/* hex form */\n\tchar *free_busy;\n\tchar *working_hours_xml_str;\n\tGSList *cal_events;\n};\n\nvoid\nsipe_cal_event_free(struct sipe_cal_event* cal_event);\n\nvoid\nsipe_cal_events_free(GSList *cal_events);\n\nvoid\nsipe_cal_calendar_free(struct sipe_calendar *cal);\n\nvoid\nsipe_cal_calendar_init(struct sipe_core_private *sipe_private);\n\n/**\n * Returns hash of Calendar Event for comparison.\n *\n * Must be g_free()'d after use.\n */\nchar *\nsipe_cal_event_hash(struct sipe_cal_event* event);\n\n/**\n * Dump calendar event in human readable form to debug log.\n */\nvoid\nsipe_cal_event_debug(const struct sipe_cal_event *cal_event,\n\t\t     const gchar *label);\n\n/**\n * Converts struct tm to Epoch time_t considering timezone.\n *\n * @param tz as defined for TZ environment variable.\n *\n * Reference: see timegm(3) - Linux man page\n */\ntime_t\nsipe_mktime_tz(struct tm *tm,\n\t       const char* tz);\n\n/**\n * Converts hex representation of freebusy string as\n * returned by Exchange Web Services to\n * condenced and base64 encoded form\n *\n * Must be g_free()'d after use.\n */\nchar *\nsipe_cal_get_freebusy_base64(const char* freebusy_hex);\n\n/** Contains buddy's working hours information */\nstruct sipe_cal_working_hours;\n\n/**\n * Parses Working Hours from passed XML piece\n * and creates/fills struct sipe_cal_working_hours in struct sipe_buddy\n */\nvoid\nsipe_cal_parse_working_hours(const struct _sipe_xml *xn_working_hours,\n\t\t\t     struct sipe_buddy *buddy);\n\n/**\n * Frees struct sipe_cal_working_hours\n */\nvoid\nsipe_cal_free_working_hours(struct sipe_cal_working_hours *wh);\n\n/**\n * Returns user calendar information in text form.\n * Example: \"Currently Busy. Free at 13:00\"\n */\nchar *\nsipe_cal_get_description(struct sipe_buddy *buddy);\n\n/**\n * Returns calendar status SIPE_CAL_* at time specified.\n * Returns SIPE_CAL_NO_DATA if no calendar data availible.\n *\n * @param since (out)\tReturns beginning time of the status.\n */\nint\nsipe_cal_get_status(struct sipe_buddy *buddy,\n\t\t    time_t time_in_question,\n\t\t    time_t *since);\n\n/**\n * Returns calendar event at time in question.\n * If conflict, takes last event in the following\n * priority order: OOF, Busy, Tentative.\n */\nstruct sipe_cal_event*\nsipe_cal_get_event(GSList *cal_events,\n\t\t   time_t time_in_question);\n\n/**\n * Publish presence information\n */\nvoid sipe_cal_presence_publish(struct sipe_core_private *sipe_private,\n\t\t\t       gboolean do_publish_calendar);\n\n/**\n * Schedule calendar update\n */\nvoid sipe_cal_delayed_calendar_update(struct sipe_core_private *sipe_private);\n"
  },
  {
    "path": "src/core/sipe-cert-crypto-nss.c",
    "content": "/**\n * @file sipe-cert-crypto-nss.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2012 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/**\n * Certificate routines implementation based on NSS.\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n\n#ifdef HAVE_VALGRIND\n#include <valgrind.h>\n#endif\n\n/*\n * Work around a compiler error in NSS 3.13.x. Let's hope they fix it for\n * 3.14.x. See also: https://bugzilla.mozilla.org/show_bug.cgi?id=702090\n */\n#include \"nss.h\"\n#if (NSS_VMAJOR == 3) && (NSS_VMINOR == 13)\n#define __GNUC_MINOR __GNUC_MINOR__\n#endif\n\n#include \"cert.h\"\n#include \"cryptohi.h\"\n#include \"keyhi.h\"\n#include \"pk11pub.h\"\n\n#include \"sipe-backend.h\"\n#include \"sipe-cert-crypto.h\"\n\nstruct sipe_cert_crypto {\n\tSECKEYPrivateKey *private;\n\tSECKEYPublicKey  *public;\n};\n\n/*\n * This data structure is used in two different modes\n *\n *  a) certificate generated by the server from our Certificate Request\n *\n *     key_pair.private - reference to client private key, don't free!\n *     key_pair.public  - reference to client public key,  don't free!\n *     decoded          - certificate as NSS data structure, must be freed\n *     raw              - certificate as DER encoded binary, must be freed\n *     length           - length of DER binary\n *\n *  b) server certificate\n *\n *     key_pair.private - NULL\n *     key_pair.public  - reference to server public key, must be freed!\n *     decoded          - certificate as NSS data structure, must be freed\n *     raw              - NULL\n *     length           - modulus length of server public key\n */\nstruct certificate_nss {\n\tstruct sipe_cert_crypto key_pair;\n\tCERTCertificate *decoded;\n\tguchar *raw;\n\tgsize length;\n};\n\nstruct sipe_cert_crypto *sipe_cert_crypto_init(void)\n{\n\tPK11SlotInfo *slot = PK11_GetInternalKeySlot();\n\n\tif (slot) {\n\t\tPK11RSAGenParams rsaParams;\n\t\tstruct sipe_cert_crypto *scc = g_new0(struct sipe_cert_crypto, 1);\n\n\t\t/* RSA parameters - should those be configurable? */\n#ifdef HAVE_VALGRIND\n\t\t/*\n\t\t * valgrind makes key pair generation extremely slow. At least\n\t\t * on my system it takes longer for the default key size than\n\t\t * the SIP server timeout and our next message will fail with\n\t\t *\n\t\t *     Read error: Connection reset by peer (104)\n\t\t *\n\t\t * Let's reduce the key size when we detect valgrind.\n\t\t */\n\t\tif (RUNNING_ON_VALGRIND) {\n\t\t\trsaParams.keySizeInBits = 1024;\n\t\t\tSIPE_DEBUG_INFO(\"sipe_cert_crypto_init: running on valgrind, reducing RSA key size to %d bits\",\n\t\t\t\t\trsaParams.keySizeInBits);\n\t\t} else\n#endif\n\t\t\trsaParams.keySizeInBits = 2048;\n\t\trsaParams.pe                    = 65537;\n\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_cert_crypto_init: generate key pair, this might take a while...\");\n\t\tscc->private = PK11_GenerateKeyPair(slot,\n\t\t\t\t\t\t    CKM_RSA_PKCS_KEY_PAIR_GEN,\n\t\t\t\t\t\t    &rsaParams,\n\t\t\t\t\t\t    &scc->public,\n\t\t\t\t\t\t    PR_FALSE, /* not permanent */\n\t\t\t\t\t\t    PR_TRUE,  /* sensitive */\n\t\t\t\t\t\t    NULL);\n\t\tif (scc->private) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_cert_crypto_init: key pair generated\");\n\t\t\tPK11_FreeSlot(slot);\n\t\t\treturn(scc);\n\t\t}\n\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_cert_crypto_init: key generation failed\");\n\t\tg_free(scc);\n\t\tPK11_FreeSlot(slot);\n\t}\n\n\treturn(NULL);\n}\n\nvoid sipe_cert_crypto_free(struct sipe_cert_crypto *scc)\n{\n\tif (scc) {\n\t\tif (scc->public)\n\t\t\tSECKEY_DestroyPublicKey(scc->public);\n\t\tif (scc->private)\n\t\t\tSECKEY_DestroyPrivateKey(scc->private);\n\t\tg_free(scc);\n\t}\n}\n\nstatic gchar *sign_cert_or_certreq(CERTCertificate *cert,\n\t\t\t\t   CERTCertificateRequest *certreq,\n\t\t\t\t   SECKEYPrivateKey *private)\n{\n\tPRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);\n\tgchar *base64 = NULL;\n\n\tif (arena) {\n\t\tSECItem *encoding = SEC_ASN1EncodeItem(arena,\n\t\t\t\t\t\t       NULL,\n\t\t\t\t\t\t       cert ?\n\t\t\t\t\t\t       (void *) cert :\n\t\t\t\t\t\t       (void *) certreq,\n\t\t\t\t\t\t       cert ?\n\t\t\t\t\t\t       SEC_ASN1_GET(CERT_CertificateTemplate) :\n\t\t\t\t\t\t       SEC_ASN1_GET(CERT_CertificateRequestTemplate));\n\n\t\tif (encoding) {\n\t\t\tSECOidTag signtag = SEC_GetSignatureAlgorithmOidTag(private->keyType,\n\t\t\t\t\t\t\t\t\t    SEC_OID_UNKNOWN);\n\n\t\t\tif (signtag != SEC_OID_UNKNOWN) {\n\t\t\t\tSECItem raw;\n\n\t\t\t\tif (!SEC_DerSignData(arena,\n\t\t\t\t\t\t     &raw,\n\t\t\t\t\t\t     encoding->data,\n\t\t\t\t\t\t     encoding->len,\n\t\t\t\t\t\t     private,\n\t\t\t\t\t\t     signtag)) {\n\n\t\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sign_cert_or_certreq: successfully signed\");\n\t\t\t\t\tbase64 = g_base64_encode(raw.data, raw.len);\n\n\t\t\t\t} else {\n\t\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sign_cert_or_certreq: signing failed\");\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sign_cert_or_certreq: can't find signature algorithm\");\n\t\t\t}\n\n\t\t\t/* all memory allocated from \"arena\"\n\t\t\t   SECITEM_FreeItem(encoding, PR_TRUE); */\n\t\t} else {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sign_cert_or_certreq: can't ASN.1 encode data\");\n\t\t}\n\n\t\tPORT_FreeArena(arena, PR_TRUE);\n\t} else {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sign_cert_or_certreq: can't allocate memory\");\n\t}\n\n\treturn(base64);\n}\n\nstatic CERTCertificateRequest *generate_request(struct sipe_cert_crypto *scc,\n\t\t\t\t\t\tconst gchar *subject)\n{\n\tSECItem *pkd;\n\tCERTCertificateRequest *certreq = NULL;\n\n\tif (!scc || !subject)\n\t\treturn(NULL);\n\n\tpkd = SECKEY_EncodeDERSubjectPublicKeyInfo(scc->public);\n\tif (pkd) {\n\t\tCERTSubjectPublicKeyInfo *spki = SECKEY_DecodeDERSubjectPublicKeyInfo(pkd);\n\n\t\tif (spki) {\n\t\t\tgchar *cn      = g_strdup_printf(\"CN=%s\", subject);\n\t\t\tCERTName *name = CERT_AsciiToName(cn);\n\t\t\tg_free(cn);\n\n\t\t\tif (name) {\n\t\t\t\tcertreq = CERT_CreateCertificateRequest(name,\n\t\t\t\t\t\t\t\t\tspki,\n\t\t\t\t\t\t\t\t\tNULL);\n\t\t\t\tif (!certreq) {\n\t\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"generate_request: certreq creation failed\");\n\t\t\t\t}\n\n\t\t\t\tCERT_DestroyName(name);\n\t\t\t} else {\n\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"generate_request: subject name creation failed\");\n\t\t\t}\n\n\t\t\tSECKEY_DestroySubjectPublicKeyInfo(spki);\n\t\t} else {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"generate_request: DER decode public key info failed\");\n\t\t}\n\n\t\tSECITEM_FreeItem(pkd, PR_TRUE);\n\t} else {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"generate_request: DER encode failed\");\n\t}\n\n\treturn(certreq);\n}\n\ngchar *sipe_cert_crypto_request(struct sipe_cert_crypto *scc,\n\t\t\t\tconst gchar *subject)\n{\n\tgchar *base64                   = NULL;\n\tCERTCertificateRequest *certreq = generate_request(scc, subject);\n\n\tif (certreq) {\n\t\tbase64 = sign_cert_or_certreq(NULL, certreq, scc->private);\n\t\tCERT_DestroyCertificateRequest(certreq);\n\t}\n\n\treturn(base64);\n}\n\nvoid sipe_cert_crypto_destroy(gpointer certificate)\n{\n\tstruct certificate_nss *cn = certificate;\n\n\tif (cn) {\n\t\t/* imported server certificate - mode (b) */\n\t\tif (!cn->raw && cn->key_pair.public)\n\t\t\tSECKEY_DestroyPublicKey(cn->key_pair.public);\n\t\tif (cn->decoded)\n\t\t\tCERT_DestroyCertificate(cn->decoded);\n\t\tg_free(cn->raw);\n\t\tg_free(cn);\n\t}\n}\n\n/* generates certificate_nss in mode (a) */\ngpointer sipe_cert_crypto_decode(struct sipe_cert_crypto *scc,\n\t\t\t\t const gchar *base64)\n{\n\tstruct certificate_nss *cn = g_new0(struct certificate_nss, 1);\n\n\tcn->raw     = g_base64_decode(base64, &cn->length);\n\tcn->decoded = CERT_DecodeCertFromPackage((char *) cn->raw, cn->length);\n\n\tif (!cn->decoded) {\n\t\tsipe_cert_crypto_destroy(cn);\n\t\treturn(NULL);\n\t}\n\n\tcn->key_pair = *scc;\n\n\treturn(cn);\n}\n\n/* generates certificate_nss in mode (b) */\ngpointer sipe_cert_crypto_import(const guchar *raw,\n\t\t\t\t gsize length)\n{\n\tstruct certificate_nss *cn = g_new0(struct certificate_nss, 1);\n\n\t/* cn->raw not needed as this is a server certificate */\n\tcn->decoded = CERT_DecodeCertFromPackage((char *) raw, length);\n\n\tif (!cn->decoded) {\n\t\tsipe_cert_crypto_destroy(cn);\n\t\treturn(NULL);\n\t}\n\n\tcn->key_pair.public = CERT_ExtractPublicKey(cn->decoded);\n\n\tif (!cn->key_pair.public) {\n\t\tsipe_cert_crypto_destroy(cn);\n\t\treturn(NULL);\n\t}\n\n\tcn->length = SECKEY_PublicKeyStrength(cn->key_pair.public);\n\n\treturn(cn);\n}\n\ngboolean sipe_cert_crypto_valid(gpointer certificate,\n\t\t\t\tguint offset)\n{\n\tstruct certificate_nss *cn = certificate;\n\tSECCertTimeValidity validity;\n\n\tif (!cn)\n\t\treturn(FALSE);\n\n\tvalidity = CERT_CheckCertValidTimes(cn->decoded,\n\t\t\t\t\t    /* PRTime unit is microseconds */\n\t\t\t\t\t    PR_Now() + offset * PR_USEC_PER_SEC,\n\t\t\t\t\t    PR_FALSE);\n\n\treturn((validity == secCertTimeValid) ||\n\t       /*\n\t\t* From certt.h: \"validity could not be decoded from the\n\t\t*                cert, most likely because it was NULL\"\n\t\t*\n\t\t* Let's assume if the server sends us such a certificate\n\t\t* that it must be valid then...\n\t\t*/\n\t       (validity == secCertTimeUndetermined));\n}\n\nguint sipe_cert_crypto_expires(gpointer certificate)\n{\n\tstruct certificate_nss *cn = certificate;\n\tPRTime now, notAfter;\n\n\tif (!cn ||\n\t    (CERT_GetCertTimes(cn->decoded,\n\t\t\t       &now, /* can't be NULL */\n\t\t\t       &notAfter) != SECSuccess))\n\t\treturn(0);\n\n\t/* Sanity check */\n\tnow = PR_Now();\n\tif (notAfter < now)\n\t\treturn(0);\n\n\t/* PRTime unit is microseconds */\n\treturn((notAfter - now) / PR_USEC_PER_SEC);\n}\n\ngsize sipe_cert_crypto_raw_length(gpointer certificate)\n{\n\treturn(((struct certificate_nss *) certificate)->length);\n}\n\nconst guchar *sipe_cert_crypto_raw(gpointer certificate)\n{\n\treturn(((struct certificate_nss *) certificate)->raw);\n}\n\ngpointer sipe_cert_crypto_public_key(gpointer certificate)\n{\n\treturn(((struct certificate_nss *) certificate)->key_pair.public);\n}\n\ngsize sipe_cert_crypto_modulus_length(gpointer certificate)\n{\n\treturn(((struct certificate_nss *) certificate)->length);\n}\n\ngpointer sipe_cert_crypto_private_key(gpointer certificate)\n{\n\treturn(((struct certificate_nss *) certificate)->key_pair.private);\n}\n\n/* Create test certificate for internal key pair (ONLY USE FOR TEST CODE!!!) */\ngpointer sipe_cert_crypto_test_certificate(struct sipe_cert_crypto *scc)\n{\n\tCERTCertificateRequest *certreq = generate_request(scc, \"test@test.com\");\n\tstruct certificate_nss *cn = NULL;\n\n\tif (certreq) {\n\t\t/* self-signed */\n\t\tCERTName *issuer = CERT_AsciiToName(\"CN=test@test.com\");\n\n\t\tif (issuer) {\n\t\t\t/* we really don't need this certificate for long... */\n\t\t\tCERTValidity *validity = CERT_CreateValidity(PR_Now(),\n\t\t\t\t\t\t\t\t     PR_Now() + 600 * PR_USEC_PER_SEC);\n\n\t\t\tif (validity) {\n\t\t\t\tCERTCertificate *certificate = CERT_CreateCertificate(1,\n\t\t\t\t\t\t\t\t\t\t      issuer,\n\t\t\t\t\t\t\t\t\t\t      validity,\n\t\t\t\t\t\t\t\t\t\t      certreq);\n\n\t\t\t\tif (certificate) {\n\t\t\t\t\tSECOidTag signtag = SEC_GetSignatureAlgorithmOidTag(scc->private->keyType,\n\t\t\t\t\t\t\t\t\t\t\t    SEC_OID_UNKNOWN);\n\n\t\t\t\t\tif ((signtag != SEC_OID_UNKNOWN) &&\n\t\t\t\t\t    (SECOID_SetAlgorithmID(certificate->arena,\n\t\t\t\t\t\t\t\t   &certificate->signature,\n\t\t\t\t\t\t\t\t   signtag, 0) == SECSuccess)) {\n\t\t\t\t\t\tgchar *base64 = sign_cert_or_certreq(certificate,\n\t\t\t\t\t\t\t\t\t\t     NULL,\n\t\t\t\t\t\t\t\t\t\t     scc->private);\n\n\t\t\t\t\t\tif (base64) {\n\t\t\t\t\t\t\tcn = sipe_cert_crypto_decode(scc,\n\t\t\t\t\t\t\t\t\t\t     base64);\n\t\t\t\t\t\t\tif (!cn) {\n\t\t\t\t\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_cert_crypto_test_certificate: certificate decode failed\");\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tg_free(base64);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_cert_crypto_test_certificate: certificate signing failed\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_cert_crypto_test_certificate: setting certificate signature algorithm ID failed\");\n\t\t\t\t\t}\n\n\t\t\t\t\tCERT_DestroyCertificate(certificate);\n\t\t\t\t} else {\n\t\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_cert_crypto_test_certificate: certificate creation failed\");\n\t\t\t\t}\n\n\t\t\t\tCERT_DestroyValidity(validity);\n\t\t\t} else {\n\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_cert_crypto_test_certificate: validity creation failed\");\n\t\t\t}\n\n\t\t\tCERT_DestroyName(issuer);\n\t\t} else {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_cert_crypto_test_certificate: issuer name creation failed\");\n\t\t}\n\n\t\tCERT_DestroyCertificateRequest(certreq);\n\t}\n\n\treturn(cn);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-cert-crypto-openssl.c",
    "content": "/**\n * @file sipe-cert-crypto-openssl.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013-2017 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/**\n * Certificate routines implementation based on OpenSSL.\n */\n\n#include <openssl/bn.h>\n#include <openssl/evp.h>\n#include <openssl/rsa.h>\n#include <openssl/x509.h>\n\n#include <time.h>\n\n#include <glib.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-cert-crypto.h\"\n\nstruct sipe_cert_crypto {\n\tRSA *key;\n};\n\n/*\n * This data structure is used in two different modes\n *\n *  a) certificate generated by the server from our Certificate Request\n *\n *     key              - reference to client RSA key, don't free!\n *     decoded          - certificate as OpenSSL data structure, must be freed\n *     raw              - certificate as DER encoded binary, must be freed\n *     length           - length of DER binary\n *\n *  b) server certificate\n *\n *     key              - reference to server public key, must be freed\n *     decoded          - certificate as OpenSSL data structure, must be freed\n *     raw              - NULL\n *     length           - modulus length of server public key\n */\nstruct certificate_openssl {\n\tRSA *key;\n\tEVP_PKEY *public;\n\tX509 *decoded;\n\tguchar *raw;\n\tgsize length;\n};\n\nstruct sipe_cert_crypto *sipe_cert_crypto_init(void)\n{\n\tstruct sipe_cert_crypto *scc = g_new0(struct sipe_cert_crypto, 1);\n\n\t/* allocate memory for RSA key */\n\tscc->key = RSA_new();\n\tif (scc->key) {\n\t\tBIGNUM *e = BN_new();\n\n\t\tif (e) {\n\t\t\t/* RSA parameters - should those be configurable? */\n\t\t\tif (BN_set_word(e, RSA_F4)) {\n\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_cert_crypto_init: generate key pair, this might take a while...\");\n\t\t\t\tif (RSA_generate_key_ex(scc->key, 2048, e, NULL)) {\n\t\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_cert_crypto_init: key pair generated\");\n\t\t\t\t\tBN_free(e);\n\t\t\t\t\treturn(scc);\n\n\t\t\t\t} else\n\t\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_cert_crypto_init: key generation failed\");\n\n\t\t\t} else\n\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_cert_crypto_init: big number initialization failed\");\n\n\t\t\tBN_free(e);\n\t\t} else\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_cert_crypto_init: memory allocation for big number failed\");\n\n\t} else\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_cert_crypto_init: memory allocation for RSA key failed\");\n\n\tsipe_cert_crypto_free(scc);\n\treturn(NULL);\n}\n\nvoid sipe_cert_crypto_free(struct sipe_cert_crypto *scc)\n{\n\tif (scc) {\n\t\tif (scc->key)\n\t\t\tRSA_free(scc->key);\n\t\tg_free(scc);\n\t}\n}\n\n\ngchar *sipe_cert_crypto_request(struct sipe_cert_crypto *scc,\n\t\t\t\tconst gchar *subject)\n{\n\tgchar *base64 = NULL;\n\tEVP_PKEY *pkey;\n\n\tif (!scc || !subject)\n\t\treturn(NULL);\n\n\tif ((pkey = EVP_PKEY_new()) != NULL) {\n\t\tX509_REQ *x509_req;\n\n\t\tif ((x509_req = X509_REQ_new()) != NULL) {\n\t\t\tX509_NAME *name;\n\n\t\t\tEVP_PKEY_set1_RSA(pkey, scc->key);\n\n\t\t\tX509_REQ_set_version(x509_req, 2);\n\t\t\tX509_REQ_set_pubkey(x509_req, pkey);\n\n\t\t\tname = X509_REQ_get_subject_name(x509_req);\n\t\t\tX509_NAME_add_entry_by_txt(name,\n\t\t\t\t\t\t   \"CN\",\n\t\t\t\t\t\t   MBSTRING_ASC,\n\t\t\t\t\t\t   (guchar *) subject,\n\t\t\t\t\t\t   -1, -1, 0);\n\n\t\t\tif (X509_REQ_sign(x509_req, pkey, EVP_sha1())) {\n\t\t\t\tgsize length;\n\t\t\t\tguchar *buf, *tmp;\n\n\t\t\t\t/*\n\t\t\t\t * Encode into DER format\n\t\t\t\t *\n\t\t\t\t * NOTE: i2d_X509(a, b) autoincrements b!\n\t\t\t\t */\n\t\t\t\tlength = i2d_X509_REQ(x509_req, NULL);\n\t\t\t\ttmp = buf = g_malloc(length);\n\t\t\t\ti2d_X509_REQ(x509_req, &tmp);\n\n\t\t\t\tbase64 = g_base64_encode(buf, length);\n\t\t\t\tg_free(buf);\n\n\t\t\t} else {\n\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_cert_crypto_request: can't sign certificate request\");\n\t\t\t}\n\n\t\t\tX509_REQ_free(x509_req);\n\t\t} else {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_cert_crypto_request: can't create x509 request data structure\");\n\t\t}\n\n\t\tEVP_PKEY_free(pkey);\n\t} else {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_cert_crypto_request: can't create private key data structure\");\n\t}\n\n\treturn(base64);\n}\n\nvoid sipe_cert_crypto_destroy(gpointer certificate)\n{\n\tstruct certificate_openssl *co = certificate;\n\n\tif (co) {\n\t\t/* imported server certificate - mode (b) */\n\t\tif (!co->raw && co->key)\n\t\t\tRSA_free(co->key);\n\t\tif (co->decoded)\n\t\t\tX509_free(co->decoded);\n\t\tg_free(co->raw);\n\t\tg_free(co);\n\t}\n}\n\n/* generates certificate_openssl in mode (a) */\ngpointer sipe_cert_crypto_decode(struct sipe_cert_crypto *scc,\n\t\t\t\t const gchar *base64)\n{\n\tstruct certificate_openssl *co = g_new0(struct certificate_openssl, 1);\n\tconst guchar *tmp;\n\n\t/* NOTE: d2i_X509(NULL, &in, len) autoincrements \"in\" */\n\ttmp = co->raw = g_base64_decode(base64, &co->length);\n\tco->decoded = d2i_X509(NULL, &tmp, co->length);\n\n\tif (!co->decoded) {\n\t\tsipe_cert_crypto_destroy(co);\n\t\treturn(NULL);\n\t}\n\n\tco->key = scc->key;\n\n\treturn(co);\n}\n\n/* generates certificate_openssl in mode (b) */\ngpointer sipe_cert_crypto_import(const guchar *raw,\n\t\t\t\t gsize length)\n{\n\tstruct certificate_openssl *co = g_new0(struct certificate_openssl, 1);\n\tEVP_PKEY *pkey;\n\n\t/* co->raw not needed as this is a server certificate */\n\t/* NOTE: d2i_X509(NULL, in, len) autoincrements \"in\" */\n\tco->decoded = d2i_X509(NULL, &raw, length);\n\n\tif (!co->decoded) {\n\t\tsipe_cert_crypto_destroy(co);\n\t\treturn(NULL);\n\t}\n\n\tpkey = X509_get_pubkey(co->decoded);\n\n\tif (!pkey) {\n\t\tsipe_cert_crypto_destroy(co);\n\t\treturn(NULL);\n\t}\n\n\tco->key    = EVP_PKEY_get1_RSA(pkey);\n\tco->length = EVP_PKEY_size(pkey);\n\tEVP_PKEY_free(pkey);\n\n\tif (!co->key) {\n\t\tsipe_cert_crypto_destroy(co);\n\t\treturn(NULL);\n\t}\n\n\treturn(co);\n}\n\ngboolean sipe_cert_crypto_valid(gpointer certificate,\n\t\t\t\tguint offset)\n{\n\tstruct certificate_openssl *co = certificate;\n\ttime_t compare = time(NULL) + offset;\n\n\treturn(co &&\n\t       (X509_cmp_time(X509_get_notAfter(co->decoded),\n\t\t\t      &compare) > 0));\n}\n\nguint sipe_cert_crypto_expires(gpointer certificate)\n{\n\tstruct certificate_openssl *co = certificate;\n\tguint min;\n\tguint max;\n\n\t/* make sure certificate hasn't expired already */\n\tif (!sipe_cert_crypto_valid(co, 0))\n\t\treturn(0);\n\n\t/*\n\t * I can't believe this, but it's true...\n\t *\n\t * OpenSSL doesn't have a public API to convert an ASN1_TIME\n\t * to seconds since epoch :-(\n\t *\n\t * @TODO: latest OpenSSL API has ASN1_TIME_diff()\n\t *\n\t * <30000 seconds (~8 hours) seems to be the most common expiration\n\t * value. Run a bisect to determine the real expiration value.\n\t */\n\tmin = 0;\n\tmax = 30000;\n\twhile (1) {\n\t\tguint offset = (max - min) / 2 + min;\n\n\t\tif (offset == min) {\n\t\t\tbreak;\n\t\t} else if (sipe_cert_crypto_valid(co, offset)) {\n\t\t\tmin = offset;\n\t\t} else {\n\t\t\tmax = offset;\n\t\t}\n\t}\n\n\treturn(min);\n}\n\ngsize sipe_cert_crypto_raw_length(gpointer certificate)\n{\n\treturn(((struct certificate_openssl *) certificate)->length);\n}\n\nconst guchar *sipe_cert_crypto_raw(gpointer certificate)\n{\n\treturn(((struct certificate_openssl *) certificate)->raw);\n}\n\ngpointer sipe_cert_crypto_public_key(gpointer certificate)\n{\n\treturn(((struct certificate_openssl *) certificate)->key);\n}\n\ngsize sipe_cert_crypto_modulus_length(gpointer certificate)\n{\n\treturn(((struct certificate_openssl *) certificate)->length);\n}\n\ngpointer sipe_cert_crypto_private_key(gpointer certificate)\n{\n\treturn(((struct certificate_openssl *) certificate)->key);\n}\n\n/* Create test certificate for internal key pair (ONLY USE FOR TEST CODE!!!) */\ngpointer sipe_cert_crypto_test_certificate(struct sipe_cert_crypto *scc)\n{\n\tstruct certificate_openssl *co = NULL;\n\tEVP_PKEY *pkey;\n\n\tif ((pkey = EVP_PKEY_new()) != NULL) {\n\t\tX509 *x509;\n\n\t\tif ((x509 = X509_new()) != NULL) {\n\t\t\tX509_NAME *name;\n\n\t\t\tEVP_PKEY_set1_RSA(pkey, scc->key);\n\n\t\t\tX509_set_version(x509, 2);\n\t\t\tASN1_INTEGER_set(X509_get_serialNumber(x509), 0);\n\t\t\tX509_gmtime_adj(X509_get_notBefore(x509), 0);\n\t\t\tX509_gmtime_adj(X509_get_notAfter(x509),  (long) 60*60*24);\n\t\t\tX509_set_pubkey(x509, pkey);\n\n\t\t\tname = X509_get_subject_name(x509);\n\t\t\tX509_NAME_add_entry_by_txt(name,\n\t\t\t\t\t\t   \"CN\",\n\t\t\t\t\t\t   MBSTRING_ASC,\n\t\t\t\t\t\t   (guchar *) \"test@test.com\",\n\t\t\t\t\t\t   -1, -1, 0);\n\t\t\tX509_set_issuer_name(x509, name);\n\n\t\t\tif (X509_sign(x509, pkey, EVP_sha1())) {\n\t\t\t\tguchar *buf;\n\n\t\t\t\tco = g_new0(struct certificate_openssl, 1);\n\t\t\t\tco->decoded = x509;\n\t\t\t\tco->key     = scc->key;\n\n\t\t\t\t/*\n\t\t\t\t * Encode into DER format\n\t\t\t\t *\n\t\t\t\t * NOTE: i2d_X509(a, b) autoincrements b!\n\t\t\t\t */\n\t\t\t\tco->length = i2d_X509(x509, NULL);\n\t\t\t\tco->raw = buf = g_malloc(co->length);\n\t\t\t\ti2d_X509(x509, &buf);\n\n\t\t\t} else {\n\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_cert_crypto_test_certificate: can't sign certificate\");\n\t\t\t\tX509_free(x509);\n\t\t\t}\n\t\t} else {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_cert_crypto_test_certificate: can't create x509 data structure\");\n\t\t}\n\n\t\tEVP_PKEY_free(pkey);\n\t} else {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_cert_crypto_test_certificate: can't create private key data structure\");\n\t}\n\n\treturn(co);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-cert-crypto.h",
    "content": "/**\n * @file sipe-cert-crypto.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-12 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/*\n * Internal interface between sipe-certificate/sipe-tls\n * and the certificate crypto implementation\n */\n\n/*\n * Interface dependencies:\n *\n * <glib.h>\n */\n\n/* Forward declarations */\nstruct sipe_cert_crypto;\n\n/**\n * Free certificate crypto backend data\n *\n * @return opaque pointer to backend private data\n */\nstruct sipe_cert_crypto *sipe_cert_crypto_init(void);\n\n/**\n * Free certificate crypto backend data\n *\n * @param scc opaque pointer to backend private data\n */\nvoid sipe_cert_crypto_free(struct sipe_cert_crypto *scc);\n\n/**\n * Create a certificate request as Base64 encoded string\n *\n * @param scc     opaque pointer to backend private data\n * @param subject subject for certificate request\n *\n * @return Base64 encoded string. Must be @g_free'd()\n */\ngchar *sipe_cert_crypto_request(struct sipe_cert_crypto *scc,\n\t\t\t\tconst gchar *subject);\n\n/**\n * Destroy certificate (this is a @GDestroyNotify)\n *\n * @param certificate opaque pointer to backend certificate structure\n *                    May be @c NULL\n */\nvoid sipe_cert_crypto_destroy(gpointer certificate);\n\n/**\n * Decode a client certificate from Base64 string\n *\n * @param base64 Base64 encoded DER data\n *\n * @return opaque pointer to certificate. Must be @sipe_cert_crypto_destroy()'d.\n */\ngpointer sipe_cert_crypto_decode(struct sipe_cert_crypto *scc,\n\t\t\t\t const gchar *base64);\n\n/**\n * Import a server certificate from DER data\n *\n * @param raw    DER data\n * @param length length of DER data\n *\n * @return opaque pointer to certificate. Must be @sipe_cert_crypto_destroy()'d.\n */\ngpointer sipe_cert_crypto_import(const guchar *raw, gsize length);\n\n/**\n * Check if certificate is valid until @c offset seconds from now\n *\n * @param certificate opaque pointer to backend certificate structure\n * @param offset      seconds from now\n *\n * @return @c TRUE if certificate is still valid at that time\n */\ngboolean sipe_cert_crypto_valid(gpointer certificate,\n\t\t\t\tguint offset);\n\n/**\n * Return how many seconds until the certificate expires\n *\n * @param certificate opaque pointer to backend certificate structure\n *\n * @return offset in seconds\n */\nguint sipe_cert_crypto_expires(gpointer certificate);\n\n/**\n * Return length of certificate in DER form\n *\n * @param certificate opaque pointer to backend certificate structure\n *\n * @return length in bytes\n */\ngsize sipe_cert_crypto_raw_length(gpointer certificate);\n\n/**\n * Return certificate in DER form\n *\n * @param certificate opaque pointer to backend certificate structure\n *\n * @return pointer to DER data\n */\nconst guchar *sipe_cert_crypto_raw(gpointer certificate);\n\n/**\n * Get public key for certificate\n *\n * @param certificate opaque pointer to backend certificate structure\n *\n * @return opaque pointer to backend public key structure\n */\ngpointer sipe_cert_crypto_public_key(gpointer certificate);\n\n/**\n * Get public key modulus length for server certificate\n *\n * @param certificate opaque pointer to backend certificate structure\n *\n * @return server public key strength\n */\ngsize sipe_cert_crypto_modulus_length(gpointer certificate);\n\n/**\n * Get private key for client certificate\n *\n * @param certificate opaque pointer to backend certificate structure\n *\n * @return opaque pointer to backend private key structure\n */\ngpointer sipe_cert_crypto_private_key(gpointer certificate);\n\n/**\n * Create test certificate for internal key pair (ONLY USE FOR TEST CODE!!!)\n *\n * @param scc opaque pointer to backend private data\n *\n * @return opaque pointer to backend certificate structure\n */\ngpointer sipe_cert_crypto_test_certificate(struct sipe_cert_crypto *scc);\n"
  },
  {
    "path": "src/core/sipe-certificate.c",
    "content": "/**\n * @file sipe-certificate.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * Specification references:\n *\n *   - [MS-SIPAE]:    http://msdn.microsoft.com/en-us/library/cc431510.aspx\n *   - [MS-OCAUTHWS]: http://msdn.microsoft.com/en-us/library/ff595592.aspx\n *   - MS Tech-Ed Europe 2010 \"UNC310: Microsoft Lync 2010 Technology Explained\"\n *     http://ecn.channel9.msdn.com/o9/te/Europe/2010/pptx/unc310.pptx\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-certificate.h\"\n#include \"sipe-cert-crypto.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-svc.h\"\n#include \"sipe-webticket.h\"\n#include \"sipe-xml.h\"\n\nstruct sipe_certificate {\n\tGHashTable *certificates;\n\tstruct sipe_cert_crypto *backend;\n};\n\nstruct certificate_callback_data {\n\tgchar *target;\n\tstruct sipe_svc_session *session;\n};\n\nstatic void callback_data_free(struct certificate_callback_data *ccd)\n{\n\tif (ccd) {\n\t\tsipe_svc_session_close(ccd->session);\n\t\tg_free(ccd->target);\n\t\tg_free(ccd);\n\t}\n}\n\nvoid sipe_certificate_free(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_certificate *sc = sipe_private->certificate;\n\n\tif (sc) {\n\t\tg_hash_table_destroy(sc->certificates);\n\t\tsipe_cert_crypto_free(sc->backend);\n\t\tg_free(sc);\n\t}\n}\n\ngboolean sipe_certificate_init(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_certificate *sc;\n\tstruct sipe_cert_crypto *ssc;\n\n\tif (sipe_private->certificate)\n\t\treturn(TRUE);\n\n\tssc = sipe_cert_crypto_init();\n\tif (!ssc) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_certificate_init: crypto backend init FAILED!\");\n\t\treturn(FALSE);\n\t}\n\n\tsc = g_new0(struct sipe_certificate, 1);\n\tsc->certificates = g_hash_table_new_full(g_str_hash, g_str_equal,\n\t\t\t\t\t\t g_free,\n\t\t\t\t\t\t sipe_cert_crypto_destroy);\n\tsc->backend = ssc;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_certificate_init: DONE\");\n\n\tsipe_private->certificate = sc;\n\treturn(TRUE);\n}\n\nstatic gchar *create_certreq(struct sipe_core_private *sipe_private,\n\t\t\t     const gchar *subject)\n{\n\tgchar *base64;\n\n\tif (!sipe_certificate_init(sipe_private))\n\t\treturn(NULL);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"create_req: generating new certificate request\");\n\n\tbase64 = sipe_cert_crypto_request(sipe_private->certificate->backend,\n\t\t\t\t\t  subject);\n\tif (base64) {\n\t\tGString *format = g_string_new(NULL);\n\t\tgsize count     = strlen(base64);\n\t\tconst gchar *p  = base64;\n\n\t\t/* Base64 needs to be formated correctly */\n#define CERTREQ_BASE64_LINE_LENGTH 76\n\t\twhile (count > 0) {\n\t\t\tgsize chunk = count > CERTREQ_BASE64_LINE_LENGTH ?\n\t\t\t\tCERTREQ_BASE64_LINE_LENGTH : count;\n\t\t\tg_string_append_len(format, p, chunk);\n\t\t\tif (chunk == CERTREQ_BASE64_LINE_LENGTH)\n\t\t\t\tg_string_append(format, \"\\r\\n\");\n\t\t\tcount -= chunk;\n\t\t\tp     += chunk;\n\t\t}\n\n\t\t/* swap Base64 buffers */\n\t\tg_free(base64);\n\t\tbase64 = format->str;\n\t\tg_string_free(format, FALSE);\n\t}\n\n\treturn(base64);\n}\n\nstatic void add_certificate(struct sipe_core_private *sipe_private,\n\t\t\t    const gchar *target,\n\t\t\t    gpointer certificate)\n{\n\tstruct sipe_certificate *sc = sipe_private->certificate;\n\tg_hash_table_insert(sc->certificates, g_strdup(target), certificate);\n}\n\ngpointer sipe_certificate_tls_dsk_find(struct sipe_core_private *sipe_private,\n\t\t\t\t       const gchar *target)\n{\n\tstruct sipe_certificate *sc = sipe_private->certificate;\n\tgpointer certificate;\n\n\tif (!target || !sc)\n\t\treturn(NULL);\n\n\tcertificate = g_hash_table_lookup(sc->certificates, target);\n\n\t/* Let's make sure the certificate is still valid for another hour */\n\tif (!sipe_cert_crypto_valid(certificate, 60 * 60)) {\n\t\tSIPE_DEBUG_ERROR(\"sipe_certificate_tls_dsk_find: certificate for '%s' is invalid\",\n\t\t\t\t target);\n\t\treturn(NULL);\n\t}\n\n\treturn(certificate);\n}\n\nstatic void certificate_failure(struct sipe_core_private *sipe_private,\n\t\t\t\tconst gchar *format,\n\t\t\t\tconst gchar *parameter,\n\t\t\t\tconst gchar *failure_info)\n{\n\tgchar *tmp = g_strdup_printf(format, parameter);\n\tif (failure_info) {\n\t\tgchar *tmp2 = g_strdup_printf(\"%s\\n(%s)\", tmp, failure_info);\n\t\tg_free(tmp);\n\t\ttmp = tmp2;\n\t}\n\tsipe_backend_connection_error(SIPE_CORE_PUBLIC,\n\t\t\t\t      SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,\n\t\t\t\t      tmp);\n\tg_free(tmp);\n}\n\nstatic void get_and_publish_cert(struct sipe_core_private *sipe_private,\n\t\t\t\t const gchar *uri,\n\t\t\t\t SIPE_UNUSED_PARAMETER const gchar *raw,\n\t\t\t\t sipe_xml *soap_body,\n\t\t\t\t gpointer callback_data)\n{\n\tstruct certificate_callback_data *ccd = callback_data;\n\tgboolean success = (uri == NULL); /* abort case */\n\n\tif (soap_body) {\n\t\tgchar *cert_base64 = sipe_xml_data(sipe_xml_child(soap_body,\n\t\t\t\t\t\t\t\t  \"Body/GetAndPublishCertResponse/RequestSecurityTokenResponse/RequestedSecurityToken/BinarySecurityToken\"));\n\n\t\tSIPE_DEBUG_INFO(\"get_and_publish_cert: received valid SOAP message from service %s\",\n\t\t\t\turi);\n\n\t\tif (cert_base64) {\n\t\t\tgpointer opaque = sipe_cert_crypto_decode(sipe_private->certificate->backend,\n\t\t\t\t\t\t\t\t  cert_base64);\n\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"get_and_publish_cert: found certificate\");\n\n\t\t\tif (opaque) {\n\t\t\t\tadd_certificate(sipe_private,\n\t\t\t\t\t\tccd->target,\n\t\t\t\t\t\topaque);\n\t\t\t\tSIPE_DEBUG_INFO(\"get_and_publish_cert: certificate for target '%s' added\",\n\t\t\t\t\t\tccd->target);\n\n\t\t\t\t/* Let's try this again... */\n\t\t\t\tsip_transport_authentication_completed(sipe_private);\n\t\t\t\tsuccess = TRUE;\n\t\t\t}\n\n\t\t\tg_free(cert_base64);\n\t\t}\n\n\t}\n\n\tif (!success) {\n\t\tcertificate_failure(sipe_private,\n\t\t\t\t    _(\"Certificate request to %s failed\"),\n\t\t\t\t    uri,\n\t\t\t\t    NULL);\n\t}\n\n\tcallback_data_free(ccd);\n}\n\nstatic void certprov_webticket(struct sipe_core_private *sipe_private,\n\t\t\t       const gchar *base_uri,\n\t\t\t       const gchar *auth_uri,\n\t\t\t       const gchar *wsse_security,\n\t\t\t       const gchar *failure_msg,\n\t\t\t       gpointer callback_data)\n{\n\tstruct certificate_callback_data *ccd = callback_data;\n\n\tif (wsse_security) {\n\t\t/* Got a Web Ticket for Certificate Provisioning Service */\n\t\tgchar *certreq_base64 = create_certreq(sipe_private,\n\t\t\t\t\t\t       sipe_private->username);\n\n\t\tSIPE_DEBUG_INFO(\"certprov_webticket: got ticket for %s\",\n\t\t\t\tbase_uri);\n\n\t\tif (certreq_base64) {\n\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"certprov_webticket: created certificate request\");\n\n\t\t\tif (sipe_svc_get_and_publish_cert(sipe_private,\n\t\t\t\t\t\t\t  ccd->session,\n\t\t\t\t\t\t\t  auth_uri,\n\t\t\t\t\t\t\t  wsse_security,\n\t\t\t\t\t\t\t  certreq_base64,\n\t\t\t\t\t\t\t  get_and_publish_cert,\n\t\t\t\t\t\t\t  ccd))\n\t\t\t\t/* callback data passed down the line */\n\t\t\t\tccd = NULL;\n\n\t\t\tg_free(certreq_base64);\n\t\t}\n\n\t        if (ccd) {\n\t\t\tcertificate_failure(sipe_private,\n\t\t\t\t\t    _(\"Certificate request to %s failed\"),\n\t\t\t\t\t    base_uri,\n\t\t\t\t\t    NULL);\n\t\t}\n\n\t} else if (auth_uri) {\n\t\tcertificate_failure(sipe_private,\n\t\t\t\t    _(\"Web ticket request to %s failed\"),\n\t\t\t\t    base_uri,\n\t\t\t\t    failure_msg);\n\t}\n\n\tif (ccd)\n\t\tcallback_data_free(ccd);\n}\n\ngboolean sipe_certificate_tls_dsk_generate(struct sipe_core_private *sipe_private,\n\t\t\t\t\t   const gchar *target,\n\t\t\t\t\t   const gchar *uri)\n{\n\tstruct certificate_callback_data *ccd = g_new0(struct certificate_callback_data, 1);\n\tgboolean ret;\n\n\tccd->session = sipe_svc_session_start();\n\n\tret = sipe_webticket_request_with_port(sipe_private,\n\t\t\t\t\t       ccd->session,\n\t\t\t\t\t       uri,\n\t\t\t\t\t       \"CertProvisioningServiceWebTicketProof_SHA1\",\n\t\t\t\t\t       certprov_webticket,\n\t\t\t\t\t       ccd);\n\tif (ret) {\n\t\tccd->target = g_strdup(target);\n\n\t} else {\n\t\tcallback_data_free(ccd);\n\t}\n\n\treturn(ret);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-certificate.h",
    "content": "/**\n * @file sipe-certificate.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/*\n * Interface dependencies:\n *\n * <glib.h>\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\n\n/**\n * Find TLS-DSK user certificate for a given target\n *\n * @param sipe_private SIPE core private data\n * @param target       target name from authentication header\n *\n * @return opaque      pointer to the certificate. The caller does not own\n *                     the certificate, i.e. he must not free it!\n */\ngpointer sipe_certificate_tls_dsk_find(struct sipe_core_private *sipe_private,\n\t\t\t\t       const gchar *target);\n\n\n/**\n * Trigger the generation of TLS-DSK user certificate for a given target\n *\n * @param sipe_private SIPE core private data\n * @param target       target name from authentication header\n * @param uri          URI for the Certificate Provisioning Service\n * @return             @c TRUE if certificate generation was triggered\n */\ngboolean sipe_certificate_tls_dsk_generate(struct sipe_core_private *sipe_private,\n\t\t\t\t\t   const gchar *target,\n\t\t\t\t\t   const gchar *uri);\n\n/**\n * Initialize certificate data\n *\n * @param sipe_private SIPE core private data\n */\ngboolean sipe_certificate_init(struct sipe_core_private *sipe_private);\n\n/**\n * Free certificate data\n *\n * @param sipe_private SIPE core private data\n */\nvoid sipe_certificate_free(struct sipe_core_private *sipe_private);\n"
  },
  {
    "path": "src/core/sipe-chat.c",
    "content": "/**\n * @file sipe-chat.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2009-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipmsg.h\"\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-chat.h\"\n#include \"sipe-conf.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-dialog.h\"\n#include \"sipe-groupchat.h\"\n#include \"sipe-im.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-schedule.h\"\n#include \"sipe-session.h\"\n#include \"sipe-user.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n\n/**\n * Invite @who to chat\n *\n * @param sipe_private SIPE core private data\n * @param session SIPE session for chat\n * @param who URI whom to invite to chat.\n */\nstatic void\nsipe_invite_to_chat(struct sipe_core_private *sipe_private,\n\t\t    struct sip_session *session,\n\t\t    const gchar *who);\n\nstatic GList *chat_sessions = NULL;\n\nstruct sipe_chat_session *sipe_chat_create_session(guint type,\n\t\t\t\t\t\t   const gchar *id,\n\t\t\t\t\t\t   const gchar *title)\n{\n\tstruct sipe_chat_session *session = g_new0(struct sipe_chat_session, 1);\n\tif (id)\n\t\tsession->id = g_strdup(id);\n\tsession->title = g_strdup(title);\n\tsession->type  = type;\n\tchat_sessions  = g_list_prepend(chat_sessions, session);\n\treturn(session);\n}\n\nvoid sipe_chat_remove_session(struct sipe_chat_session *session)\n{\n\tchat_sessions = g_list_remove(chat_sessions, session);\n\tsipe_backend_chat_session_destroy(session->backend);\n\tg_free(session->title);\n\tg_free(session->id);\n\tg_free(session->join_url);\n\tg_free(session->dial_in_conf_id);\n\tg_free(session->organizer);\n\n\tif (session->appshare_ask_ctx) {\n\t\tsipe_user_close_ask(session->appshare_ask_ctx);\n\t}\n\n\tg_free(session);\n}\n\nvoid sipe_chat_destroy(void)\n{\n\twhile (chat_sessions) {\n\t\tstruct sipe_chat_session *chat_session = chat_sessions->data;\n\t\tSIPE_DEBUG_INFO(\"sipe_chat_destroy: '%s' (%s)\",\n\t\t\t\tchat_session->title, chat_session->id);\n\t\tsipe_chat_remove_session(chat_session);\n\t}\n}\n\nconst gchar *sipe_core_chat_id(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t       struct sipe_chat_session *chat_session)\n{\n\treturn(chat_session->id);\n}\n\nguint sipe_core_chat_type(struct sipe_chat_session *chat_session)\n{\n\treturn(chat_session ? chat_session->type : SIPE_CHAT_TYPE_UNKNOWN);\n}\n\nvoid sipe_core_chat_invite(struct sipe_core_public *sipe_public,\n\t\t\t   struct sipe_chat_session *chat_session,\n\t\t\t   const char *name)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\n\tSIPE_DEBUG_INFO(\"sipe_core_chat_create: who '%s'\", name);\n\n\tswitch (chat_session->type) {\n\tcase SIPE_CHAT_TYPE_MULTIPARTY:\n\tcase SIPE_CHAT_TYPE_CONFERENCE:\n\t\t{\n\t\t\tstruct sip_session *session = sipe_session_find_chat(sipe_private,\n\t\t\t\t\t\t\t\t\t     chat_session);\n\n\t\t\tif (session) {\n\t\t\t\tgchar *uri = sip_uri(name);\n\t\t\t\tsipe_invite_to_chat(sipe_private, session, uri);\n\t\t\t\tg_free(uri);\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase SIPE_CHAT_TYPE_GROUPCHAT:\n\t\t/* @TODO */\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"GROUP CHAT: INVITE NOT IMPLEMENTED!\");\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\nvoid sipe_core_chat_rejoin(struct sipe_core_public *sipe_public,\n\t\t\t   struct sipe_chat_session *chat_session)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\n\tSIPE_DEBUG_INFO(\"sipe_core_chat_rejoin: '%s'\", chat_session->title);\n\n\tswitch (chat_session->type) {\n\tcase SIPE_CHAT_TYPE_MULTIPARTY:\n\t\t{\n\t\t\tstruct sip_session *session = sipe_session_add_chat(sipe_private,\n\t\t\t\t\t\t\t\t\t    chat_session,\n\t\t\t\t\t\t\t\t\t    TRUE,\n\t\t\t\t\t\t\t\t\t    NULL);\n\t\t\tgchar *self = sip_uri_self(sipe_private);\n\n\t\t\tsipe_invite_to_chat(sipe_private, session, self);\n\t\t\tsipe_backend_chat_rejoin(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t chat_session->backend,\n\t\t\t\t\t\t self,\n\t\t\t\t\t\t chat_session->title);\n\t\t\tg_free(self);\n\t\t}\n\t\tbreak;\n\tcase SIPE_CHAT_TYPE_CONFERENCE:\n\t\tsipe_conf_create(sipe_private, chat_session, NULL);\n\t\tbreak;\n\tcase SIPE_CHAT_TYPE_GROUPCHAT:\n\t\tsipe_groupchat_rejoin(sipe_private, chat_session);\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\nvoid sipe_core_chat_leave(struct sipe_core_public *sipe_public,\n\t\t\t  struct sipe_chat_session *chat_session)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\n\tSIPE_DEBUG_INFO(\"sipe_core_chat_leave: '%s'\", chat_session->title);\n\n\tswitch (chat_session->type) {\n\tcase SIPE_CHAT_TYPE_MULTIPARTY:\n\tcase SIPE_CHAT_TYPE_CONFERENCE:\n\t\t{\n\t\t\tstruct sip_session *session = sipe_session_find_chat(sipe_private,\n\t\t\t\t\t\t\t\t\t     chat_session);\n\n\t\t\tif (session) {\n\t\t\t\tsipe_session_close(sipe_private, session);\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase SIPE_CHAT_TYPE_GROUPCHAT:\n\t\tsipe_groupchat_leave(sipe_private, chat_session);\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\nvoid sipe_core_chat_send(struct sipe_core_public *sipe_public,\n\t\t\t struct sipe_chat_session *chat_session,\n\t\t\t const char *what)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\n\tSIPE_DEBUG_INFO(\"sipe_core_chat_send: '%s' to '%s'\",\n\t\t\twhat, chat_session->title);\n\n\tswitch (chat_session->type) {\n\tcase SIPE_CHAT_TYPE_MULTIPARTY:\n\tcase SIPE_CHAT_TYPE_CONFERENCE:\n\t\t{\n\t\t\tstruct sip_session *session = sipe_session_find_chat(sipe_private,\n\t\t\t\t\t\t\t\t\t     chat_session);\n\n\t\t\tif (session) {\n\t\t\t\tsipe_session_enqueue_message(session,\n\t\t\t\t\t\t\t     what,\n\t\t\t\t\t\t\t     NULL);\n\t\t\t\tsipe_im_process_queue(sipe_private, session);\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase SIPE_CHAT_TYPE_GROUPCHAT:\n\t\tsipe_groupchat_send(sipe_private, chat_session, what);\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\ngchar *\nsipe_chat_get_name(void)\n{\n\t/**\n\t * A non-volatile ID counter.\n\t * Should survive connection drop & reconnect.\n\t */\n\tstatic guint chat_seq = 0;\n\n\t/* Generate next ID */\n\tgchar *chat_name = g_strdup_printf(_(\"Chat #%d\"), ++chat_seq);\n\tSIPE_DEBUG_INFO(\"sipe_chat_get_name: added new: %s\", chat_name);\n\n\treturn chat_name;\n}\n\nstatic void\nsipe_refer(struct sipe_core_private *sipe_private,\n\t   struct sip_session *session,\n\t   const gchar *who)\n{\n\tgchar *hdr;\n\tgchar *contact;\n\tstruct sip_dialog *dialog = sipe_dialog_find(session,\n\t\t\t\t\t\t     session->chat_session->id);\n\tconst char *ourtag = dialog && dialog->ourtag ? dialog->ourtag : NULL;\n\n\tcontact = get_contact(sipe_private);\n\thdr = g_strdup_printf(\n\t\t\"Contact: %s\\r\\n\"\n\t\t\"Refer-to: <%s>\\r\\n\"\n\t\t\"Referred-By: <sip:%s>%s%s;epid=%s\\r\\n\"\n\t\t\"Require: com.microsoft.rtc-multiparty\\r\\n\",\n\t\tcontact,\n\t\twho,\n\t\tsipe_private->username,\n\t\tourtag ? \";tag=\" : \"\",\n\t\tourtag ? ourtag : \"\",\n\t\tsip_transport_epid(sipe_private));\n\n\tsip_transport_request(sipe_private,\n\t\t\t      \"REFER\",\n\t\t\t      session->chat_session->id,\n\t\t\t      session->chat_session->id,\n\t\t\t      hdr,\n\t\t\t      NULL,\n\t\t\t      dialog,\n\t\t\t      NULL);\n\n\tg_free(hdr);\n\tg_free(contact);\n}\n\nstatic gboolean\nsipe_is_election_finished(struct sip_session *session)\n{\n\tgboolean res = TRUE;\n\n\tSIPE_DIALOG_FOREACH {\n\t\tif (dialog->election_vote == 0) {\n\t\t\tres = FALSE;\n\t\t\tbreak;\n\t\t}\n\t} SIPE_DIALOG_FOREACH_END;\n\n\tif (res) {\n\t\tsession->is_voting_in_progress = FALSE;\n\t}\n\treturn res;\n}\n\nstatic gboolean\nprocess_info_response(struct sipe_core_private *sipe_private,\n\t\t      struct sipmsg *msg,\n\t\t      struct transaction *trans);\n\nstatic void\nsipe_send_election_set_rm(struct sipe_core_private *sipe_private,\n\t\t\t  struct sip_dialog *dialog)\n{\n\tconst gchar *hdr = \"Content-Type: application/x-ms-mim\\r\\n\";\n\n\tgchar *body = g_strdup_printf(\n\t\t\"<?xml version=\\\"1.0\\\"?>\\r\\n\"\n\t\t\"<action xmlns=\\\"http://schemas.microsoft.com/sip/multiparty/\\\">\"\n\t\t\"<SetRM uri=\\\"sip:%s\\\"/></action>\\r\\n\",\n\t\tsipe_private->username);\n\n\tsip_transport_info(sipe_private,\n\t\t\t   hdr,\n\t\t\t   body,\n\t\t\t   dialog,\n\t\t\t   process_info_response);\n\n\tg_free(body);\n}\n\nvoid\nsipe_process_pending_invite_queue(struct sipe_core_private *sipe_private,\n\t\t\t\t  struct sip_session *session)\n{\n\tgchar *invitee;\n\tGSList *entry = session->pending_invite_queue;\n\n\twhile (entry) {\n\t\tinvitee = entry->data;\n\t\tsipe_invite_to_chat(sipe_private, session, invitee);\n\t\tentry = session->pending_invite_queue = g_slist_remove(session->pending_invite_queue, invitee);\n\t\tg_free(invitee);\n\t}\n}\n\nvoid sipe_chat_set_roster_manager(struct sip_session *session,\n\t\t\t\t  const gchar *roster_manager)\n{\n\tstruct sipe_chat_session *chat_session = session->chat_session;\n\n\tg_free(chat_session->id);\n\tchat_session->id = NULL;\n\tif (roster_manager)\n\t\tchat_session->id = g_strdup(roster_manager);\n}\n\nstatic void\nsipe_election_result(struct sipe_core_private *sipe_private,\n\t\t     void *sess)\n{\n\tstruct sip_session *session = (struct sip_session *)sess;\n\tconst gchar *rival = NULL;\n\n\tif (session->chat_session->id) {\n\t\tSIPE_DEBUG_INFO(\n\t\t\t\"sipe_election_result: RM has already been elected in the meantime. It is %s\",\n\t\t\tsession->chat_session->id);\n\t\treturn;\n\t}\n\n\tsession->is_voting_in_progress = FALSE;\n\n\tSIPE_DIALOG_FOREACH {\n\t\tif (dialog->election_vote < 0) {\n\t\t\trival = dialog->with;\n\t\t\tbreak;\n\t\t}\n\t} SIPE_DIALOG_FOREACH_END;\n\n\tif (rival) {\n\t\tSIPE_DEBUG_INFO(\"sipe_election_result: we loose RM election to %s\", rival);\n\t} else {\n\t\tgchar *self = sip_uri_self(sipe_private);\n\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_election_result: we have won RM election!\");\n\n\t\tsipe_chat_set_roster_manager(session, self);\n\t\tg_free(self);\n\n\t\tSIPE_DIALOG_FOREACH {\n\t\t\t/* send SetRM to each chat participant*/\n\t\t\tsipe_send_election_set_rm(sipe_private, dialog);\n\t\t} SIPE_DIALOG_FOREACH_END;\n\t}\n\tsession->bid = 0;\n\n\tsipe_process_pending_invite_queue(sipe_private, session);\n}\n\nstatic gboolean\nprocess_info_response(struct sipe_core_private *sipe_private,\n\t\t      struct sipmsg *msg,\n\t\t      SIPE_UNUSED_PARAMETER struct transaction *trans)\n{\n\tconst gchar *contenttype = sipmsg_find_content_type_header(msg);\n\tconst gchar *callid = sipmsg_find_call_id_header(msg);\n\tstruct sip_dialog *dialog;\n\tstruct sip_session *session;\n\n\tsession = sipe_session_find_chat_by_callid(sipe_private, callid);\n\tif (!session) {\n\t\tSIPE_DEBUG_INFO(\"process_info_response: failed find dialog for callid %s, exiting.\", callid);\n\t\treturn FALSE;\n\t}\n\n\tif (msg->response == 200 && g_str_has_prefix(contenttype, \"application/x-ms-mim\")) {\n\t\tsipe_xml *xn_action                    = sipe_xml_parse(msg->body, msg->bodylen);\n\t\tconst sipe_xml *xn_request_rm_response = sipe_xml_child(xn_action, \"RequestRMResponse\");\n\t\tconst sipe_xml *xn_set_rm_response     = sipe_xml_child(xn_action, \"SetRMResponse\");\n\n\t\tif (xn_request_rm_response) {\n\t\t\tconst char *with = sipe_xml_attribute(xn_request_rm_response, \"uri\");\n\t\t\tconst char *allow = sipe_xml_attribute(xn_request_rm_response, \"allow\");\n\n\t\t\tdialog = sipe_dialog_find(session, with);\n\t\t\tif (!dialog) {\n\t\t\t\tSIPE_DEBUG_INFO(\"process_info_response: failed find dialog for %s, exiting.\", with);\n\t\t\t\tsipe_xml_free(xn_action);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tif (allow && !g_ascii_strcasecmp(allow, \"true\")) {\n\t\t\t\tSIPE_DEBUG_INFO(\"process_info_response: %s has voted PRO\", with);\n\t\t\t\tdialog->election_vote = 1;\n\t\t\t} else if (allow && !g_ascii_strcasecmp(allow, \"false\")) {\n\t\t\t\tSIPE_DEBUG_INFO(\"process_info_response: %s has voted CONTRA\", with);\n\t\t\t\tdialog->election_vote = -1;\n\t\t\t}\n\n\t\t\tif (sipe_is_election_finished(session)) {\n\t\t\t\tsipe_election_result(sipe_private,\n\t\t\t\t\t\t     session);\n\t\t\t}\n\n\t\t} else if (xn_set_rm_response) {\n\n\t\t}\n\t\tsipe_xml_free(xn_action);\n\n\t}\n\n\treturn TRUE;\n}\n\nstatic void\nsipe_send_election_request_rm(struct sipe_core_private *sipe_private,\n\t\t\t      struct sip_dialog *dialog,\n\t\t\t      int bid)\n{\n\tconst gchar *hdr = \"Content-Type: application/x-ms-mim\\r\\n\";\n\n\tgchar *body = g_strdup_printf(\n\t\t\"<?xml version=\\\"1.0\\\"?>\\r\\n\"\n\t\t\"<action xmlns=\\\"http://schemas.microsoft.com/sip/multiparty/\\\">\"\n\t\t\"<RequestRM uri=\\\"sip:%s\\\" bid=\\\"%d\\\"/></action>\\r\\n\",\n\t\tsipe_private->username, bid);\n\n\tsip_transport_info(sipe_private,\n\t\t\t   hdr,\n\t\t\t   body,\n\t\t\t   dialog,\n\t\t\t   process_info_response);\n\n\tg_free(body);\n}\n\nstatic void\nsipe_election_start(struct sipe_core_private *sipe_private,\n\t\t    struct sip_session *session)\n{\n\tif (session->is_voting_in_progress) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_election_start: other election is in progress, exiting.\");\n\t\treturn;\n\t} else {\n\t\tsession->is_voting_in_progress = TRUE;\n\t}\n\tsession->bid = rand();\n\n\tSIPE_DEBUG_INFO(\"sipe_election_start: RM election has initiated. Our bid=%d\", session->bid);\n\n\tSIPE_DIALOG_FOREACH {\n\t\t/* reset election_vote for each chat participant */\n\t\tdialog->election_vote = 0;\n\n\t\t/* send RequestRM to each chat participant*/\n\t\tsipe_send_election_request_rm(sipe_private, dialog, session->bid);\n\t} SIPE_DIALOG_FOREACH_END;\n\n\tsipe_schedule_seconds(sipe_private,\n\t\t\t      \"<+election-result>\",\n\t\t\t      session,\n\t\t\t      15,\n\t\t\t      sipe_election_result,\n\t\t\t      NULL);\n}\n\nstatic void\nsipe_invite_to_chat(struct sipe_core_private *sipe_private,\n\t\t    struct sip_session *session,\n\t\t    const gchar *who)\n{\n\t/* a conference */\n\tif (session->chat_session->type == SIPE_CHAT_TYPE_CONFERENCE)\n\t{\n\t\tsipe_invite_conf(sipe_private, session, who);\n\t}\n\telse /* a multi-party chat */\n\t{\n\t\tgchar *self = sip_uri_self(sipe_private);\n\t\tif (session->chat_session->id) {\n\t\t\tif (sipe_strcase_equal(session->chat_session->id, self)) {\n\t\t\t\tsipe_im_invite(sipe_private, session, who, NULL, NULL, NULL, FALSE);\n\t\t\t} else {\n\t\t\t\tsipe_refer(sipe_private, session, who);\n\t\t\t}\n\t\t} else {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_invite_to_chat: no RM available\");\n\n\t\t\tsession->pending_invite_queue = sipe_utils_slist_insert_unique_sorted(session->pending_invite_queue,\n\t\t\t\t\t\t\t\t\t\t\t      g_strdup(who),\n\t\t\t\t\t\t\t\t\t\t\t      (GCompareFunc)strcmp,\n\t\t\t\t\t\t\t\t\t\t\t      g_free);\n\t\t\tsipe_election_start(sipe_private, session);\n\t\t}\n\t\tg_free(self);\n\t}\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-chat.h",
    "content": "/**\n * @file sipe-chat.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2009-2017 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\nstruct sip_session;\nstruct sipe_backend_chat_session;\n\nenum sipe_chat_type {\n\tSIPE_CHAT_TYPE_UNKNOWN = 0,\n\tSIPE_CHAT_TYPE_MULTIPARTY,\n\tSIPE_CHAT_TYPE_CONFERENCE,\n\tSIPE_CHAT_TYPE_GROUPCHAT\n};\n\nstruct sipe_chat_session {\n\tstruct sipe_backend_chat_session *backend;\n\n\t/*\n\t * Chat identifier (must be unique per account)\n\t *\n\t * 2007 Group chat:      channel URI\n\t * 2007 Conference:      focus URI\n\t * 2005 multiparty chat: roster manager SIP URI\n\t */\n\tgchar *id;\n\n\t/* Human readable chat identifier (can have duplicates) */\n\tgchar *title;\n\n\t/* SIPE_CHAT_TYPE_xxx */\n\tguint type;\n\n\tgchar *join_url;\n\tgchar *dial_in_conf_id;\n\tgchar *organizer;\n\n\tstruct sipe_user_ask_ctx *appshare_ask_ctx;\n};\n\n/**\n * Create a new chat session\n *\n * @param session\n */\nstruct sipe_chat_session *\nsipe_chat_create_session(guint type,\n\t\t\t const gchar *id,\n\t\t\t const gchar *title);\n\n/**\n * Remove a chat session\n *\n * @param session\n */\nvoid\nsipe_chat_remove_session(struct sipe_chat_session *session);\n\n/**\n * Release resources on unload\n */\nvoid\nsipe_chat_destroy(void);\n\n/**\n * Generate a name for a new private chat.\n *\n * @return chat name. Must be g_free()'d after use\n */\ngchar *\nsipe_chat_get_name(void);\n\n/**\n *\n *\n * @param sipe_private SIPE core private data\n * @param session SIPE session for chat\n */\nvoid\nsipe_process_pending_invite_queue(struct sipe_core_private *sipe_private,\n\t\t\t\t  struct sip_session *session);\n\n/**\n * Set roster manager URI for a multiparty chat\n *\n * @param session SIPE session for chat\n * @param roster_manager New roster manager URI or NULL\n */\nvoid sipe_chat_set_roster_manager(struct sip_session *session,\n\t\t\t\t  const gchar *roster_manager);\n"
  },
  {
    "path": "src/core/sipe-conf.c",
    "content": "/**\n * @file sipe-conf.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2009 pier11 <pier11@operamail.com>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/**\n * Documentation references:\n *\n * Microsoft DevNet: [MS-CONFIM]: Centralized Conference Control Protocol:\n *                                Instant Messaging Extensions\n *  <http://msdn.microsoft.com/en-us/library/cc431500%28v=office.12%29.aspx>\n *\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipmsg.h\"\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-buddy.h\"\n#include \"sipe-chat.h\"\n#include \"sipe-conf.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-appshare.h\"\n#include \"sipe-dialog.h\"\n#include \"sipe-http.h\"\n#include \"sipe-im.h\"\n#include \"sipe-media.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-session.h\"\n#include \"sipe-subscriptions.h\"\n#include \"sipe-user.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n\n/**\n * Invite counterparty to join conference.\n * @param focus_uri (%s)\n * @param subject (%s) of conference\n */\n#define SIPE_SEND_CONF_INVITE \\\n\"<Conferencing version=\\\"2.0\\\">\"\\\n\t\"<focus-uri>%s</focus-uri>\"\\\n\t\"<subject>%s</subject>\"\\\n\t\"<im available=\\\"true\\\">\"\\\n\t\t\"<first-im/>\"\\\n\t\"</im>\"\\\n\"</Conferencing>\"\n\nstatic gboolean\nsipe_conf_check_for_lync_url(struct sipe_core_private *sipe_private,\n\t\t\t     gchar *uri);\n\nstatic struct transaction *\ncccp_request(struct sipe_core_private *sipe_private, const gchar *method,\n\t     const gchar *with, struct sip_dialog *dialog,\n\t     TransCallback callback, const gchar *body, ...)\n{\n\tgchar *headers;\n\tgchar *request;\n\tgchar *request_body;\n\n\tgchar *self = sip_uri_self(sipe_private);\n\n\tva_list args;\n\n\tstruct transaction *trans;\n\n\theaders = g_strdup_printf(\n\t\t\"Supported: ms-sender\\r\\n\"\n\t\t\"Contact: %s\\r\\n\"\n\t\t\"Content-Type: application/cccp+xml\\r\\n\",\n\t\tsipe_private->contact);\n\n\t/* TODO: put request_id to queue to further compare with incoming one */\n\trequest = g_strdup_printf(\n\t\t\"<?xml version=\\\"1.0\\\"?>\"\n\t\t\"<request xmlns=\\\"urn:ietf:params:xml:ns:cccp\\\" \"\n\t\t\"xmlns:mscp=\\\"http://schemas.microsoft.com/rtc/2005/08/cccpextensions\\\" \"\n\t\t\t\"C3PVersion=\\\"1\\\" \"\n\t\t\t\"to=\\\"%s\\\" \"\n\t\t\t\"from=\\\"%s\\\" \"\n\t\t\t\"requestId=\\\"%d\\\">\"\n\t\t\t\"%s\"\n\t\t\"</request>\",\n\t\twith,\n\t\tself,\n\t\tsipe_private->cccp_request_id++,\n\t\tbody);\n\tg_free(self);\n\n\tva_start(args, body);\n\trequest_body = g_strdup_vprintf(request, args);\n\tva_end(args);\n\n\tg_free(request);\n\n\ttrans = sip_transport_request(sipe_private,\n\t\t\t\t      method,\n\t\t\t\t      with,\n\t\t\t\t      with,\n\t\t\t\t      headers,\n\t\t\t\t      request_body,\n\t\t\t\t      dialog,\n\t\t\t\t      callback);\n\n\tg_free(headers);\n\tg_free(request_body);\n\n\treturn trans;\n}\n\nstatic gboolean\nprocess_conf_get_capabilities(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private,\n\t\t\t      struct sipmsg *msg,\n\t\t\t      SIPE_UNUSED_PARAMETER struct transaction *trans)\n{\n\tif (msg->response >= 400) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_conf_get_capabilities: \"\n\t\t\t\t\"getConferencingCapabilities failed.\");\n\t\treturn FALSE;\n\t}\n\tif (msg->response == 200) {\n\t\tsipe_xml *xn_response = sipe_xml_parse(msg->body, msg->bodylen);\n\t\tconst sipe_xml *node;\n\t\tgchar *default_region;\n\n\t\tif (!sipe_strequal(\"success\", sipe_xml_attribute(xn_response, \"code\"))) {\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tnode = sipe_xml_child(xn_response, \"getConferencingCapabilities/mcu-types/mcuType\");\n\t\tfor (;node; node = sipe_xml_twin(node)) {\n\t\t\tsipe_private->conf_mcu_types =\n\t\t\t\t\tg_slist_append(sipe_private->conf_mcu_types,\n\t\t\t\t\t\t       sipe_xml_data(node));\n\t\t}\n\n\t\tg_hash_table_remove_all(sipe_private->access_numbers);\n\t\tnode = sipe_xml_child(xn_response, \"getConferencingCapabilities/pstn-bridging/access-numbers/region\");\n\t\tfor (;node; node = sipe_xml_twin(node)) {\n\t\t\tgchar *name = g_strdup(sipe_xml_attribute(node, \"name\"));\n\t\t\tgchar *number = sipe_xml_data(sipe_xml_child(node, \"access-number/number\"));\n\t\t\tif (name && number) {\n\t\t\t\tg_hash_table_insert(sipe_private->access_numbers, name, number);\n\t\t\t}\n\t\t}\n\n\t\tnode = sipe_xml_child(xn_response, \"getConferencingCapabilities/pstn-bridging/access-numbers/default-region\");\n\t\tdefault_region = sipe_xml_data(node);\n\t\tif (default_region) {\n\t\t\tsipe_private->default_access_number =\n\t\t\t\t\tg_hash_table_lookup(sipe_private->access_numbers, default_region);\n\t\t}\n\t\tg_free(default_region);\n\n\t\tsipe_xml_free(xn_response);\n\t}\n\n\treturn TRUE;\n}\n\nvoid\nsipe_conf_get_capabilities(struct sipe_core_private *sipe_private)\n{\n\tcccp_request(sipe_private, \"SERVICE\",\n\t\t     sipe_private->focus_factory_uri,\n\t\t     NULL,\n\t\t     process_conf_get_capabilities,\n\t\t     \"<getConferencingCapabilities />\");\n}\n\ngboolean\nsipe_conf_supports_mcu_type(struct sipe_core_private *sipe_private,\n\t\t\t    const gchar *type)\n{\n\treturn g_slist_find_custom(sipe_private->conf_mcu_types, type,\n\t\t\t\t   (GCompareFunc)g_strcmp0) != NULL;\n}\n\n/**\n * Generates random GUID.\n * This method is borrowed from pidgin's msnutils.c\n */\nstatic char *\nrand_guid()\n{\n\treturn g_strdup_printf(\"%4X%4X-%4X-%4X-%4X-%4X%4X%4X\",\n\t\t\trand() % 0xAAFF + 0x1111,\n\t\t\trand() % 0xAAFF + 0x1111,\n\t\t\trand() % 0xAAFF + 0x1111,\n\t\t\trand() % 0xAAFF + 0x1111,\n\t\t\trand() % 0xAAFF + 0x1111,\n\t\t\trand() % 0xAAFF + 0x1111,\n\t\t\trand() % 0xAAFF + 0x1111,\n\t\t\trand() % 0xAAFF + 0x1111);\n}\n\n/** Invite us to the focus callback */\nstatic gboolean\nprocess_invite_conf_focus_response(struct sipe_core_private *sipe_private,\n\t\t\t\t   struct sipmsg *msg,\n\t\t\t\t   SIPE_UNUSED_PARAMETER struct transaction *trans)\n{\n\tstruct sip_session *session = NULL;\n\tchar *focus_uri = sipmsg_parse_to_address(msg);\n\n\tsession = sipe_session_find_conference(sipe_private, focus_uri);\n\n\tif (!session) {\n\t\tSIPE_DEBUG_INFO(\"process_invite_conf_focus_response: unable to find conf session with focus=%s\", focus_uri);\n\t\tg_free(focus_uri);\n\t\treturn FALSE;\n\t}\n\n\tif (!session->focus_dialog) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_invite_conf_focus_response: session's focus_dialog is NULL\");\n\t\tg_free(focus_uri);\n\t\treturn FALSE;\n\t}\n\n\tsipe_dialog_parse(session->focus_dialog, msg, TRUE);\n\n\tif (msg->response >= 200) {\n\t\t/* send ACK to focus */\n\t\tsession->focus_dialog->cseq = 0;\n\t\tsip_transport_ack(sipe_private, session->focus_dialog);\n\t\tsession->focus_dialog->outgoing_invite = NULL;\n\t\tsession->focus_dialog->is_established = TRUE;\n\t}\n\n\tif (msg->response >= 400) {\n\t\tgchar *reason = sipmsg_get_ms_diagnostics_reason(msg);\n\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_invite_conf_focus_response: INVITE response is not 200. Failed to join focus.\");\n\t\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t  _(\"Failed to join the conference\"),\n\t\t\t\t\t  reason ? reason : _(\"no reason given\"));\n\t\tg_free(reason);\n\n\t\tsipe_session_remove(sipe_private, session);\n\t\tg_free(focus_uri);\n\t\treturn FALSE;\n\t} else if (msg->response == 200) {\n\t\tsipe_xml *xn_response = sipe_xml_parse(msg->body, msg->bodylen);\n\t\tconst gchar *code = sipe_xml_attribute(xn_response, \"code\");\n\t\tif (sipe_strequal(code, \"success\")) {\n\t\t\t/* subscribe to focus */\n\t\t\tsipe_subscribe_conference(sipe_private,\n\t\t\t\t\t\t  session->chat_session->id,\n\t\t\t\t\t\t  FALSE);\n#ifdef HAVE_VV\n\t\t\tif (session->is_call)\n\t\t\t\tsipe_core_media_connect_conference(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t   session->chat_session,\n\t\t\t\t\t\t\t\t   FALSE);\n#endif\n\t\t}\n\t\tsipe_xml_free(xn_response);\n\t}\n\n\tg_free(focus_uri);\n\treturn TRUE;\n}\n\nstatic gchar *\nparse_ocs_focus_uri(const gchar *uri)\n{\n\tconst gchar *confkey;\n\tsize_t uri_len;\n\n\tif (!uri)\n\t\treturn NULL;\n\n\t// URI can have this prefix if it was typed in by the user\n\tif (g_str_has_prefix(uri, \"meet:\") || g_str_has_prefix(uri, \"conf:\")) {\n\t\turi += 5;\n\t}\n\n\turi_len = strlen(uri);\n\n\tif (!uri || !g_str_has_prefix(uri, \"sip:\") ||\n\t\turi_len == 4 || g_strstr_len(uri, -1, \"%\")) {\n\t\treturn NULL;\n\t}\n\n\tconfkey = g_strstr_len(uri, -1, \"?\");\n\tif (confkey) {\n\t\t/* TODO: Investigate how conf-key field should be used,\n\t\t * ignoring for now */\n\t\turi_len = confkey - uri;\n\t}\n\n\treturn g_strndup(uri, uri_len);\n}\n\nstatic gchar *\nextract_uri_from_html(const gchar *body,\n\t\t      const gchar *prefix,\n\t\t      guint prefix_skip_chars)\n{\n\tgchar *uri = NULL;\n\tconst gchar *start = g_strstr_len(body, -1, prefix);\n\n\tif (start) {\n\t\tconst gchar *end;\n\n\t\tstart += prefix_skip_chars;\n\t\tend = strchr(start, '\"');\n\n\t\tif (end) {\n\t\t\tgchar *html = g_strndup(start, end - start);\n\n\t\t\t/* decode HTML entities */\n\t\t\tgchar *html_unescaped = sipe_backend_markup_strip_html(html);\n\t\t\tg_free(html);\n\n\t\t\tif (!is_empty(html_unescaped)) {\n\t\t\t\turi = sipe_utils_uri_unescape(html_unescaped);\n\t\t\t}\n\n\t\t\tg_free(html_unescaped);\n\t\t}\n\t}\n\n\treturn uri;\n}\n\nstatic void sipe_conf_lync_url_cb(struct sipe_core_private *sipe_private,\n\t\t\t\t  guint status,\n\t\t\t\t  SIPE_UNUSED_PARAMETER GSList *headers,\n\t\t\t\t  const gchar *body,\n\t\t\t\t  gpointer callback_data)\n{\n\tgchar *uri = callback_data;\n\n\tif (status != (guint) SIPE_HTTP_STATUS_ABORTED) {\n\t\tgchar *focus_uri = NULL;\n\n\t\tif (body) {\n\t\t\t/*\n\t\t\t * Extract focus URI from HTML, e.g.\n\t\t\t *\n\t\t\t *  <a ... href=\"conf&#58;sip&#58;...ABCDEF&#37;3Frequired...\" ... >\n\t\t\t */\n\t\t\tgchar *uri = extract_uri_from_html(body, \"href=\\\"conf\", 6);\n\t\t\tfocus_uri = parse_ocs_focus_uri(uri);\n\t\t\tg_free(uri);\n\t\t}\n\n\t\tif (focus_uri) {\n\t\t\tSIPE_DEBUG_INFO(\"sipe_conf_lync_url_cb: found focus URI\"\n\t\t\t\t\t\" '%s'\", focus_uri);\n\n\t\t\tsipe_conf_create(sipe_private, NULL, focus_uri);\n\t\t\tg_free(focus_uri);\n\t\t} else {\n\t\t\t/*\n\t\t\t * If present, domainOwnerJoinLauncherUrl redirects to\n\t\t\t * a page from where we still may extract the focus URI.\n\t\t\t */\n\t\t\tgchar *launcher_url = NULL;\n\t\t\tstatic const gchar *launcher_url_prefix[] = {\n\t\t\t\t\"var domainOwnerJoinLauncherUrl = \\\"\",\n\t\t\t\t\"sb-data-domainOwnerJoinLauncherUrl=\\\"\",\n\t\t\t\tNULL\n\t\t\t};\n\t\t\tconst gchar **p;\n\n\t\t\tSIPE_DEBUG_INFO(\"sipe_conf_lync_url_cb: no focus URI \"\n\t\t\t\t\t\"found from URL '%s'\", uri);\n\n\t\t\tfor (p = launcher_url_prefix; !launcher_url && *p; ++p) {\n\t\t\t\tlauncher_url = extract_uri_from_html(body,\n\t\t\t\t\t\t\t\t     *p,\n\t\t\t\t\t\t\t\t     strlen(*p));\n\t\t\t}\n\n\t\t\tif (launcher_url &&\n\t\t\t    sipe_conf_check_for_lync_url(sipe_private, launcher_url)) {\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_conf_lync_url_cb: retrying with URL '%s'\",\n\t\t\t\t\t\tlauncher_url);\n\t\t\t\t/* Ownership taken by sipe_conf_check_for_lync_url() */\n\t\t\t\tlauncher_url = NULL;\n\t\t\t} else {\n\t\t\t\tgchar *error;\n\n\t\t\t\terror = g_strdup_printf(_(\"Can't find a conference URI on this page:\\n\\n%s\"),\n\t\t\t\t\t\t\turi);\n\n\t\t\t\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t  _(\"Failed to join the conference\"),\n\t\t\t\t\t\t\t  error);\n\t\t\t\tg_free(error);\n\t\t\t}\n\n\t\t\tg_free(launcher_url);\n\t\t}\n\t}\n\n\tg_free(uri);\n}\n\nstatic gboolean sipe_conf_check_for_lync_url(struct sipe_core_private *sipe_private,\n\t\t\t\t\t     gchar *uri)\n{\n\tstruct sipe_http_request *request;\n\n\tif (!(g_str_has_prefix(uri, \"https://\") ||\n\t      g_str_has_prefix(uri, \"http://\")))\n\t\treturn(FALSE);\n\n\t/* URL points to a HTML page with the conference focus URI */\n\trequest = sipe_http_request_get(sipe_private,\n\t\t\t\t\turi,\n\t\t\t\t\tNULL,\n\t\t\t\t\tsipe_conf_lync_url_cb,\n\t\t\t\t\turi);\n\n\tif (request) {\n\t\tsipe_http_request_ready(request);\n\t\treturn(TRUE);\n\t}\n\n\treturn(FALSE);\n}\n\nstatic void sipe_conf_uri_error(struct sipe_core_private *sipe_private,\n\t\t\t\tconst gchar *uri)\n{\n\tgchar *error = g_strdup_printf(_(\"\\\"%s\\\" is not a valid conference URI\"),\n\t\t\t\t       uri ? uri : \"\");\n\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t  _(\"Failed to join the conference\"),\n\t\t\t\t  error);\n\tg_free(error);\n}\n\nvoid sipe_core_conf_create(struct sipe_core_public *sipe_public,\n\t\t\t   const gchar *uri,\n\t\t\t   const gchar *organizer,\n\t\t\t   const gchar *meeting_id)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\n\t/* SIP URI or HTTP URL */\n\tif (uri) {\n\t\tgchar *uri_ue = sipe_utils_uri_unescape(uri);\n\n\t\tSIPE_DEBUG_INFO(\"sipe_core_conf_create: URI '%s' unescaped '%s'\",\n\t\t\t\turi,\n\t\t\t\turi_ue ? uri_ue : \"<UNDEFINED>\");\n\n\t\t/* takes ownership of \"uri_ue\" if successful */\n\t\tif (!sipe_conf_check_for_lync_url(sipe_private, uri_ue)) {\n\t\t\tgchar *focus_uri = parse_ocs_focus_uri(uri_ue);\n\n\t\t\tif (focus_uri) {\n\t\t\t\tsipe_conf_create(sipe_private, NULL, focus_uri);\n\t\t\t\tg_free(focus_uri);\n\t\t\t} else\n\t\t\t\tsipe_conf_uri_error(sipe_private, uri);\n\n\t\t\tg_free(uri_ue);\n\t\t}\n\n\t/* Organizer email and meeting ID */\n\t} else if (organizer && meeting_id) {\n\t\tgchar *tmp = g_strdup_printf(\"sip:%s;gruu;opaque=app:conf:focus:id:%s\",\n\t\t\t\t\t     organizer, meeting_id);\n\t\tgchar *focus_uri = parse_ocs_focus_uri(tmp);\n\n\t\tSIPE_DEBUG_INFO(\"sipe_core_conf_create: organizer '%s' meeting ID '%s'\",\n\t\t\t\torganizer,\n\t\t\t\tmeeting_id);\n\n\t\tif (focus_uri) {\n\t\t\tsipe_conf_create(sipe_private, NULL, focus_uri);\n\t\t\tg_free(focus_uri);\n\t\t} else\n\t\t\tsipe_conf_uri_error(sipe_private, tmp);\n\t\tg_free(tmp);\n\n\t} else {\n\t\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t  _(\"Failed to join the conference\"),\n\t\t\t\t\t  _(\"Incomplete conference information provided\"));\n\t}\n}\n\n/** Create new session with Focus URI */\nstruct sip_session *\nsipe_conf_create(struct sipe_core_private *sipe_private,\n\t\t struct sipe_chat_session *chat_session,\n\t\t const gchar *focus_uri)\n{\n\t/* addUser request to the focus.\n\t *\n\t * focus_URI, from, endpoint_GUID\n\t */\n\tstatic const gchar CCCP_ADD_USER[] =\n\t\t\"<addUser>\"\n\t\t\t\"<conferenceKeys confEntity=\\\"%s\\\"/>\"\n\t\t\t\"<ci:user xmlns:ci=\\\"urn:ietf:params:xml:ns:conference-info\\\" entity=\\\"%s\\\">\"\n\t\t\t\t\"<ci:roles>\"\n\t\t\t\t\t\"<ci:entry>attendee</ci:entry>\"\n\t\t\t\t\"</ci:roles>\"\n\t\t\t\t\"<ci:endpoint entity=\\\"{%s}\\\" \"\n\t\t\t\t\t      \"xmlns:msci=\\\"http://schemas.microsoft.com/rtc/2005/08/confinfoextensions\\\"/>\"\n\t\t\t\"</ci:user>\"\n\t\t\"</addUser>\";\n\n\tgchar *self;\n\tstruct sip_session *session = sipe_session_add_chat(sipe_private,\n\t\t\t\t\t\t\t    chat_session,\n\t\t\t\t\t\t\t    FALSE,\n\t\t\t\t\t\t\t    focus_uri);\n\n\tsession->focus_dialog = g_new0(struct sip_dialog, 1);\n\tsession->focus_dialog->callid = gencallid();\n\tsession->focus_dialog->with = g_strdup(session->chat_session->id);\n\tsession->focus_dialog->endpoint_GUID = rand_guid();\n\tsession->focus_dialog->ourtag = gentag();\n\n\tself = sip_uri_self(sipe_private);\n\tsession->focus_dialog->outgoing_invite =\n\t\tcccp_request(sipe_private, \"INVITE\",\n\t\t\t     session->focus_dialog->with, session->focus_dialog,\n\t\t\t     process_invite_conf_focus_response,\n\t\t\t     CCCP_ADD_USER,\n\t\t\t     session->focus_dialog->with, self,\n\t\t\t     session->focus_dialog->endpoint_GUID);\n\n\t/* Rejoin existing session? */\n\tif (chat_session) {\n\t\tSIPE_DEBUG_INFO(\"sipe_conf_create: rejoin '%s' (%s)\",\n\t\t\t\tchat_session->title,\n\t\t\t\tchat_session->id);\n\t\tsipe_backend_chat_rejoin(SIPE_CORE_PUBLIC,\n\t\t\t\t\t chat_session->backend,\n\t\t\t\t\t self,\n\t\t\t\t\t chat_session->title);\n\t}\n\tg_free(self);\n\n\treturn(session);\n}\n\n/** Modify User Role */\nvoid\nsipe_conf_modify_user_role(struct sipe_core_private *sipe_private,\n\t\t\t   struct sip_session *session,\n\t\t\t   const gchar* who)\n{\n\t/* modifyUserRoles request to the focus. Makes user a leader.\n\t *\n\t * focus_uri (%s)\n\t * who (%s)\n\t */\n\tstatic const gchar CCCP_MODIFY_USER_ROLES[] =\n\t\t\"<modifyUserRoles>\"\n\t\t\t\"<userKeys confEntity=\\\"%s\\\" userEntity=\\\"%s\\\"/>\"\n\t\t\t\"<user-roles xmlns=\\\"urn:ietf:params:xml:ns:conference-info\\\">\"\n\t\t\t\t\"<entry>presenter</entry>\"\n\t\t\t\"</user-roles>\"\n\t\t\"</modifyUserRoles>\";\n\n\tif (!session->focus_dialog || !session->focus_dialog->is_established) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_conf_modify_user_role: no dialog with focus, exiting.\");\n\t\treturn;\n\t}\n\n\tcccp_request(sipe_private, \"INFO\", session->focus_dialog->with,\n\t\t     session->focus_dialog, NULL,\n\t\t     CCCP_MODIFY_USER_ROLES,\n\t\t     session->focus_dialog->with, who);\n}\n\n/**\n * Check conference lock status\n */\nsipe_chat_lock_status sipe_core_chat_lock_status(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t struct sipe_chat_session *chat_session)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tsipe_chat_lock_status status = SIPE_CHAT_LOCK_STATUS_NOT_ALLOWED;\n\n\tif (chat_session &&\n\t    (chat_session->type == SIPE_CHAT_TYPE_CONFERENCE)) {\n\t\tstruct sip_session *session = sipe_session_find_chat(sipe_private,\n\t\t\t\t\t\t\t\t     chat_session);\n\t\tif (session) {\n\t\t\tgchar *self = sip_uri_self(sipe_private);\n\n\t\t\t/* Only operators are allowed to change the lock status */\n\t\t\tif (sipe_backend_chat_is_operator(chat_session->backend, self)) {\n\t\t\t\tstatus = session->locked ?\n\t\t\t\t\tSIPE_CHAT_LOCK_STATUS_LOCKED :\n\t\t\t\t\tSIPE_CHAT_LOCK_STATUS_UNLOCKED;\n\t\t\t}\n\n\t\t\tg_free(self);\n\t\t}\n\t}\n\n\treturn(status);\n}\n\n/**\n * Modify Conference Lock\n * Sends request to Focus.\n * INFO method is a carrier of application/cccp+xml\n */\nvoid\nsipe_core_chat_modify_lock(struct sipe_core_public *sipe_public,\n\t\t\t   struct sipe_chat_session *chat_session,\n\t\t\t   const gboolean locked)\n{\n\t/* modifyConferenceLock request to the focus. Locks/unlocks conference.\n\t *\n\t * focus_uri (%s)\n\t * locked (%s) \"true\" or \"false\" values applicable\n\t */\n\tstatic const gchar CCCP_MODIFY_CONFERENCE_LOCK[] =\n\t\t\"<modifyConferenceLock>\"\n\t\t\t\"<conferenceKeys confEntity=\\\"%s\\\"/>\"\n\t\t\t\"<locked>%s</locked>\"\n\t\t\"</modifyConferenceLock>\";\n\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\n\tstruct sip_session *session = sipe_session_find_chat(sipe_private,\n\t\t\t\t\t\t\t     chat_session);\n\n\tif (!session) return;\n\tif (!session->focus_dialog || !session->focus_dialog->is_established) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_conf_modify_conference_lock: no dialog with focus, exiting.\");\n\t\treturn;\n\t}\n\n\tcccp_request(sipe_private, \"INFO\", session->focus_dialog->with,\n\t\t     session->focus_dialog, NULL,\n\t\t     CCCP_MODIFY_CONFERENCE_LOCK,\n\t\t     session->focus_dialog->with,\n\t\t     locked ? \"true\" : \"false\");\n}\n\n/** Modify Delete User */\nvoid\nsipe_conf_delete_user(struct sipe_core_private *sipe_private,\n\t\t      struct sip_session *session,\n\t\t      const gchar* who)\n{\n\t/* deleteUser request to the focus. Removes a user from the conference.\n\t *\n\t * focus_uri (%s)\n\t * who (%s)\n\t */\n\tstatic const gchar CCCP_DELETE_USER[] =\n\t\t\"<deleteUser>\"\n\t\t\t\"<userKeys confEntity=\\\"%s\\\" userEntity=\\\"%s\\\"/>\"\n\t\t\"</deleteUser>\";\n\n\tif (!session->focus_dialog || !session->focus_dialog->is_established) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_conf_delete_user: no dialog with focus, exiting.\");\n\t\treturn;\n\t}\n\n\tcccp_request(sipe_private, \"INFO\", session->focus_dialog->with,\n\t\t     session->focus_dialog, NULL,\n\t\t     CCCP_DELETE_USER,\n\t\t     session->focus_dialog->with, who);\n}\n\nvoid\nsipe_conf_announce_audio_mute_state(struct sipe_core_private *sipe_private,\n\t\t\t\t    struct sip_session *session,\n\t\t\t\t    gboolean is_muted)\n{\n\t// See [MS-CONFAV] 3.2.5.4 and 4.3\n\tstatic const gchar CCCP_MODIFY_ENDPOINT_MEDIA[] =\n\t\t\"<modifyEndpointMedia mscp:mcuUri=\\\"%s\\\"\"\n\t\t\" xmlns:mscp=\\\"http://schemas.microsoft.com/rtc/2005/08/cccpextensions\\\">\"\n\t\t\t\"<mediaKeys confEntity=\\\"%s\\\" userEntity=\\\"%s\\\"\"\n\t\t\t\" endpointEntity=\\\"%s\\\" mediaId=\\\"%d\\\"/>\"\n\t\t\t\"<ci:media\"\n\t\t\t\" xmlns:ci=\\\"urn:ietf:params:xml:ns:conference-info\\\" id=\\\"%d\\\">\"\n\t\t\t\t\"<ci:type>audio</ci:type>\"\n\t\t\t\t\"<ci:status>%s</ci:status>\"\n\t\t\t\t\"<media-ingress-filter\"\n\t\t\t\t\" xmlns=\\\"http://schemas.microsoft.com/rtc/2005/08/confinfoextensions\\\">\"\n\t\t\t\t\t\"%s\"\n\t\t\t\t\"</media-ingress-filter>\"\n\t\t\t\"</ci:media>\"\n\t\t\"</modifyEndpointMedia>\";\n\n\tgchar *mcu_uri = sipe_conf_build_uri(session->focus_dialog->with,\n\t\t\t\t\t     \"audio-video\");\n\tgchar *self = sip_uri_self(sipe_private);\n\n\tcccp_request(sipe_private, \"INFO\", session->focus_dialog->with,\n\t\t     session->focus_dialog, NULL,\n\t\t     CCCP_MODIFY_ENDPOINT_MEDIA,\n\t\t     mcu_uri, session->focus_dialog->with, self,\n\t\t     session->audio_video_entity,\n\t\t     session->audio_media_id, session->audio_media_id,\n\t\t     is_muted ? \"recvonly\" : \"sendrecv\",\n\t\t     is_muted ? \"block\" : \"unblock\");\n\n\tg_free(mcu_uri);\n\tg_free(self);\n}\n\n/** Invite counterparty to join conference callback */\nstatic gboolean\nprocess_invite_conf_response(struct sipe_core_private *sipe_private,\n\t\t\t     struct sipmsg *msg,\n\t\t\t     SIPE_UNUSED_PARAMETER struct transaction *trans)\n{\n\tstruct sip_dialog *dialog = g_new0(struct sip_dialog, 1);\n\n\tdialog->callid = g_strdup(sipmsg_find_call_id_header(msg));\n\tdialog->cseq = sipmsg_parse_cseq(msg);\n\tdialog->with = sipmsg_parse_to_address(msg);\n\tsipe_dialog_parse(dialog, msg, TRUE);\n\n\tif (msg->response >= 200) {\n\t\t/* send ACK to counterparty */\n\t\tdialog->cseq--;\n\t\tsip_transport_ack(sipe_private, dialog);\n\t\tdialog->outgoing_invite = NULL;\n\t\tdialog->is_established = TRUE;\n\t}\n\n\tif (msg->response >= 400) {\n\t\tSIPE_DEBUG_INFO(\"process_invite_conf_response: INVITE response is not 200. Failed to invite %s.\", dialog->with);\n\t\t/* @TODO notify user of failure to invite counterparty */\n\t\tsipe_dialog_free(dialog);\n\t\treturn FALSE;\n\t}\n\n\tif (msg->response >= 200) {\n\t\tstruct sip_session *session = sipe_session_find_im(sipe_private, dialog->with);\n\t\tstruct sip_dialog *im_dialog = sipe_dialog_find(session, dialog->with);\n\n\t\t/* close IM session to counterparty */\n\t\tif (im_dialog) {\n\t\t\tsip_transport_bye(sipe_private, im_dialog);\n\t\t\tsipe_dialog_remove(session, dialog->with);\n\t\t}\n\t}\n\n\tsipe_dialog_free(dialog);\n\treturn TRUE;\n}\n\n/**\n * Invites counterparty to join conference.\n */\nvoid\nsipe_invite_conf(struct sipe_core_private *sipe_private,\n\t\t struct sip_session *session,\n\t\t const gchar* who)\n{\n\tgchar *hdr;\n\tgchar *contact;\n\tgchar *body;\n\tstruct sip_dialog *dialog = NULL;\n\n\t/* It will be short lived special dialog.\n\t * Will not be stored in session.\n\t */\n\tdialog = g_new0(struct sip_dialog, 1);\n\tdialog->callid = gencallid();\n\tdialog->with = g_strdup(who);\n\tdialog->ourtag = gentag();\n\n\tcontact = get_contact(sipe_private);\n\thdr = g_strdup_printf(\n\t\t\"Supported: ms-sender\\r\\n\"\n\t\t\"Contact: %s\\r\\n\"\n\t\t\"Content-Type: application/ms-conf-invite+xml\\r\\n\",\n\t\tcontact);\n\tg_free(contact);\n\n\tbody = g_strdup_printf(\n\t\tSIPE_SEND_CONF_INVITE,\n\t\tsession->chat_session->id,\n\t\tsession->subject ? session->subject : \"\"\n\t\t);\n\n\tsip_transport_invite(sipe_private,\n\t\t\t     hdr,\n\t\t\t     body,\n\t\t\t     dialog,\n\t\t\t     process_invite_conf_response);\n\n\tsipe_dialog_free(dialog);\n\tg_free(body);\n\tg_free(hdr);\n}\n\n/** Create conference callback */\nstatic gboolean\nprocess_conf_add_response(struct sipe_core_private *sipe_private,\n\t\t\t  struct sipmsg *msg,\n\t\t\t  struct transaction *trans)\n{\n\tif (msg->response >= 400) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_conf_add_response: SERVICE response is not 200. Failed to create conference.\");\n\t\t/* @TODO notify user of failure to create conference */\n\t\treturn FALSE;\n\t}\n\tif (msg->response == 200) {\n\t\tsipe_xml *xn_response = sipe_xml_parse(msg->body, msg->bodylen);\n\t\tif (sipe_strequal(\"success\", sipe_xml_attribute(xn_response, \"code\")))\n\t\t{\n\t\t\tgchar *who = trans->payload->data;\n\t\t\tconst sipe_xml *xn_conference_info = sipe_xml_child(xn_response, \"addConference/conference-info\");\n\t\t\tstruct sip_session *session = sipe_conf_create(sipe_private,\n\t\t\t\t\t\t\t\t       NULL,\n\t\t\t\t\t\t\t\t       sipe_xml_attribute(xn_conference_info,\n\t\t\t\t\t\t\t\t\t\t\t  \"entity\"));\n\n\t\t\tSIPE_DEBUG_INFO(\"process_conf_add_response: session->focus_uri=%s\",\n\t\t\t\t\tsession->chat_session->id);\n\n\t\t\tsession->pending_invite_queue = sipe_utils_slist_insert_unique_sorted(session->pending_invite_queue,\n\t\t\t\t\t\t\t\t\t\t\t      g_strdup(who),\n\t\t\t\t\t\t\t\t\t\t\t      (GCompareFunc)strcmp,\n\t\t\t\t\t\t\t\t\t\t\t      g_free);\n\t\t}\n\t\tsipe_xml_free(xn_response);\n\t}\n\n\treturn TRUE;\n}\n\n/**\n * Creates conference.\n */\nvoid\nsipe_conf_add(struct sipe_core_private *sipe_private,\n\t      const gchar* who)\n{\n\tgchar *conference_id;\n\tstruct transaction *trans;\n\ttime_t expiry = time(NULL) + 7*60*60; /* 7 hours */\n\tchar *expiry_time;\n\n\t/* addConference request to the focus factory.\n\t *\n\t * conference_id\t(%s) Ex.: 8386E6AEAAA41E4AA6627BA76D43B6D1\n\t * expiry_time\t\t(%s) Ex.: 2009-07-13T17:57:09Z\n\t * conference_view\t(%s) Ex.: <msci:entity-view entity=\"chat\"/>\n\t */\n\tstatic const gchar CCCP_ADD_CONFERENCE[] =\n\t\t\"<addConference>\"\n\t\t\t\"<ci:conference-info xmlns:ci=\\\"urn:ietf:params:xml:ns:conference-info\\\" \"\n\t\t\t\t\t     \"entity=\\\"\\\" \"\n\t\t\t\t\t     \"xmlns:msci=\\\"http://schemas.microsoft.com/rtc/2005/08/confinfoextensions\\\">\"\n\t\t\t\t\"<ci:conference-description>\"\n\t\t\t\t\t\"<ci:subject/>\"\n\t\t\t\t\t\"<msci:conference-id>%s</msci:conference-id>\"\n\t\t\t\t\t\"<msci:expiry-time>%s</msci:expiry-time>\"\n\t\t\t\t\t\"<msci:admission-policy>openAuthenticated</msci:admission-policy>\"\n\t\t\t\t\"</ci:conference-description>\"\n\t\t\t\t\"<msci:conference-view>%s</msci:conference-view>\"\n\t\t\t\"</ci:conference-info>\"\n\t\t\"</addConference>\";\n\n\tstatic const gchar *DESIRED_MCU_TYPES[] = {\n\t\t\"chat\",\n#ifdef HAVE_VV\n\t\t\"audio-video\",\n#endif\n#ifdef HAVE_APPSHARE\n\t\t\"applicationsharing\",\n#endif\n\t\tNULL\n\t};\n\n\tGString *conference_view = g_string_new(\"\");\n\tconst gchar **type;\n\n\tfor (type = DESIRED_MCU_TYPES; *type; ++type ) {\n\t\tif (sipe_conf_supports_mcu_type(sipe_private, *type)) {\n\t\t\tg_string_append(conference_view, \"<msci:entity-view entity=\\\"\");\n\t\t\tg_string_append(conference_view, *type);\n\t\t\tg_string_append(conference_view, \"\\\"/>\");\n\t\t}\n\t}\n\n\texpiry_time = sipe_utils_time_to_str(expiry);\n\tconference_id = genconfid();\n\ttrans = cccp_request(sipe_private, \"SERVICE\", sipe_private->focus_factory_uri,\n\t\t\t     NULL, process_conf_add_response,\n\t\t\t     CCCP_ADD_CONFERENCE,\n\t\t\t     conference_id, expiry_time, conference_view->str);\n\tg_free(conference_id);\n\tg_free(expiry_time);\n\tg_string_free(conference_view, TRUE);\n\n\tif (trans) {\n\t\tstruct transaction_payload *payload = g_new0(struct transaction_payload, 1);\n\n\t\tpayload->destroy = g_free;\n\t\tpayload->data = g_strdup(who);\n\t\ttrans->payload = payload;\n\t}\n}\n\nstatic void\naccept_incoming_invite_conf(struct sipe_core_private *sipe_private,\n\t\t\t    gchar *focus_uri,\n\t\t\t    gboolean audio,\n\t\t\t    struct sipmsg *msg)\n{\n\tstruct sip_session *session;\n\n\t/* acknowledge invite */\n\tsipmsg_update_to_header_tag(msg);\n\tsip_transport_response(sipe_private, msg, 200, \"OK\", NULL);\n\n\t/* add self to conf */\n\tsession = sipe_conf_create(sipe_private, NULL, focus_uri);\n\tsession->is_call = audio;\n}\n\nstruct conf_accept_ctx {\n\tgchar *focus_uri;\n\tstruct sipmsg *msg;\n\tstruct sipe_user_ask_ctx *ask_ctx;\n\n\tSipeUserAskCb accept_cb;\n\tSipeUserAskCb decline_cb;\n\n\tgpointer user_data;\n};\n\nstatic void\nconf_accept_ctx_free(struct conf_accept_ctx *ctx)\n{\n\tg_return_if_fail(ctx != NULL);\n\n\tsipmsg_free(ctx->msg);\n\tg_free(ctx->focus_uri);\n\tg_free(ctx);\n}\n\nstatic void\nconf_accept_cb(struct sipe_core_private *sipe_private, struct conf_accept_ctx *ctx)\n{\n\taccept_incoming_invite_conf(sipe_private, ctx->focus_uri, TRUE, ctx->msg);\n}\n\nstatic void\nconf_decline_cb(struct sipe_core_private *sipe_private, struct conf_accept_ctx *ctx)\n{\n\tsip_transport_response(sipe_private,\n\t\t\t       ctx->msg,\n\t\t\t       603, \"Decline\", NULL);\n}\n\nvoid\nsipe_conf_cancel_unaccepted(struct sipe_core_private *sipe_private,\n\t\t\t    struct sipmsg *msg)\n{\n\tconst gchar *callid1 = msg ? sipmsg_find_call_id_header(msg) : NULL;\n\tGSList *it = sipe_private->sessions_to_accept;\n\twhile (it) {\n\t\tstruct conf_accept_ctx *ctx = it->data;\n\t\tconst gchar *callid2 = NULL;\n\n\t\tif (msg && ctx->msg)\n\t\t\tcallid2 = sipmsg_find_call_id_header(ctx->msg);\n\n\t\tif (sipe_strequal(callid1, callid2)) {\n\t\t\tGSList *tmp;\n\n\t\t\tif (ctx->msg)\n\t\t\t\tsip_transport_response(sipe_private, ctx->msg,\n\t\t\t\t\t\t       487, \"Request Terminated\", NULL);\n\n\t\t\tif (msg)\n\t\t\t\tsip_transport_response(sipe_private, msg, 200, \"OK\", NULL);\n\n\t\t\tsipe_user_close_ask(ctx->ask_ctx);\n\t\t\tconf_accept_ctx_free(ctx);\n\n\t\t\ttmp = it;\n\t\t\tit = it->next;\n\n\t\t\tsipe_private->sessions_to_accept =\n\t\t\t\tg_slist_delete_link(sipe_private->sessions_to_accept, tmp);\n\n\t\t\tif (callid1)\n\t\t\t\tbreak;\n\t\t} else\n\t\t\tit = it->next;\n\t}\n}\n\nstatic void\naccept_invitation_cb(struct sipe_core_private *sipe_private, gpointer data)\n{\n\tstruct conf_accept_ctx *ctx = data;\n\n\tsipe_private->sessions_to_accept =\n\t\t\tg_slist_remove(sipe_private->sessions_to_accept, ctx);\n\n\tif (ctx->accept_cb) {\n\t\tctx->accept_cb(sipe_private, ctx);\n\t}\n\n\tconf_accept_ctx_free(ctx);\n}\n\nstatic void\ndecline_invitation_cb(struct sipe_core_private *sipe_private, gpointer data)\n{\n\tstruct conf_accept_ctx *ctx = data;\n\n\tsipe_private->sessions_to_accept =\n\t\t\tg_slist_remove(sipe_private->sessions_to_accept, ctx);\n\n\tif (ctx->decline_cb) {\n\t\tctx->decline_cb(sipe_private, ctx);\n\t}\n\n\tconf_accept_ctx_free(ctx);\n}\n\nstatic void\nask_accept_invitation(struct sipe_core_private *sipe_private,\n\t\t      const gchar *focus_uri,\n\t\t      const gchar *question,\n\t\t      struct sipmsg *msg,\n\t\t      SipeUserAskCb accept_cb,\n\t\t      SipeUserAskCb decline_cb,\n\t\t      gpointer user_data)\n{\n\tgchar **parts;\n\tgchar *alias;\n\tgchar *question_str;\n\tstruct conf_accept_ctx *ctx;\n\n\tparts = g_strsplit(focus_uri, \";\", 2);\n\talias = sipe_buddy_get_alias(sipe_private, parts[0]);\n\n\tquestion_str = g_strdup_printf(\"%s %s\", alias ? alias : parts[0], question);\n\n\tg_free(alias);\n\tg_strfreev(parts);\n\n\tctx = g_new0(struct conf_accept_ctx, 1);\n\tsipe_private->sessions_to_accept =\n\t\t\tg_slist_append(sipe_private->sessions_to_accept, ctx);\n\n\tctx->focus_uri = g_strdup(focus_uri);\n\tctx->msg = msg ? sipmsg_copy(msg) : NULL;\n\tctx->accept_cb = accept_cb;\n\tctx->decline_cb = decline_cb;\n\tctx->user_data = user_data;\n\tctx->ask_ctx = sipe_user_ask(sipe_private, question_str,\n\t\t\t\t     _(\"Accept\"), accept_invitation_cb,\n\t\t\t\t     _(\"Decline\"), decline_invitation_cb,\n\t\t\t\t     ctx);\n\n\tg_free(question_str);\n}\n\nstatic void\nask_accept_voice_conference(struct sipe_core_private *sipe_private,\n\t\t\t    const gchar *focus_uri,\n\t\t\t    struct sipmsg *msg,\n\t\t\t    SipeUserAskCb accept_cb,\n\t\t\t    SipeUserAskCb decline_cb)\n{\n\tgchar *question;\n\tconst gchar *novv_note;\n\n#ifdef HAVE_VV\n\tnovv_note = \"\";\n#else\n\tnovv_note = _(\"\\n\\nAs this client was not compiled with voice call \"\n\t\t      \"support, if you accept, you will be able to contact \"\n\t\t      \"the other participants only via IM session.\");\n#endif\n\n\tquestion = g_strdup_printf(_(\"wants to invite you \"\n\t\t\t\t     \"to a conference call%s\"), novv_note);\n\n\task_accept_invitation(sipe_private, focus_uri, question, msg,\n\t\t\t      accept_cb, decline_cb, NULL);\n\n\tg_free(question);\n}\n\nvoid\nprocess_incoming_invite_conf(struct sipe_core_private *sipe_private,\n\t\t\t     struct sipmsg *msg)\n{\n\tsipe_xml *xn_conferencing = sipe_xml_parse(msg->body, msg->bodylen);\n\tconst sipe_xml *xn_focus_uri = sipe_xml_child(xn_conferencing, \"focus-uri\");\n\tconst sipe_xml *xn_audio = sipe_xml_child(xn_conferencing, \"audio\");\n\tgchar *focus_uri = sipe_xml_data(xn_focus_uri);\n\tgboolean audio = sipe_strequal(sipe_xml_attribute(xn_audio, \"available\"), \"true\");\n\n\tsipe_xml_free(xn_conferencing);\n\n\tSIPE_DEBUG_INFO(\"We have received invitation to Conference. Focus URI=%s\", focus_uri);\n\n\tif (audio) {\n\t\tsip_transport_response(sipe_private, msg, 180, \"Ringing\", NULL);\n\t\task_accept_voice_conference(sipe_private, focus_uri, msg,\n\t\t\t\t\t    (SipeUserAskCb) conf_accept_cb,\n\t\t\t\t\t    (SipeUserAskCb) conf_decline_cb);\n\n\t} else {\n\t\taccept_incoming_invite_conf(sipe_private, focus_uri, FALSE, msg);\n\t}\n\n\tg_free(focus_uri);\n}\n\n#ifdef HAVE_VV\n\nstatic void\nprocess_conference_av_endpoint(const sipe_xml *endpoint,\n\t\t\t       const gchar *user_uri,\n\t\t\t       const gchar *self_uri,\n\t\t\t       struct sip_session *session)\n{\n\tconst sipe_xml *media;\n\n\tif (sipe_strequal(user_uri, self_uri)) {\n\t\tconst gchar *new_entity = sipe_xml_attribute(endpoint, \"entity\");\n\n\t\tif (!sipe_strequal(session->audio_video_entity, new_entity)) {\n\t\t\tg_free(session->audio_video_entity);\n\t\t\tsession->audio_video_entity = g_strdup(new_entity);\n\t\t}\n\t}\n\n\tmedia = sipe_xml_child(endpoint, \"media\");\n\tfor (; media; media = sipe_xml_twin(media)) {\n\t\tgchar *type = sipe_xml_data(sipe_xml_child(media, \"type\"));\n\n\t\tif (sipe_strequal(type, \"audio\") && sipe_strequal(user_uri, self_uri)) {\n\t\t\tsession->audio_media_id = sipe_xml_int_attribute(media, \"id\", 0);\n\t\t} else if (sipe_strequal(type, \"video\") && session->video_media_source_id == 0) {\n\t\t\tconst sipe_xml *child = sipe_xml_child(media, \"media-source-id\");\n\t\t\tconst gchar *data = sipe_xml_data(child);\n\n\t\t\tif (data) {\n\t\t\t\tsession->video_media_source_id = atoi(data);\n\t\t\t}\n\t\t}\n\n\t\tg_free(type);\n\t}\n}\n\nstatic void\ncall_accept_cb(struct sipe_core_private *sipe_private, struct conf_accept_ctx *ctx)\n{\n\tstruct sip_session *session;\n\tsession = sipe_session_find_conference(sipe_private, ctx->focus_uri);\n\n\tif (session) {\n\t\tsipe_core_media_connect_conference(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t   session->chat_session,\n\t\t\t\t\t\t   FALSE);\n\t}\n}\n\n#ifdef HAVE_APPSHARE\nsipe_appshare_role\nsipe_core_conf_get_appshare_role(struct sipe_core_public *sipe_public,\n\t\t\t\t struct sipe_chat_session *chat_session)\n{\n\tif (chat_session) {\n\t\tgchar *mcu_uri;\n\t\tstruct sipe_media_call *call;\n\n\t\tmcu_uri = sipe_conf_build_uri(chat_session->id, \"applicationsharing\");\n\n\t\tcall = sipe_media_call_find(SIPE_CORE_PRIVATE, mcu_uri);\n\n\t\tg_free(mcu_uri);\n\n\t\tif (call) {\n\t\t\treturn sipe_appshare_get_role(call);\n\t\t}\n\t}\n\n\treturn SIPE_APPSHARE_ROLE_NONE;\n}\n\nstatic gboolean\nprocess_conference_appshare_endpoint(const sipe_xml *endpoint)\n{\n\tgboolean presentation_added = FALSE;\n\tconst sipe_xml *media;\n\n\tfor (media = sipe_xml_child(endpoint, \"media\");\n\t     media && !presentation_added;\n\t     media = sipe_xml_twin(media)) {\n\t\tgchar *type;\n\t\tgchar *media_state;\n\t\tgchar *status;\n\n\t\ttype = sipe_xml_data(sipe_xml_child(media, \"type\"));\n\t\tmedia_state = sipe_xml_data(sipe_xml_child(media, \"media-state\"));\n\t\tstatus = sipe_xml_data(sipe_xml_child(media, \"status\"));\n\n\t\tif (sipe_strequal(type, \"applicationsharing\") &&\n\t\t    sipe_strequal(media_state, \"connected\") &&\n\t\t    sipe_strequal(status, \"sendonly\")) {\n\t\t\tpresentation_added = TRUE;\n\t\t}\n\n\t\tg_free(type);\n\t\tg_free(media_state);\n\t\tg_free(status);\n\t}\n\n\treturn(presentation_added);\n}\n#endif // HAVE_APPSHARE\n#endif // HAVE_VV\n\nvoid\nsipe_process_conference(struct sipe_core_private *sipe_private,\n\t\t\tstruct sipmsg *msg)\n{\n\tsipe_xml *xn_conference_info;\n\tconst sipe_xml *node;\n\tconst sipe_xml *xn_subject;\n\tconst gchar *focus_uri;\n\tstruct sip_session *session;\n\tgboolean just_joined = FALSE;\n#ifdef HAVE_VV\n\tgboolean audio_was_added = FALSE;\n#ifdef HAVE_APPSHARE\n\tgboolean presentation_was_added = FALSE;\n#endif\n#endif // HAVE_VV\n\n\tif (msg->response != 0 && msg->response != 200) return;\n\n\tif (msg->bodylen == 0 || msg->body == NULL || !sipe_strequal(sipmsg_find_event_header(msg), \"conference\")) return;\n\n\txn_conference_info = sipe_xml_parse(msg->body, msg->bodylen);\n\tif (!xn_conference_info) return;\n\n\tfocus_uri = sipe_xml_attribute(xn_conference_info, \"entity\");\n\tsession = sipe_session_find_conference(sipe_private, focus_uri);\n\n\tif (!session) {\n\t\tSIPE_DEBUG_INFO(\"sipe_process_conference: unable to find conf session with focus=%s\", focus_uri);\n\t\treturn;\n\t}\n\n\tif (!session->chat_session->backend) {\n\t\tgchar *self = sip_uri_self(sipe_private);\n\n\t\t/* create chat */\n\t\tsession->chat_session->backend = sipe_backend_chat_create(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\t  session->chat_session,\n\t\t\t\t\t\t\t\t\t  session->chat_session->title,\n\t\t\t\t\t\t\t\t\t  self);\n\t\tjust_joined = TRUE;\n\t\t/* @TODO ask for full state (re-subscribe) if it was a partial one -\n\t\t * this is to obtain full list of conference participants.\n\t\t */\n\t\t g_free(self);\n\t}\n\n\t/* subject */\n\tif ((xn_subject = sipe_xml_child(xn_conference_info, \"conference-description/subject\"))) {\n\t\tg_free(session->subject);\n\t\tsession->subject = sipe_xml_data(xn_subject);\n\t\tsipe_backend_chat_topic(session->chat_session->backend, session->subject);\n\t\tSIPE_DEBUG_INFO(\"sipe_process_conference: subject=%s\", session->subject ? session->subject : \"\");\n\t}\n\n\t/* IM MCU URI */\n\tif (!session->im_mcu_uri) {\n\t\tfor (node = sipe_xml_child(xn_conference_info, \"conference-description/conf-uris/entry\");\n\t\t     node;\n\t\t     node = sipe_xml_twin(node))\n\t\t{\n\t\t\tgchar *purpose = sipe_xml_data(sipe_xml_child(node, \"purpose\"));\n\n\t\t\tif (sipe_strequal(\"chat\", purpose)) {\n\t\t\t\tg_free(purpose);\n\t\t\t\tsession->im_mcu_uri = sipe_xml_data(sipe_xml_child(node, \"uri\"));\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_process_conference: im_mcu_uri=%s\", session->im_mcu_uri);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tg_free(purpose);\n\t\t}\n\t}\n\n\t/* organizer */\n\tif (!session->chat_session->organizer) {\n\t\tnode = sipe_xml_child(xn_conference_info, \"conference-description/organizer/display-name\");\n\t\tif (node) {\n\t\t\tsession->chat_session->organizer = sipe_xml_data(node);\n\t\t}\n\t}\n\n\t/* join URL */\n\tif (!session->chat_session->join_url) {\n\t\tnode = sipe_xml_child(xn_conference_info, \"conference-description/join-url\");\n\t\tif (node) {\n\t\t\tsession->chat_session->join_url = sipe_xml_data(node);\n\t\t}\n\t}\n\n\t/* dial-in conference id */\n\tif (!session->chat_session->dial_in_conf_id) {\n\t\tnode = sipe_xml_child(xn_conference_info, \"conference-description/pstn-access/id\");\n\t\tif (node) {\n\t\t\tsession->chat_session->dial_in_conf_id = sipe_xml_data(node);\n\t\t}\n\t}\n\n\t/* users */\n\tfor (node = sipe_xml_child(xn_conference_info, \"users/user\"); node; node = sipe_xml_twin(node)) {\n\t\tconst gchar *user_uri = sipe_xml_attribute(node, \"entity\");\n\t\tconst gchar *state = sipe_xml_attribute(node, \"state\");\n\t\tgchar *role = sipe_xml_data(sipe_xml_child(node, \"roles/entry\"));\n\t\tgboolean is_operator = sipe_strequal(role, \"presenter\");\n\t\tgboolean is_in_im_mcu = FALSE;\n\t\tgchar *self = sip_uri_self(sipe_private);\n\n\t\tif (sipe_strequal(\"deleted\", state)) {\n\t\t\tif (sipe_backend_chat_find(session->chat_session->backend, user_uri)) {\n\t\t\t\tsipe_backend_chat_remove(session->chat_session->backend,\n\t\t\t\t\t\t\t user_uri);\n\t\t\t}\n\t\t} else {\n\t\t\t/* endpoints */\n\t\t\tconst sipe_xml *endpoint;\n\t\t\tfor (endpoint = sipe_xml_child(node, \"endpoint\"); endpoint; endpoint = sipe_xml_twin(endpoint)) {\n\t\t\t\tconst gchar *session_type;\n\t\t\t\tgchar *status = sipe_xml_data(sipe_xml_child(endpoint, \"status\"));\n\t\t\t\tgboolean connected = sipe_strequal(\"connected\", status);\n\t\t\t\tg_free(status);\n\n\t\t\t\tif (!connected)\n\t\t\t\t\tcontinue;\n\n\t\t\t\tsession_type = sipe_xml_attribute(endpoint, \"session-type\");\n\n\t\t\t\tif (sipe_strequal(\"chat\", session_type)) {\n\t\t\t\t\tis_in_im_mcu = TRUE;\n\t\t\t\t\tif (!sipe_backend_chat_find(session->chat_session->backend, user_uri)) {\n\t\t\t\t\t\tsipe_backend_chat_add(session->chat_session->backend,\n\t\t\t\t\t\t\t\t      user_uri,\n\t\t\t\t\t\t\t\t      !just_joined && g_ascii_strcasecmp(user_uri, self));\n\t\t\t\t\t}\n\t\t\t\t\tif (is_operator) {\n\t\t\t\t\t\tsipe_backend_chat_operator(session->chat_session->backend,\n\t\t\t\t\t\t\t\t\t   user_uri);\n\t\t\t\t\t}\n\t\t\t\t} else if (sipe_strequal(\"audio-video\", session_type)) {\n#ifdef HAVE_VV\n\t\t\t\t\tif (!session->is_call)\n\t\t\t\t\t\taudio_was_added = TRUE;\n\t\t\t\t\tprocess_conference_av_endpoint(endpoint,\n\t\t\t\t\t\t\t\t       user_uri,\n\t\t\t\t\t\t\t\t       self,\n\t\t\t\t\t\t\t\t       session);\n#endif\n\t\t\t\t} else if (sipe_strequal(\"applicationsharing\", session_type)) {\n#ifdef HAVE_APPSHARE\n\t\t\t\t\tif (sipe_core_conf_get_appshare_role(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\t     session->chat_session) == SIPE_APPSHARE_ROLE_NONE &&\n\t\t\t\t\t    !sipe_strequal(user_uri, self)) {\n\t\t\t\t\t\tpresentation_was_added = process_conference_appshare_endpoint(endpoint);\n\t\t\t\t\t}\n#endif\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!is_in_im_mcu) {\n\t\t\t\tif (sipe_backend_chat_find(session->chat_session->backend, user_uri)) {\n\t\t\t\t\tsipe_backend_chat_remove(session->chat_session->backend,\n\t\t\t\t\t\t\t\t user_uri);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tg_free(role);\n\t\tg_free(self);\n\t}\n\n#ifdef HAVE_VV\n\tif (audio_was_added) {\n\t\tsession->is_call = TRUE;\n\t\task_accept_voice_conference(sipe_private, focus_uri, NULL,\n\t\t\t\t\t    (SipeUserAskCb) call_accept_cb,\n\t\t\t\t\t    NULL);\n\t}\n#ifdef HAVE_APPSHARE\n\tif (presentation_was_added) {\n\t\tsipe_core_appshare_connect_conference(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t      session->chat_session,\n\t\t\t\t\t\t      TRUE);\n\t}\n#endif\n#endif // HAVE_VV\n\n\t/* entity-view, locked */\n\tfor (node = sipe_xml_child(xn_conference_info, \"conference-view/entity-view\");\n\t     node;\n\t     node = sipe_xml_twin(node)) {\n\n\t\tconst sipe_xml *xn_type = sipe_xml_child(node, \"entity-state/media/entry/type\");\n\t\tgchar *tmp = NULL;\n\t\tif (xn_type && sipe_strequal(\"chat\", (tmp = sipe_xml_data(xn_type)))) {\n\t\t\tconst sipe_xml *xn_locked = sipe_xml_child(node, \"entity-state/locked\");\n\t\t\tif (xn_locked) {\n\t\t\t\tgchar *locked = sipe_xml_data(xn_locked);\n\t\t\t\tgboolean prev_locked = session->locked;\n\t\t\t\tsession->locked = sipe_strequal(locked, \"true\");\n\t\t\t\tif (prev_locked && !session->locked) {\n\t\t\t\t\tsipe_user_present_info(sipe_private, session,\n\t\t\t\t\t\t\t       _(\"This conference is no longer locked. Additional participants can now join.\"));\n\t\t\t\t}\n\t\t\t\tif (!prev_locked && session->locked) {\n\t\t\t\t\tsipe_user_present_info(sipe_private, session,\n\t\t\t\t\t\t\t       _(\"This conference is locked. Nobody else can join the conference while it is locked.\"));\n\t\t\t\t}\n\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_process_conference: session->locked=%s\",\n\t\t\t\t\t\tsession->locked ? \"TRUE\" : \"FALSE\");\n\t\t\t\tg_free(locked);\n\t\t\t}\n\t\t}\n\t\tg_free(tmp);\n\t}\n\tsipe_xml_free(xn_conference_info);\n\n\tif (session->im_mcu_uri) {\n\t\tstruct sip_dialog *dialog = sipe_dialog_find(session, session->im_mcu_uri);\n\t\tif (!dialog) {\n\t\t\tdialog = sipe_dialog_add(session);\n\n\t\t\tdialog->callid = g_strdup(session->callid);\n\t\t\tdialog->with = g_strdup(session->im_mcu_uri);\n\n\t\t\t/* send INVITE to IM MCU */\n\t\t\tsipe_im_invite(sipe_private, session, dialog->with, NULL, NULL, NULL, FALSE);\n\t\t}\n\t}\n\n\tsipe_process_pending_invite_queue(sipe_private, session);\n}\n\nvoid\nsipe_conf_immcu_closed(struct sipe_core_private *sipe_private,\n\t\t       struct sip_session *session)\n{\n\tsipe_user_present_info(sipe_private, session,\n\t\t\t       _(\"You have been disconnected from this conference.\"));\n\tsipe_backend_chat_close(session->chat_session->backend);\n}\n\nvoid\nconf_session_close(struct sipe_core_private *sipe_private,\n\t\t   struct sip_session *session)\n{\n\tif (session) {\n\t\t/* unsubscribe from focus */\n\t\tsipe_subscribe_conference(sipe_private,\n\t\t\t\t\t  session->chat_session->id, TRUE);\n\n\t\tif (session->focus_dialog) {\n\t\t\t/* send BYE to focus */\n\t\t\tsip_transport_bye(sipe_private, session->focus_dialog);\n\t\t}\n\t}\n}\n\nvoid\nsipe_process_imdn(struct sipe_core_private *sipe_private,\n\t\t  struct sipmsg *msg)\n{\n\tgchar *with = sipmsg_parse_from_address(msg);\n\tconst gchar *callid = sipmsg_find_call_id_header(msg);\n\tstatic struct sip_session *session;\n\tsipe_xml *xn_imdn;\n\tconst sipe_xml *node;\n\tgchar *message_id;\n\tgchar *message;\n\n\tsession = sipe_session_find_chat_or_im(sipe_private, callid, with);\n\tif (!session) {\n\t\tSIPE_DEBUG_INFO(\"sipe_process_imdn: unable to find conf session with callid=%s\", callid);\n\t\tg_free(with);\n\t\treturn;\n\t}\n\n\txn_imdn = sipe_xml_parse(msg->body, msg->bodylen);\n\tmessage_id = sipe_xml_data(sipe_xml_child(xn_imdn, \"message-id\"));\n\n\tmessage = g_hash_table_lookup(session->conf_unconfirmed_messages, message_id);\n\n\t/* recipient */\n\tfor (node = sipe_xml_child(xn_imdn, \"recipient\"); node; node = sipe_xml_twin(node)) {\n\t\tgchar *tmp = parse_from(sipe_xml_attribute(node, \"uri\"));\n\t\tgchar *uri = parse_from(tmp);\n\t\tgchar *status = sipe_xml_data(sipe_xml_child(node, \"status\"));\n\t\tguint error = status ? g_ascii_strtoull(status, NULL, 10) : 0;\n\t\t/* default to error if missing or conversion failed */\n\t\tif ((error == 0) || (error >= 300))\n\t\t\tsipe_user_present_message_undelivered(sipe_private,\n\t\t\t\t\t\t\t      session,\n\t\t\t\t\t\t\t      error,\n\t\t\t\t\t\t\t      -1,\n\t\t\t\t\t\t\t      uri,\n\t\t\t\t\t\t\t      message);\n\t\tg_free(status);\n\t\tg_free(tmp);\n\t\tg_free(uri);\n\t}\n\n\tsipe_xml_free(xn_imdn);\n\n\tg_hash_table_remove(session->conf_unconfirmed_messages, message_id);\n\tSIPE_DEBUG_INFO(\"sipe_process_imdn: removed message %s from conf_unconfirmed_messages(count=%d)\",\n\t\t\tmessage_id, g_hash_table_size(session->conf_unconfirmed_messages));\n\tg_free(message_id);\n\tg_free(with);\n}\n\nvoid sipe_core_conf_make_leader(struct sipe_core_public *sipe_public,\n\t\t\t\tgpointer parameter,\n\t\t\t\tconst gchar *buddy_name)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tstruct sipe_chat_session *chat_session = parameter;\n\tstruct sip_session *session;\n\n\tSIPE_DEBUG_INFO(\"sipe_core_conf_make_leader: chat_title=%s\",\n\t\t\tchat_session->title);\n\n\tsession = sipe_session_find_chat(sipe_private, chat_session);\n\tsipe_conf_modify_user_role(sipe_private, session, buddy_name);\n}\n\nvoid sipe_core_conf_remove_from(struct sipe_core_public *sipe_public,\n\t\t\t\tgpointer parameter,\n\t\t\t\tconst gchar *buddy_name)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tstruct sipe_chat_session *chat_session = parameter;\n\tstruct sip_session *session;\n\n\tSIPE_DEBUG_INFO(\"sipe_core_conf_remove_from: chat_title=%s\",\n\t\t\tchat_session->title);\n\n\tsession = sipe_session_find_chat(sipe_private, chat_session);\n\tsipe_conf_delete_user(sipe_private, session, buddy_name);\n}\n\ngchar *\nsipe_conf_build_uri(const gchar *focus_uri, const gchar *session_type)\n{\n\tgchar **parts = g_strsplit(focus_uri, \":focus:\", 2);\n\tgchar *result = NULL;\n\n\tif (g_strv_length(parts) == 2) {\n\t\tresult = g_strconcat(parts[0], \":\", session_type, \":\", parts[1],\n\t\t\t\t     NULL);\n\t}\n\n\tg_strfreev(parts);\n\treturn result;\n}\n\nstatic gchar *\naccess_numbers_info(struct sipe_core_public *sipe_public)\n{\n\tGString *result = g_string_new(\"\");\n\tGList *keys = g_hash_table_get_keys(SIPE_CORE_PRIVATE->access_numbers);\n\tkeys = g_list_sort(keys, (GCompareFunc)g_strcmp0);\n\n\tfor (; keys; keys = g_list_delete_link(keys, keys)) {\n\t\tgchar *value;\n\t\tvalue = g_hash_table_lookup(SIPE_CORE_PRIVATE->access_numbers,\n\t\t\t\t\t    keys->data);\n\n\t\tg_string_append(result, keys->data);\n\t\tg_string_append(result, \"&nbsp;&nbsp;&nbsp;&nbsp;\");\n\t\tg_string_append(result, value);\n\t\tg_string_append(result, \"<br/>\");\n\t}\n\n\treturn g_string_free(result, FALSE);\n}\n\ngchar *\nsipe_core_conf_entry_info(struct sipe_core_public *sipe_public,\n\t\t\t  struct sipe_chat_session *chat_session)\n{\n\tgchar *access_info = access_numbers_info(sipe_public);\n\tgchar *result = g_strdup_printf(\n\t\t\t\"<b><font size=\\\"+1\\\">%s</font></b><br/>\"\n\t\t\t\"<b>%s:</b> %s<br/>\"\n\t\t\t\"<b>%s:</b> %s<br/>\"\n\t\t\t\"<br/>\"\n\t\t\t\"<b>%s:</b><br/>\"\n\t\t\t\"%s<br/>\"\n\t\t\t\"<br/>\"\n\t\t\t\"<b>%s:</b> %s<br/>\"\n\t\t\t\"<br/>\"\n\t\t\t\"<b><font size=\\\"+1\\\">%s</font></b><br/>\"\n\t\t\t\"%s\",\n\t\t\t_(\"Dial-in info\"),\n\t\t\t_(\"Number\"),\n\t\t\tSIPE_CORE_PRIVATE->default_access_number ? SIPE_CORE_PRIVATE->default_access_number : \"\",\n\t\t\t_(\"Conference ID\"),\n\t\t\tchat_session->dial_in_conf_id ? chat_session->dial_in_conf_id : \"\",\n\t\t\t_(\"Meeting link\"),\n\t\t\tchat_session->join_url ? chat_session->join_url : \"\",\n\t\t\t_(\"Organizer\"),\n\t\t\tchat_session->organizer ? chat_session->organizer : \"\",\n\t\t\t_(\"Alternative dial-in numbers\"),\n\t\t\taccess_info);\n\n\tg_free(access_info);\n\n\treturn result;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-conf.h",
    "content": "/**\n * @file sipe-conf.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2009-10 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipmsg;\nstruct sip_session;\nstruct sipe_core_private;\n\n/**\n * Obtains conferencing capabilities enabled on the server.\n *\n * @param sipe_private SIPE core data\n */\nvoid\nsipe_conf_get_capabilities(struct sipe_core_private *sipe_private);\n\n/**\n * Checks whether given Multipoint Control Unit type is supported by the server.\n */\ngboolean\nsipe_conf_supports_mcu_type(struct sipe_core_private *sipe_private,\n\t\t\t    const gchar *type);\n\n/**\n * Creates conference.\n */\nvoid\nsipe_conf_add(struct sipe_core_private *sipe_private,\n\t      const gchar* who);\n\n/**\n * Processes incoming INVITE with\n * Content-Type: application/ms-conf-invite+xml\n * i.e. invitation to join conference.\n *\n * Server 2007+ functionality.\n */\nvoid\nprocess_incoming_invite_conf(struct sipe_core_private *sipe_private,\n\t\t\t     struct sipmsg *msg);\n\n/**\n * Create new session with Focus URI\n *\n * @param chat_session non-NULL if we rejoin a conference\n * @param focus_uri    non-NULL if we create a new conference\n *\n * @return new SIP session\n */\nstruct sip_session *\nsipe_conf_create(struct sipe_core_private *sipe_private,\n\t\t struct sipe_chat_session *chat_session,\n\t\t const gchar *focus_uri);\n\n/**\n * Process of conference state\n * Content-Type: application/conference-info+xml\n */\nvoid\nsipe_process_conference(struct sipe_core_private *sipe_private,\n\t\t\tstruct sipmsg * msg);\n\n/**\n * Invites counterparty to join conference.\n */\nvoid\nsipe_invite_conf(struct sipe_core_private *sipe_private,\n\t\t struct sip_session *session,\n\t\t const gchar* who);\n\n/**\n * Modify User Role.\n * Sends request to Focus.\n * INFO method is a carrier of application/cccp+xml\n */\nvoid\nsipe_conf_modify_user_role(struct sipe_core_private *sipe_private,\n\t\t\t   struct sip_session *session,\n\t\t\t   const gchar* who);\n\n/**\n * Ejects user from conference.\n * Sends request to Focus.\n * INFO method is a carrier of application/cccp+xml\n */\nvoid\nsipe_conf_delete_user(struct sipe_core_private *sipe_private,\n\t\t      struct sip_session *session,\n\t\t      const gchar* who);\n\n/**\n * Notifies conference call participants of our microphone mute state.\n */\nvoid\nsipe_conf_announce_audio_mute_state(struct sipe_core_private *sipe_private,\n\t\t\t\t    struct sip_session *session,\n\t\t\t\t    gboolean is_muted);\n\n/**\n * Invokes when we are ejected from conference\n * for example or conference has been timed out.\n */\nvoid\nsipe_conf_immcu_closed(struct sipe_core_private *sipe_private,\n\t\t       struct sip_session *session);\n\n/**\n * Removes a session waiting to be accepted or declined by the user.\n *\n * @param sipe_private SIPE core data\n * @param msg SIP CANCEL message. If NULL is passed, all sessions not accepted\n *            will be canceled\n */\nvoid\nsipe_conf_cancel_unaccepted(struct sipe_core_private *sipe_private,\n\t\t\t    struct sipmsg *msg);\n\n/**\n * Creates URI for given session type within a conference specified by its\n * focus URI.\n *\n * @param focus_uri conference focus URI\n * @param session_type type of session for which to build the URI,\n *                     e.g. \"audio-video\"\n */\ngchar *\nsipe_conf_build_uri(const gchar *focus_uri, const gchar *session_type);\n\n/**\n * Invokes when we leave conversation.\n * Usually by closing chat wingow.\n */\nvoid\nconf_session_close(struct sipe_core_private *sipe_private,\n\t\t   struct sip_session *session);\n\n/**\n * Invoked to process message delivery notification\n * in conference.\n */\nvoid\nsipe_process_imdn(struct sipe_core_private *sipe_private,\n\t\t  struct sipmsg *msg);\n"
  },
  {
    "path": "src/core/sipe-core-private.h",
    "content": "/**\n * @file sipe-core-private.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sip_address_data;\nstruct sip_csta;\nstruct sip_service_data;\nstruct sip_transport;\nstruct sipe_buddies;\nstruct sipe_calendar;\nstruct sipe_certificate;\nstruct sipe_ews_autodiscover;\nstruct sipe_groupchat;\nstruct sipe_groups;\nstruct sipe_http;\nstruct sipe_http_request;\nstruct sipe_lync_autodiscover;\nstruct sipe_media_call_private;\nstruct sipe_svc;\nstruct sipe_ucs;\nstruct sipe_webticket;\n\n/**\n * Private part of the Sipe data structure\n *\n * This part contains the information only needed by the core\n */\nstruct sipe_core_private {\n\t/**\n\t * The public part is the first item, i.e. a pointer to the\n\t * public part can also be used as a pointer to the private part.\n\t */\n\tstruct sipe_core_public public;\n\n\t/* sip-transport.c private data */\n\tstruct sip_transport *transport;\n\tGSList *lync_autodiscover_servers;           /* Lync autodiscover */\n\tconst struct sip_service_data *service_data; /* autodiscovery SRV records */\n\tconst struct sip_address_data *address_data; /* autodiscovery A records */\n\tgchar *user_agent;\n\tguint transport_type;\n\tguint authentication_type;\n\n\t/* Account information */\n\tgchar *username;\n\tgchar *authuser;   /* NULL when SSO is enabled */\n\tgchar *password;   /* NULL when SSO is enabled */\n\tgchar *email;\n\tgchar *email_authuser;   /* NULL -> use default authentication */\n\tgchar *email_password;\n\n\t/* SIPE protocol information */\n\tgchar *contact;\n\tgchar *register_callid;\n\tgchar *focus_factory_uri;\n\tGSList *sessions;\n\tGSList *sessions_to_accept;\n\t/* from REGISTER response: server events\n\t *  we're allowed to subscribe to\n\t */\n\tGSList *allowed_events;\n\n\t/* Presence */\n\tgchar *status;\n\tgchar *note;\n\ttime_t note_since;\n\tgboolean status_set_by_user;\n\n\t/* [MS-SIP] deltaNum counters */\n\tguint deltanum_contacts;\n\tguint deltanum_acl;      /* setACE (OCS2005 only) */\n\n\t/* [MS-PRES] */\n\tGSList *containers;\n\tGSList *our_publication_keys;\n\tGHashTable *our_publications;\n\tGHashTable *user_state_publications;\n\n\t/* Buddies */\n\tstruct sipe_groups *groups;\n\tstruct sipe_buddies *buddies;\n\n\t/* Calendar and related stuff */\n\tstruct sipe_calendar *calendar;\n\n\t/* EWS autodiscover */\n\tstruct sipe_ews_autodiscover *ews_autodiscover;\n\n\t/* Lync autodiscover */\n\tstruct sipe_lync_autodiscover *lync_autodiscover;\n\n\t/*\n\t * 2005 Custom XML piece\n\t *\n\t * Possibly set by other point of presence or just other client at\n\t * earlier time. It should be preserved/modified, not overwritten.\n\t * This implies subscription to self-contact. Information kept:\n\t *\n\t * - User note\n\t * - OOF flag\n\t * - User status\n\t */\n\tgchar *ocs2005_user_states;\n\n\t/* Scheduling system */\n\tGSList *timeouts;\n\n\t/* Active subscriptions */\n\tGHashTable *subscriptions;\n\n\t/* Voice call */\n\tGHashTable *media_calls;\n\tgchar *test_call_bot_uri;\n\tgchar *uc_line_uri;\n\t/**\n\t *  Provides the necessary information on where we can obtain\n\t *  credentials for the A/V Edge server service.\n\t */\n\tgchar *mras_uri;\n\tgchar *media_relay_username;\n\tgchar *media_relay_password;\n\tGSList *media_relays;\n\tSipeEncryptionPolicy server_av_encryption_policy;\n\n\t/* Group chat */\n\tstruct sipe_groupchat *groupchat;\n\tgchar *persistentChatPool_uri;\n\n\t/* buddy menu memory allocation */\n\tGSList *blist_menu_containers;\n\n\t/* For RCC - Remote Call Control */\n\tstruct sip_csta *csta;\n\n\tstruct sipe_dns_query *dns_query;\n\n\t/* HTTP service */\n\tstruct sipe_http *http;\n\n\t/* TLS-DSK: Certificates & Web services */\n\tstruct sipe_certificate *certificate;\n\tstruct sipe_webticket *webticket;\n\tstruct sipe_svc *svc;\n\n\t/* Unified Contact Store */\n\tstruct sipe_ucs *ucs;\n\n\t/* [MS-DLX] server URI */\n\tgchar *dlx_uri;\n\n\t/* Addressbook server URI */\n\tgchar *addressbook_uri;\n\n\t/* [MS-CONFPRO] CCCP request ID counter */\n\tguint cccp_request_id;\n\n\tguint ms_filetransfer_request_id;\n\n\tGSList *conf_mcu_types;\n\n\t/* Dial-in conferencing phone numbers for different regions */\n\tGHashTable *access_numbers;\n\tconst gchar *default_access_number;\n\n\t/* Port ranges to use for media connections. Zero means any port. */\n\tguint min_media_port;\n\tguint max_media_port;\n\tguint min_audio_port;\n\tguint max_audio_port;\n\tguint min_video_port;\n\tguint max_video_port;\n\tguint min_appsharing_port;\n\tguint max_appsharing_port;\n\tguint min_filetransfer_port;\n\tguint max_filetransfer_port;\n};\n\n/**\n * Flags - stored in sipe_core_public.flags but names not exported\n */\n/* server is OCS2007+ */\n#define SIPE_CORE_PRIVATE_FLAG_OCS2007            0x80000000\n/* we are connected from outside the enterprise network boundary\n * via Edge Server */\n#define SIPE_CORE_PRIVATE_FLAG_REMOTE_USER        0x40000000\n/* multiple points of presence detected */\n#define SIPE_CORE_PRIVATE_FLAG_MPOP               0x20000000\n/* if there is support for batched subscription*/\n#define SIPE_CORE_PRIVATE_FLAG_BATCHED_SUPPORT    0x10000000\n/* if note is out-of-office note */\n#define SIPE_CORE_PRIVATE_FLAG_OOF_NOTE           0x08000000\n/* whether we published our initial state or not */\n#define SIPE_CORE_PRIVATE_FLAG_INITIAL_PUBLISH    0x04000000\n/* whether basic access level is set or not */\n#define SIPE_CORE_PRIVATE_FLAG_ACCESS_LEVEL_SET   0x02000000\n/* whether subscribed to buddies presence or not */\n#define SIPE_CORE_PRIVATE_FLAG_SUBSCRIBED_BUDDIES 0x01000000\n/* user enabled Single-Sign On */\n#define SIPE_CORE_PRIVATE_FLAG_SSO                0x00800000\n/* server is Lync 2013+ */\n#define SIPE_CORE_PRIVATE_FLAG_LYNC2013           0x00400000\n/* server is Skype for Business (RTC/6.0 +) */\n#define SIPE_CORE_PRIVATE_FLAG_SFB                0x00200000\n\n#define SIPE_CORE_PUBLIC_FLAG_IS(flag)    \\\n\t((sipe_private->public.flags & SIPE_CORE_FLAG_ ## flag) == SIPE_CORE_FLAG_ ## flag)\n#define SIPE_CORE_PUBLIC_FLAG_SET(flag)   \\\n\t(sipe_private->public.flags |= SIPE_CORE_FLAG_ ## flag)\n#define SIPE_CORE_PUBLIC_FLAG_UNSET(flag)\t\t\t\t\\\n\t(sipe_private->public.flags &= ~SIPE_CORE_FLAG_ ## flag)\n#define SIPE_CORE_PRIVATE_FLAG_IS(flag)    \\\n\t((sipe_private->public.flags & SIPE_CORE_PRIVATE_FLAG_ ## flag) == SIPE_CORE_PRIVATE_FLAG_ ## flag)\n#define SIPE_CORE_PRIVATE_FLAG_SET(flag)   \\\n\t(sipe_private->public.flags |= SIPE_CORE_PRIVATE_FLAG_ ## flag)\n#define SIPE_CORE_PRIVATE_FLAG_UNSET(flag)\t\t\t\t\\\n\t(sipe_private->public.flags &= ~SIPE_CORE_PRIVATE_FLAG_ ## flag)\n\n/* Convenience macros */\n#define SIPE_CORE_PRIVATE ((struct sipe_core_private *)sipe_public)\n#define SIPE_CORE_PUBLIC  ((struct sipe_core_public *)sipe_private)\n\n/**\n * sipe-core internal functions\n */\nvoid sipe_core_backend_initialized(struct sipe_core_private *sipe_private,\n\t\t\t\t   guint authentication);\nvoid sipe_core_connection_cleanup(struct sipe_core_private *sipe_private);\nvoid sipe_core_email_authentication(struct sipe_core_private *sipe_private,\n\t\t\t\t    struct sipe_http_request *request);\nconst gchar *sipe_core_user_agent(struct sipe_core_private *sipe_private);\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-core.c",
    "content": "/**\n * @file sipe-core.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * Some notes on the history of this project/code/copyrights:\n *\n *  - the project is called SIPE, but originally the code was only written\n *    for the libpurple framework, i.e. Pidgin. Hence the package name is\n *    \"pidgin-sipe\".\n *\n *  - in the beginning almost all of the code was located in a module\n *    called \"sipe.c\". During the effort to remove the libpurple\n *    dependencies from the SIPE core, thousands of lines of code got\n *    shifted out of sipe.c, mostly to newly created modules and sipe.c\n *    ceased to exist.\n *\n *  - it would have been tedious to track down the original author or\n *    copyright and preserve them for each line of code that was moved.\n *    Therefore the new modules started with a fresh copyright notice\n *    (like the one above).\n *\n *  - the original copyright notices from sipe.c have been moved to this\n *    file (see below) and *MUST* be preserved!\n *\n *  - if necessary the author of a line of code in question can still be\n *    reconstructed from the git repository information.\n *    See also \"man git-blame\"\n *\n *  - if you think your copyright should be restored for a piece of code,\n *    then please contact the SIPE project to fix the source files ASAP.\n *\n *------------------- Copyright notices from \"sipe.c\" ---------------\n * Copyright (C) 2010-11 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2009-10 pier11 <pier11@operamail.com>\n * Copyright (C) 2008    Novell, Inc.\n * Copyright (C) 2007-09 Anibal Avelar <debianmx@gmail.com>\n * Copyright (C) 2005    Thomas Butter <butter@uni-mannheim.de>\n *\n * ***\n * Thanks to Google's Summer of Code Program and the helpful mentors\n * ***\n *------------------- Copyright notices from \"sipe.c\" ---------------\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sip-csta.h\"\n#include \"sip-sec.h\"\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-buddy.h\"\n#include \"sipe-cal.h\"\n#include \"sipe-certificate.h\"\n#include \"sipe-chat.h\"\n#include \"sipe-conf.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-crypt.h\"\n#include \"sipe-ews-autodiscover.h\"\n#include \"sipe-group.h\"\n#include \"sipe-groupchat.h\"\n#include \"sipe-http.h\"\n#include \"sipe-lync-autodiscover.h\"\n#include \"sipe-media.h\"\n#include \"sipe-mime.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-ocs2007.h\"\n#include \"sipe-schedule.h\"\n#include \"sipe-session.h\"\n#include \"sipe-status.h\"\n#include \"sipe-subscriptions.h\"\n#include \"sipe-svc.h\"\n#include \"sipe-ucs.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-webticket.h\"\n\n#if !GLIB_CHECK_VERSION(2,18,0)\n#error glib-2.0 >= 2.18.0 is required to build SIPE\n#endif\n\n#ifdef PACKAGE_GIT_COMMIT\n#define SIPE_CORE_VERSION PACKAGE_VERSION \" (git commit \" PACKAGE_GIT_COMMIT \" / \"\n#else\n#define SIPE_CORE_VERSION PACKAGE_VERSION \" (\"\n#endif\n\n/* translate config.h options to strings */\nstatic const gchar * const sipe_core_build_options[] = {\n\n\t/* Authentication */\n#ifdef HAVE_SSPI\n\t\"SSPI\",\n#elif defined(HAVE_GSSAPI_ONLY)\n\t\"GSSAPI\",\n#ifndef HAVE_GSSAPI_PASSWORD_SUPPORT\n\t\"SSO only\",\n#endif\n#else\n#ifdef HAVE_GSSAPI_GSSAPI_H\n\t\"Kerberos 5 & NTLM\",\n#else\n\t\"NTLM\",\n#endif\n#endif\n\n\t/* D-Bus */\n#ifdef HAVE_DBUS\n\t\"D-Bus\",\n#endif\n\n\t/* Media */\n#ifdef HAVE_VV\n\t\"Voice & Video\",\n#ifdef HAVE_SRTP\n\t\"SRTP\",\n#endif\n#ifdef HAVE_XDATA\n\t\"Lync FT\",\n#endif\n#ifdef HAVE_APPSHARE\n#ifdef HAVE_APPSHARE_SERVER\n\t\"Application Sharing - full\",\n#else\n\t\"Application Sharing - client only\",\n#endif\n#endif\n#endif\n\n\t/* Development */\n#ifdef HAVE_VALGRIND\n\t\"Valgrind\",\n#endif\n\n\tNULL\n};\n\n\n/* locale_dir is unused if ENABLE_NLS is not defined */\nvoid sipe_core_init(SIPE_UNUSED_PARAMETER const char *locale_dir)\n{\n\tsrand(time(NULL));\n\tsip_sec_init();\n\n#ifdef ENABLE_NLS\n\tSIPE_DEBUG_INFO(\"bindtextdomain = %s\",\n\t\t\tbindtextdomain(PACKAGE_NAME, locale_dir));\n\tSIPE_DEBUG_INFO(\"bind_textdomain_codeset = %s\",\n\t\t\tbind_textdomain_codeset(PACKAGE_NAME, \"UTF-8\"));\n\ttextdomain(PACKAGE_NAME);\n#endif\n\t/* Initialization for crypto backend (production mode) */\n\tsipe_crypto_init(TRUE);\n\tsipe_mime_init();\n\tsipe_status_init();\n}\n\nvoid sipe_core_destroy(void)\n{\n\tsipe_chat_destroy();\n\tsipe_status_shutdown();\n\tsipe_mime_shutdown();\n\tsipe_crypto_shutdown();\n\tsip_sec_destroy();\n}\n\ngchar *sipe_core_about(void)\n{\n\tgchar *options = g_strjoinv(\" / \", (gchar **) sipe_core_build_options);\n\tgchar *about   = g_strdup_printf(\n\t\t/*\n\t\t * Non-translatable parts, like markup, are hard-coded\n\t\t * into the format string. This requires more translatable\n\t\t * texts but it makes the translations less error prone.\n\t\t */\n\t\t\"<b><font size=\\\"+1\\\">SIPE \" SIPE_CORE_VERSION \"%s) </font></b><br/>\"\n\t\t\"<br/>\"\n\t\t/* 1 */   \"%s:<br/>\"\n\t\t\" - Skype for Business<br/>\"\n\t\t\" - Microsoft Office 365<br/>\"\n\t\t\" - Microsoft Business Productivity Online Suite (BPOS)<br/>\"\n\t\t\" - Microsoft Lync Server<br/>\"\n\t\t\" - Microsoft Office Communications Server 2007 R2<br/>\"\n\t\t\" - Microsoft Office Communications Server 2007<br/>\"\n\t\t\" - Microsoft Live Communications Server 2005<br/>\"\n\t\t\" - Microsoft Live Communications Server 2003<br/>\"\n\t\t\"<br/>\"\n\t\t/* 2 */   \"%s: <a href=\\\"\" PACKAGE_URL \"\\\">\" PACKAGE_URL \"</a><br/>\"\n\t\t/* 3,4 */ \"%s: <a href=\\\"http://sourceforge.net/p/sipe/discussion/688534/\\\">%s</a><br/>\"\n\t\t/* 5,6 */   \"%s: <a href=\\\"\" PACKAGE_BUGREPORT \"\\\">%s</a><br/>\"\n\t\t/* 7 */   \"%s: <a href=\\\"\" SIPE_TRANSLATIONS_URL \"\\\">Transifex.com</a><br/>\"\n\t\t/* 8 */   \"%s: GPL-2.0-or-later<br/>\"\n\t\t\"<br/>\"\n\t\t/* 9 (REMOVED) */\n\t\t/* 10,11 */ \"%s<a href=\\\"\" SIPE_TRANSLATIONS_URL \"\\\">Transifex.com</a>%s.<br/>\"\n\t\t\"<br/>\"\n\t\t/* 12 */  \"<b>%s:</b><br/>\"\n\t\t\" - Stefan Becker<br/>\"\n\t\t\" - Jakub Adam<br/>\"\n\t\t\" - Jochen De Smet (retired, Miranda port)<br/>\"\n\t\t\" - Michael Lamb (retired, Adium port)<br/>\"\n\t\t\" - Anibal Avelar (retired)<br/>\"\n\t\t\" - Gabriel Burt (retired)<br/>\"\n\t\t\" - pier11 (retired)<br/>\"\n\t\t\" - Tomáš Hrabčík (retired)<br/>\"\n\t\t\"<br/>\"\n\t\t/* 13 */  \"%s<br/>\"\n\t\t, options,\n\t\t/* The next 13 texts make up the SIPE about note text */\n\t\t/* About note, part 1/13: introduction */\n\t\t_(\"A third-party plugin implementing extended version of SIP/SIMPLE used by various products\"),\n\t\t/* About note, part 2/13: home page URL (label) */\n\t\t_(\"Home Page\"),\n\t\t/* About note, part 3/13: support forum URL (label) */\n\t\t_(\"Support\"),\n\t\t/* About note, part 4/13: support forum name (hyperlink text) */\n\t\t_(\"Help Forum\"),\n\t\t/* About note, part 5/13: bug tracker URL (label) */\n\t\t_(\"Report Problems\"),\n\t\t/* About note, part 6/13: bug tracker URL (hyperlink text) */\n\t\t_(\"Bug Tracker\"),\n\t\t/* About note, part 7/13: translation service URL (label) */\n\t\t_(\"Translations\"),\n\t\t/* About note, part 8/13: license type (label) */\n\t\t_(\"License\"),\n\t\t/* About note, part 9/13: (REMOVED) */\n\t\t/* About note, part 10/13: translation request, text before Transifex.com URL */\n\t\t/* append a space if text is not empty */\n\t\t_(\"Please help us to translate SIPE to your native language here at \"),\n\t\t/* About note, part 11/13: translation request, text after Transifex.com URL */\n\t\t/* start with a space if text is not empty */\n\t\t_(\" using convenient web interface\"),\n\t\t/* About note, part 12/13: author list (header) */\n\t\t_(\"Authors\"),\n\t\t/* About note, part 13/13: Localization credit */\n\t\t/* PLEASE NOTE: do *NOT* simply translate the english original */\n\t\t/* but write something similar to the following sentence: */\n\t\t/* \"Localization for <language name> (<language code>): <name>\" */\n\t\t_(\"Original texts in English (en): SIPE developers\")\n\t\t);\n\tg_free(options);\n\treturn(about);\n}\n\nstruct sipe_core_public *sipe_core_allocate(const gchar *signin_name,\n\t\t\t\t\t    gboolean sso,\n\t\t\t\t\t    const gchar *login_account,\n\t\t\t\t\t    const gchar *password,\n\t\t\t\t\t    const gchar *email,\n\t\t\t\t\t    const gchar *email_url,\n\t\t\t\t\t    const gchar **errmsg)\n{\n\tstruct sipe_core_private *sipe_private;\n\tgchar **user_domain;\n\tgchar *options = g_strjoinv(\" / \", (gchar **) sipe_core_build_options);\n\n\tSIPE_LOG_INFO(\"sipe_core_allocate: SIPE version \" SIPE_CORE_VERSION \"%s)\", options);\n\tg_free(options);\n\tSIPE_DEBUG_INFO(\"sipe_core_allocate: signin_name '%s'\", signin_name);\n\n\t/* ensure that sign-in name doesn't contain invalid characters */\n\tif (strpbrk(signin_name, \"\\t\\v\\r\\n\") != NULL) {\n\t\t*errmsg = _(\"SIP Exchange user name contains invalid characters\");\n\t\treturn NULL;\n\t}\n\n\t/* ensure that sign-in name format is name@domain */\n\tif (!strchr(signin_name, '@') ||\n\t    g_str_has_prefix(signin_name, \"@\") ||\n\t    g_str_has_suffix(signin_name, \"@\")) {\n\t\t*errmsg = _(\"User name should be a valid SIP URI\\nExample: user@company.com\");\n\t\treturn NULL;\n\t}\n\n\n\t/* ensure that Password is valid when SSO is not selected */\n\tif (!sso && is_empty(password)) {\n\t\t*errmsg = _(\"Password is required when Single Sign-On is not enabled\");\n\t\treturn NULL;\n\t}\n\n\t/* ensure that email format is name@domain (if provided) */\n\tif (!is_empty(email) &&\n\t    (!strchr(email, '@') ||\n\t     g_str_has_prefix(email, \"@\") ||\n\t     g_str_has_suffix(email, \"@\")))\n\t{\n\t\t*errmsg = _(\"Email address should be valid if provided\\nExample: user@company.com\");\n\t\treturn NULL;\n\t}\n\n\t/* ensure that user name doesn't contain spaces */\n\tuser_domain = g_strsplit(signin_name, \"@\", 2);\n\tSIPE_DEBUG_INFO(\"sipe_core_allocate: user '%s' domain '%s'\", user_domain[0], user_domain[1]);\n\tif (strchr(user_domain[0], ' ') != NULL) {\n\t\tg_strfreev(user_domain);\n\t\t*errmsg = _(\"SIP Exchange user name contains whitespace\");\n\t\treturn NULL;\n\t}\n\n\t/* ensure that email_url is in proper format if enabled (if provided).\n\t * Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n\t * Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n\t */\n\tif (!is_empty(email_url)) {\n\t\tchar *tmp = g_ascii_strdown(email_url, -1);\n\t\tif (!g_str_has_prefix(tmp, \"https://\"))\n\t\t{\n\t\t\tg_free(tmp);\n\t\t\tg_strfreev(user_domain);\n\t\t\t*errmsg = _(\"Email services URL should be valid if provided\\n\"\n\t\t\t\t    \"Example: https://exchange.corp.com/EWS/Exchange.asmx\\n\"\n\t\t\t\t    \"Example: https://domino.corp.com/maildatabase.nsf\");\n\t\t\treturn NULL;\n\t\t}\n\t\tg_free(tmp);\n\t}\n\n\t/* re-use sign-in name if login is empty */\n\tif (is_empty(login_account))\n\t\tlogin_account = signin_name;\n\n\tsipe_private = g_new0(struct sipe_core_private, 1);\n\tSIPE_CORE_PRIVATE_FLAG_UNSET(SUBSCRIBED_BUDDIES);\n\tSIPE_CORE_PRIVATE_FLAG_UNSET(INITIAL_PUBLISH);\n\tSIPE_CORE_PRIVATE_FLAG_UNSET(SSO);\n\tif (sso)\n\t\tSIPE_CORE_PRIVATE_FLAG_SET(SSO);\n\tsipe_private->username   = g_strdup(signin_name);\n\tsipe_private->email      = is_empty(email) ? g_strdup(signin_name) : g_strdup(email);\n\tsipe_private->authuser   = sso             ? NULL                  : g_strdup(login_account);\n\tsipe_private->password   = sso             ? NULL                  : g_strdup(password);\n\tsipe_private->public.sip_name   = g_strdup(user_domain[0]);\n\tsipe_private->public.sip_domain = g_strdup(user_domain[1]);\n\tg_strfreev(user_domain);\n\n\tsipe_group_init(sipe_private);\n\tsipe_buddy_init(sipe_private);\n\tsipe_private->our_publications = g_hash_table_new_full(g_str_hash, g_str_equal,\n\t\t\t\t\t\t\t       g_free, (GDestroyNotify)g_hash_table_destroy);\n\tsipe_subscriptions_init(sipe_private);\n\tsipe_lync_autodiscover_init(sipe_private);\n\tsipe_ews_autodiscover_init(sipe_private);\n\tsipe_status_set_activity(sipe_private, SIPE_ACTIVITY_UNSET);\n\n\tsipe_private->media_calls = g_hash_table_new_full(g_str_hash, g_str_equal,\n\t\t\t\t\t\t\t  g_free, NULL);\n\tsipe_private->access_numbers = g_hash_table_new_full(g_str_hash, g_str_equal,\n\t\t\t\t\t\t\t     g_free, g_free);\n\n\treturn((struct sipe_core_public *)sipe_private);\n}\n\nvoid sipe_core_backend_initialized(struct sipe_core_private *sipe_private,\n\t\t\t\t   guint authentication)\n{\n\tconst gchar *value;\n\n\tsipe_private->authentication_type = authentication;\n\n\t/* user specified email login? */\n\tvalue = sipe_backend_setting(SIPE_CORE_PUBLIC, SIPE_SETTING_EMAIL_LOGIN);\n\tif (!is_empty(value)) {\n\t\tsipe_private->email_authuser = g_strdup(value);\n\t\tsipe_private->email_password = g_strdup(sipe_backend_setting(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\t     SIPE_SETTING_EMAIL_PASSWORD));\n\t}\n}\n\nvoid sipe_core_connection_cleanup(struct sipe_core_private *sipe_private)\n{\n\tsipe_http_free(sipe_private);\n\tsip_transport_drop(sipe_private);\n\n\tsipe_schedule_cancel_all(sipe_private);\n\n\tif (sipe_private->allowed_events)\n\t\tsipe_utils_slist_free_full(sipe_private->allowed_events, g_free);\n\n\tsipe_ocs2007_free(sipe_private);\n\n\tsipe_core_buddy_menu_free(SIPE_CORE_PUBLIC);\n\n\tif (sipe_private->contact)\n\t\tg_free(sipe_private->contact);\n\tsipe_private->contact = NULL;\n\tif (sipe_private->register_callid)\n\t\tg_free(sipe_private->register_callid);\n\tsipe_private->register_callid = NULL;\n\n\tif (sipe_private->focus_factory_uri)\n\t\tg_free(sipe_private->focus_factory_uri);\n\tsipe_private->focus_factory_uri = NULL;\n\n\tsipe_groupchat_free(sipe_private);\n\n\twhile (sipe_private->lync_autodiscover_servers)\n\t\tsipe_private->lync_autodiscover_servers =\n\t\t\tsipe_lync_autodiscover_pop(sipe_private->lync_autodiscover_servers);\n}\n\nvoid sipe_core_deallocate(struct sipe_core_public *sipe_public)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\n#ifdef HAVE_VV\n\tsipe_media_handle_going_offline(sipe_private);\n#endif\n\n\t/* leave all conversations */\n\tif (sipe_private->sessions) {\n\t\tGSList *entry;\n\t\twhile ((entry = sipe_private->sessions) != NULL) {\n\t\t\tsipe_session_close(sipe_private, entry->data);\n\t\t}\n\t}\n\n\tsipe_conf_cancel_unaccepted(sipe_private, NULL);\n\n\tif (sipe_private->csta) {\n\t\tsip_csta_close(sipe_private);\n\t}\n\n\t/* pending service requests must be cancelled first */\n\tsipe_svc_free(sipe_private);\n\tsipe_webticket_free(sipe_private);\n\tsipe_ucs_free(sipe_private);\n\tsipe_lync_autodiscover_free(sipe_private);\n\n\tif (sipe_backend_connection_is_valid(SIPE_CORE_PUBLIC)) {\n\t\tsipe_subscriptions_unsubscribe(sipe_private);\n\t\tsip_transport_deregister(sipe_private);\n\t}\n\n\tsipe_core_connection_cleanup(sipe_private);\n\tsipe_ews_autodiscover_free(sipe_private);\n\tsipe_cal_calendar_free(sipe_private->calendar);\n\tsipe_certificate_free(sipe_private);\n\n\tg_free(sipe_private->public.sip_name);\n\tg_free(sipe_private->public.sip_domain);\n\tg_free(sipe_private->username);\n\tg_free(sipe_private->user_agent);\n\tg_free(sipe_private->email_password);\n\tg_free(sipe_private->email_authuser);\n\tg_free(sipe_private->email);\n\tg_free(sipe_private->password);\n\tg_free(sipe_private->authuser);\n\tg_free(sipe_private->status);\n\tg_free(sipe_private->note);\n\tg_free(sipe_private->ocs2005_user_states);\n\n\tsipe_buddy_free(sipe_private);\n\tg_hash_table_destroy(sipe_private->our_publications);\n\tg_hash_table_destroy(sipe_private->user_state_publications);\n\tg_hash_table_destroy(sipe_private->media_calls);\n\tsipe_subscriptions_destroy(sipe_private);\n\tsipe_group_free(sipe_private);\n\n\tif (sipe_private->our_publication_keys)\n\t\tsipe_utils_slist_free_full(sipe_private->our_publication_keys, g_free);\n\n#ifdef HAVE_VV\n\tg_free(sipe_private->test_call_bot_uri);\n\tg_free(sipe_private->uc_line_uri);\n\tg_free(sipe_private->mras_uri);\n\tg_free(sipe_private->media_relay_username);\n\tg_free(sipe_private->media_relay_password);\n\tsipe_media_relay_list_free(sipe_private->media_relays);\n#endif\n\n\tg_free(sipe_private->persistentChatPool_uri);\n\tg_free(sipe_private->addressbook_uri);\n\tg_free(sipe_private->dlx_uri);\n\tsipe_utils_slist_free_full(sipe_private->conf_mcu_types, g_free);\n\tg_hash_table_destroy(sipe_private->access_numbers);\n\tg_free(sipe_private);\n}\n\nvoid sipe_core_email_authentication(struct sipe_core_private *sipe_private,\n\t\t\t\t    struct sipe_http_request *request)\n{\n\tif (sipe_private->email_authuser) {\n\t\tsipe_http_request_authentication(request,\n\t\t\t\t\t\t sipe_private->email_authuser,\n\t\t\t\t\t\t sipe_private->email_password);\n\t}\n}\n\nconst gchar *sipe_core_user_agent(struct sipe_core_private *sipe_private)\n{\n\tif (!sipe_private->user_agent) {\n\t\tconst gchar *useragent = sipe_backend_setting(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t      SIPE_SETTING_USER_AGENT);\n\t\tif (is_empty(useragent)) {\n/*@TODO: better approach to define _user_ OS, it's version and host architecture */\n/* ref: lzodefs.h */\n#if defined(__linux__) || defined(__linux) || defined(__LINUX__)\n  #define SIPE_TARGET_PLATFORM \"linux\"\n#elif defined(__NetBSD__) ||defined( __OpenBSD__) || defined(__FreeBSD__)\n  #define SIPE_TARGET_PLATFORM \"bsd\"\n#elif defined(__APPLE__) || defined(__MACOS__)\n  #define SIPE_TARGET_PLATFORM \"macosx\"\n#elif defined(_AIX) || defined(__AIX__) || defined(__aix__)\n  #define SIPE_TARGET_PLATFORM \"aix\"\n#elif defined(__solaris__) || defined(__sun)\n  #define SIPE_TARGET_PLATFORM \"sun\"\n#elif defined(_WIN32)\n  #define SIPE_TARGET_PLATFORM \"win\"\n#elif defined(__CYGWIN__)\n  #define SIPE_TARGET_PLATFORM \"cygwin\"\n#elif defined(__hpux__)\n  #define SIPE_TARGET_PLATFORM \"hpux\"\n#elif defined(__sgi__)\n  #define SIPE_TARGET_PLATFORM \"irix\"\n#else\n  #define SIPE_TARGET_PLATFORM \"unknown\"\n#endif\n\n#if defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)\n  #define SIPE_TARGET_ARCH \"x86_64\"\n#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386)\n  #define SIPE_TARGET_ARCH \"i386\"\n#elif defined(__ppc64__)\n  #define SIPE_TARGET_ARCH \"ppc64\"\n#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR)\n  #define SIPE_TARGET_ARCH \"ppc\"\n#elif defined(__hppa__) || defined(__hppa)\n  #define SIPE_TARGET_ARCH \"hppa\"\n#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000)\n  #define SIPE_TARGET_ARCH \"mips\"\n#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x)\n  #define SIPE_TARGET_ARCH \"s390\"\n#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8)\n  #define SIPE_TARGET_ARCH \"sparc\"\n#elif defined(__arm__)\n  #define SIPE_TARGET_ARCH \"arm\"\n#else\n  #define SIPE_TARGET_ARCH \"other\"\n#endif\n\t\t\tgchar *backend = sipe_backend_version();\n\t\t\tsipe_private->user_agent = g_strdup_printf(\"%s Sipe/\" PACKAGE_VERSION \" (\" SIPE_TARGET_PLATFORM \"-\" SIPE_TARGET_ARCH \")\",\n\t\t\t\t\t\t\t\t   backend);\n\t\t\tg_free(backend);\n\t\t} else {\n\t\t\tsipe_private->user_agent = g_strdup(useragent);\n\t\t}\n\t}\n\treturn(sipe_private->user_agent);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-crypt-nss.c",
    "content": "/**\n * @file sipe-crypt-nss.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2015 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2010 pier11 <pier11@operamail.com>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/**\n * Cypher routines implementation based on NSS.\n * Includes: RC4, DES\n */\n\n#include \"glib.h\"\n\n#include \"nss.h\"\n/*\n * Work around a compiler error in NSS 3.13.x. Let's hope they fix it for\n * 3.14.x. See also: https://bugzilla.mozilla.org/show_bug.cgi?id=702090\n */\n#if (NSS_VMAJOR == 3) && (NSS_VMINOR == 13)\n#define __GNUC_MINOR __GNUC_MINOR__\n#endif\n#include \"pk11pub.h\"\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-crypt.h\"\n\n/* NSS specific initialization/shutdown */\nvoid sipe_crypto_init(SIPE_UNUSED_PARAMETER gboolean production_mode)\n{\n\tif (!NSS_IsInitialized()) {\n\t\t/*\n\t\t * I have a bad feeling about this: according to the NSS\n\t\t * documentation, NSS can only be initialized once.\n\t\t * Unfortunately there seems to be no way to initialize a\n\t\t * \"NSS context\" that could then be used by the SIPE code\n\t\t * to avoid colliding with other NSS users.\n\t\t *\n\t\t * This seems to work, so it'll have to do for now.\n\t\t *\n\t\t * It might also be required to move this to the backend\n\t\t * so that the backend code can decide when it is OK to\n\t\t * initialize NSS.\n\t\t */\n\t\tNSS_NoDB_Init(\".\");\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"NSS initialised\");\n\t}\n}\n\nvoid sipe_crypto_shutdown(void)\n{\n\t/* do nothing for NSS.\n\t * We don't want accedently switch off NSS possibly used by other plugin -\n\t * ssl-nss in Pidgin for example.\n\t */\n}\n\n/* PRIVATE methods */\n\nstatic PK11Context*\nsipe_crypt_ctx_create(CK_MECHANISM_TYPE cipherMech,\n\t\t      const guchar *key, gsize key_length,\n\t\t      const guchar *iv, gsize iv_length)\n{\n\tPK11SlotInfo* slot;\n\tSECItem keyItem;\n\tSECItem ivItem;\n\tPK11SymKey* SymKey;\n\tSECItem *SecParam;\n\tPK11Context* EncContext;\n\n\t/* For key */\n\tslot = PK11_GetBestSlot(cipherMech, NULL);\n\n\tkeyItem.type = siBuffer;\n\tkeyItem.data = (unsigned char *)key;\n\tkeyItem.len = key_length;\n\n\tSymKey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, NULL);\n\n\t/* Parameter for crypto context */\n\tivItem.type = siBuffer;\n\tivItem.data = (unsigned char *)iv;\n\tivItem.len = iv_length;\n\tSecParam = PK11_ParamFromIV(cipherMech, &ivItem);\n\n\tEncContext = PK11_CreateContextBySymKey(cipherMech, CKA_ENCRYPT, SymKey, SecParam);\n\n\tPK11_FreeSymKey(SymKey);\n\tSECITEM_FreeItem(SecParam, PR_TRUE);\n\tPK11_FreeSlot(slot);\n\n\treturn EncContext;\n}\n\nstatic void\nsipe_crypt_ctx_encrypt(PK11Context* EncContext, const guchar *in, gsize length, guchar *out)\n{\n\tint tmp1_outlen;\n\n\tPK11_CipherOp(EncContext, out, &tmp1_outlen, length, (unsigned char *)in, length);\n}\n\nstatic void\nsipe_crypt_ctx_destroy(PK11Context* EncContext)\n{\n\tPK11_DestroyContext(EncContext, PR_TRUE);\n}\n\nstatic void\nsipe_crypt(CK_MECHANISM_TYPE cipherMech,\n\t   const guchar *key, gsize key_length,\n\t   const guchar *plaintext, gsize plaintext_length,\n\t   guchar *encrypted_text)\n{\n\tvoid *EncContext;\n\n\tEncContext = sipe_crypt_ctx_create(cipherMech, key, key_length, NULL, 0);\n\tsipe_crypt_ctx_encrypt(EncContext, plaintext, plaintext_length, encrypted_text);\n\tsipe_crypt_ctx_destroy(EncContext);\n}\n\n\n/* PUBLIC methods */\n\nvoid\nsipe_crypt_des(const guchar *key,\n\t       const guchar *plaintext, gsize plaintext_length,\n\t       guchar *encrypted_text)\n{\n\tsipe_crypt(CKM_DES_ECB, key, 8, plaintext, plaintext_length, encrypted_text);\n}\n\nvoid\nsipe_crypt_rc4(const guchar *key, gsize key_length,\n\t       const guchar *plaintext, gsize plaintext_length,\n\t       guchar *encrypted_text)\n{\n\tsipe_crypt(CKM_RC4, key, key_length, plaintext, plaintext_length, encrypted_text);\n}\n\ngboolean\nsipe_crypt_rsa_encrypt(gpointer public, gsize modulus_length,\n\t\t       const guchar *plaintext,\n\t\t       guchar *encrypted_text)\n{\n  SECStatus result = PK11_PubEncryptRaw(public,\n\t\t\t\t\tencrypted_text, (guchar *) plaintext,\n\t\t\t\t\tmodulus_length, NULL);\n  return(result == SECSuccess);\n}\n\ngboolean\nsipe_crypt_rsa_decrypt(gpointer private, gsize modulus_length,\n\t\t       const guchar *encrypted_text,\n\t\t       guchar *plaintext)\n{\n  unsigned int length;\n  SECStatus result = PK11_PubDecryptRaw(private,\n\t\t\t\t\t(guchar *) encrypted_text, &length, modulus_length,\n\t\t\t\t\tplaintext, modulus_length);\n  return((result == SECSuccess) && (length == modulus_length));\n}\n\nguchar *sipe_crypt_rsa_sign(gpointer private,\n\t\t \t    const guchar *digest, gsize digest_length,\n\t\t\t    gsize *signature_length)\n{\n  SECItem digItem;\n  SECItem sigItem;\n  SECStatus length;\n\n  length = PK11_SignatureLen(private);\n  if (length < 0) return(NULL);\n\n  /* digest to sign (= encrypt) with private key */\n  digItem.data = (guchar *) digest;\n  digItem.len  = digest_length;\n\n  /* signature */\n  sigItem.data = g_malloc(length);\n  sigItem.len  = length;\n\n  length = PK11_Sign(private, &sigItem, &digItem);\n  if (length != SECSuccess) {\n\t  g_free(sigItem.data);\n\t  return(NULL);\n  }\n\n  *signature_length = sigItem.len;\n  return(sigItem.data);\n}\n\ngboolean sipe_crypt_verify_rsa(gpointer public,\n\t\t\t       const guchar *digest, gsize digest_length,\n\t\t\t       const guchar *signature, gsize signature_length)\n{\n  SECItem digItem;\n  SECItem sigItem;\n\n  /* digest to verify against */\n  digItem.data = (guchar *) digest;\n  digItem.len  = digest_length;\n\n  /* signature to decrypt with public key -> digest to compare */\n  sigItem.data = (guchar *) signature;\n  sigItem.len  = signature_length;\n\n  return(PK11_Verify(public, &sigItem, &digItem, NULL) == SECSuccess);\n}\n\n\n/* Stream RC4 cipher for file transfer */\ngpointer\nsipe_crypt_ft_start(const guchar *key)\n{\n\treturn sipe_crypt_ctx_create(CKM_RC4, key, 16, NULL, 0);\n}\n\nvoid\nsipe_crypt_ft_stream(gpointer context,\n\t\t     const guchar *in, gsize length,\n\t\t     guchar *out)\n{\n\tsipe_crypt_ctx_encrypt(context, in, length, out);\n}\n\nvoid\nsipe_crypt_ft_destroy(gpointer context)\n{\n\tsipe_crypt_ctx_destroy(context);\n}\n\n/*\n * Stream RC4 cipher for TLS\n *\n * basically the same as for FT, but with variable key length\n */\ngpointer sipe_crypt_tls_start(const guchar *key, gsize key_length)\n{\n\treturn sipe_crypt_ctx_create(CKM_RC4, key, key_length, NULL, 0);\n}\n\nvoid sipe_crypt_tls_stream(gpointer context,\n\t\t\t   const guchar *in, gsize length,\n\t\t\t   guchar *out)\n{\n\tsipe_crypt_ctx_encrypt(context, in, length, out);\n}\n\nvoid sipe_crypt_tls_destroy(gpointer context)\n{\n\tsipe_crypt_ctx_destroy(context);\n}\n\n/* Block AES-CBC cipher for TLS */\nvoid sipe_crypt_tls_block(const guchar *key, gsize key_length,\n\t\t\t  const guchar *iv, gsize iv_length,\n\t\t\t  const guchar *in, gsize length,\n\t\t\t  guchar *out)\n{\n\tPK11Context* context = sipe_crypt_ctx_create(CKM_AES_CBC,\n\t\t\t\t\t\t     key, key_length,\n\t\t\t\t\t\t     iv, iv_length);\n\tif (context) {\n\t\tsipe_crypt_ctx_encrypt(context, in, length, out);\n\t\tsipe_crypt_ctx_destroy(context);\n\t}\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-crypt-openssl.c",
    "content": "/**\n * @file sipe-crypt-openssl.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013-2017 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/**\n * Cipher routines implementation based on OpenSSL.\n */\n#include <openssl/evp.h>\n#include <openssl/rsa.h>\n\n#include \"glib.h\"\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-crypt.h\"\n\n/* OpenSSL specific initialization/shutdown */\nvoid sipe_crypto_init(SIPE_UNUSED_PARAMETER gboolean production_mode)\n{\n\t/* nothing to do here */\n}\n\nvoid sipe_crypto_shutdown(void)\n{\n\t/* nothing to do here */\n}\n\nstatic void openssl_oneshot_crypt(const EVP_CIPHER *type,\n\t\t\t\t  const guchar *key, gsize key_length,\n\t\t\t\t  const guchar *plaintext, gsize plaintext_length,\n\t\t\t\t  guchar *encrypted_text)\n{\n\tEVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();\n\tint encrypted_length = 0;\n\n\t/* initialize context */\n\tEVP_EncryptInit_ex(ctx, type, NULL, key, NULL);\n\n\t/* set encryption parameters */\n\tif (key_length)\n\t\tEVP_CIPHER_CTX_set_key_length(ctx, key_length);\n\tEVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL);\n\n\t/* encrypt */\n\tEVP_EncryptUpdate(ctx,\n\t\t\t  encrypted_text, &encrypted_length,\n\t\t\t  plaintext, plaintext_length);\n\tencrypted_text += encrypted_length;\n\tEVP_EncryptFinal_ex(ctx, encrypted_text, &encrypted_length);\n\n\t/* cleanup */\n\tEVP_CIPHER_CTX_free(ctx);\n}\n\n/* DES CBC with 56-bit key */\nvoid sipe_crypt_des(const guchar *key,\n\t\t    const guchar *plaintext, gsize plaintext_length,\n\t\t    guchar *encrypted_text)\n{\n\topenssl_oneshot_crypt(EVP_des_cbc(),\n\t\t\t      key, 0 /* fixed length */,\n\t\t\t      plaintext, plaintext_length,\n\t\t\t      encrypted_text);\n}\n\n/* RC4 with variable length key */\nvoid sipe_crypt_rc4(const guchar *key, gsize key_length,\n\t\t    const guchar *plaintext, gsize plaintext_length,\n\t\t    guchar *encrypted_text)\n{\n\topenssl_oneshot_crypt(EVP_rc4(),\n\t\t\t      key, key_length,\n\t\t\t      plaintext, plaintext_length,\n\t\t\t      encrypted_text);\n}\n\ngboolean sipe_crypt_rsa_encrypt(gpointer public,\n\t\t\t\tgsize modulus_length,\n\t\t\t\tconst guchar *plaintext,\n\t\t\t\tguchar *encrypted_text)\n{\n\treturn(RSA_public_encrypt(modulus_length,\n\t\t\t\t  plaintext,\n\t\t\t\t  encrypted_text,\n\t\t\t\t  public,\n\t\t\t\t  RSA_NO_PADDING)\n\t       != -1);\n}\n\ngboolean sipe_crypt_rsa_decrypt(gpointer private,\n\t\t\t\tgsize modulus_length,\n\t\t\t\tconst guchar *encrypted_text,\n\t\t\t\tguchar *plaintext)\n{\n\treturn(RSA_private_decrypt(modulus_length,\n\t\t\t\t   encrypted_text,\n\t\t\t\t   plaintext,\n\t\t\t\t   private,\n\t\t\t\t   RSA_NO_PADDING)\n\t       != -1);\n}\n\nguchar *sipe_crypt_rsa_sign(gpointer private,\n\t\t\t    const guchar *digest, gsize digest_length,\n\t\t\t    gsize *signature_length)\n{\n\tguchar *signature = g_malloc(RSA_size(private));\n\tunsigned int length;\n\n\tif (!RSA_sign(NID_md5_sha1,\n\t\t      digest, digest_length,\n\t\t      signature, &length,\n\t\t      private)) {\n\t\tg_free(signature);\n\t\treturn(NULL);\n\t}\n\n\t*signature_length = length;\n\treturn(signature);\n}\n\ngboolean sipe_crypt_verify_rsa(gpointer public,\n\t\t\t       const guchar *digest, gsize digest_length,\n\t\t\t       const guchar *signature, gsize signature_length)\n{\n\treturn(RSA_verify(NID_md5_sha1,\n\t\t\t  digest, digest_length,\n\t\t\t  /* older OpenSSL version don't have \"const\" here */\n\t\t\t  (guchar *) signature, signature_length,\n\t\t\t  public));\n}\n\nstatic gpointer openssl_EVP_init(const EVP_CIPHER *type,\n\t\t\t\t const guchar *key,\n\t\t\t\t gsize key_length,\n\t\t\t\t const guchar *iv)\n{\n\tEVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();\n\n\t/* initialize context */\n\tEVP_EncryptInit_ex(ctx, type, NULL, key, iv);\n\n\t/* set encryption parameters */\n\tEVP_CIPHER_CTX_set_key_length(ctx, key_length);\n\tEVP_EncryptInit_ex(ctx, NULL, NULL, key, iv);\n\n\treturn(ctx);\n}\n\n/* Stream RC4 cipher for file transfer with fixed-length 128-bit key */\ngpointer sipe_crypt_ft_start(const guchar *key)\n{\n\treturn(openssl_EVP_init(EVP_rc4(), key, 16, NULL));\n}\n\nvoid sipe_crypt_ft_stream(gpointer context,\n\t\t\t  const guchar *in, gsize length,\n\t\t\t  guchar *out)\n{\n\tint tmp;\n\tEVP_EncryptUpdate(context, out, &tmp, in, length);\n}\n\nvoid sipe_crypt_ft_destroy(gpointer context)\n{\n\tEVP_CIPHER_CTX_free(context);\n}\n\n/* Stream RC4 cipher for TLS with variable key length */\ngpointer sipe_crypt_tls_start(const guchar *key, gsize key_length)\n{\n\treturn(openssl_EVP_init(EVP_rc4(), key, key_length, NULL));\n}\n\nvoid sipe_crypt_tls_stream(gpointer context,\n\t\t\t   const guchar *in, gsize length,\n\t\t\t   guchar *out)\n{\n\tint tmp;\n\tEVP_EncryptUpdate(context, out, &tmp, in, length);\n}\n\nvoid sipe_crypt_tls_destroy(gpointer context)\n{\n\tEVP_CIPHER_CTX_free(context);\n}\n\n/* Block AES-CBC cipher for TLS */\nvoid sipe_crypt_tls_block(const guchar *key, gsize key_length,\n\t\t\t  const guchar *iv,\n\t\t\t  /* OpenSSL assumes that iv is of correct size */\n\t\t\t  SIPE_UNUSED_PARAMETER gsize iv_length,\n\t\t\t  const guchar *in, gsize length,\n\t\t\t  guchar *out)\n{\n\tconst EVP_CIPHER *type = NULL;\n\n\tswitch (key_length) {\n\tcase 128 / 8:\n\t\ttype = EVP_aes_128_cbc();\n\t\tbreak;\n\t/*\n\t * TLS does not use AES-192\n\t *\n\tcase 192 / 8:\n\t\ttype = EVP_aes_192_cbc();\n\t\tbreak;\n\t*/\n\tcase 256 / 8:\n\t\ttype = EVP_aes_256_cbc();\n\t\tbreak;\n\tdefault:\n\t\tSIPE_DEBUG_ERROR(\"sipe_crypt_tls_block: unsupported key length %\" G_GSIZE_FORMAT \" bytes for AES CBC\",\n\t\t\t\t key_length);\n\t\tbreak;\n\t}\n\n\tif (type) {\n\t\tEVP_CIPHER_CTX *context = openssl_EVP_init(type,\n\t\t\t\t\t\t\t   key, key_length,\n\t\t\t\t\t\t\t   iv);\n\n\t\tif (context) {\n\t\t\tint tmp;\n\t\t\tEVP_EncryptUpdate(context, out, &tmp, in, length);\n\t\t\tEVP_CIPHER_CTX_free(context);\n\t\t}\n\t}\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-crypt.h",
    "content": "/**\n * @file sipe-crypt.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2015 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/**\n * Crypto backend specific initialization/shutdown\n *\n * TRUE  - production mode, i.e. called from sipe-core.c\n * FALSE - test mode\n */\nvoid sipe_crypto_init(gboolean production_mode);\nvoid sipe_crypto_shutdown(void);\n\nvoid sipe_crypt_des(const guchar *key,\n\t\t    const guchar *plaintext, gsize plaintext_length,\n\t\t    guchar *encrypted_text);\n\nvoid sipe_crypt_rc4(const guchar *key, gsize key_length,\n\t\t    const guchar *plaintext, gsize plaintext_length,\n\t\t    guchar *encrypted_text);\n\n/* plaintext & encrypted_text must point to modulus_length long spaces */\ngboolean sipe_crypt_rsa_encrypt(gpointer public, gsize modulus_length,\n\t\t\t\tconst guchar *plaintext,\n\t\t\t\tguchar *encrypted_text);\ngboolean sipe_crypt_rsa_decrypt(gpointer private, gsize modulus_length,\n\t\t\t\tconst guchar *encrypted_text,\n\t\t\t\tguchar *plaintext);\n/* must be g_free'd() */\nguchar *sipe_crypt_rsa_sign(gpointer private,\n\t\t\t    const guchar *digest, gsize digest_length,\n\t\t\t    gsize *signature_length);\ngboolean sipe_crypt_verify_rsa(gpointer public,\n\t\t\t       const guchar *digest, gsize digest_length,\n\t\t\t       const guchar *signature, gsize signature_length);\n\n/* Stream RC4 cipher for file transfer */\ngpointer sipe_crypt_ft_start(const guchar *key);\nvoid sipe_crypt_ft_stream(gpointer context,\n\t\t\t  const guchar *in, gsize length,\n\t\t\t  guchar *out);\nvoid sipe_crypt_ft_destroy(gpointer context);\n\n/* Stream RC4 cipher for TLS */\ngpointer sipe_crypt_tls_start(const guchar *key, gsize key_length);\nvoid sipe_crypt_tls_stream(gpointer context,\n\t\t\t   const guchar *in, gsize length,\n\t\t\t   guchar *out);\nvoid sipe_crypt_tls_destroy(gpointer context);\n\n/* Block AES-CBC cipher for TLS */\nvoid sipe_crypt_tls_block(const guchar *key, gsize key_length,\n\t\t\t  const guchar *iv, gsize iv_length,\n\t\t\t  const guchar *in, gsize length,\n\t\t\t  guchar *out);\n"
  },
  {
    "path": "src/core/sipe-dialog.c",
    "content": "/**\n * @file sipe-dialog.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2009-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#include <glib.h>\n\n#include \"sipe-core.h\"\n#include \"sipe-common.h\"\n#include \"sipe-ft.h\"\n#include \"sipmsg.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-dialog.h\"\n#include \"sipe-session.h\"\n#include \"sipe-utils.h\"\n\nvoid sipe_dialog_free(struct sip_dialog *dialog)\n{\n\tGSList *entry;\n\tvoid *data;\n\n\tif (!dialog) return;\n\n\tg_free(dialog->with);\n\tg_free(dialog->endpoint_GUID);\n\tentry = dialog->routes;\n\twhile (entry) {\n\t\tdata = entry->data;\n\t\tentry = g_slist_remove(entry, data);\n\t\tg_free(data);\n\t}\n\tentry = dialog->supported;\n\twhile (entry) {\n\t\tdata = entry->data;\n\t\tentry = g_slist_remove(entry, data);\n\t\tg_free(data);\n\t}\n\n\twhile (dialog->filetransfers) {\n\t\tstruct sipe_file_transfer *ft = dialog->filetransfers->data;\n\t\tsipe_ft_free(ft);\n\t}\n\n\tg_free(dialog->callid);\n\tg_free(dialog->ourtag);\n\tg_free(dialog->theirtag);\n\tg_free(dialog->theirepid);\n\tg_free(dialog->request);\n\n\tg_free(dialog);\n}\n\nstruct sip_dialog *sipe_dialog_add(struct sip_session *session)\n{\n\tstruct sip_dialog *dialog = g_new0(struct sip_dialog, 1);\n\tsession->dialogs = g_slist_append(session->dialogs, dialog);\n\treturn(dialog);\n}\n\nstatic struct sip_dialog *\nsipe_dialog_find_3(struct sip_session *session,\n\t\t   struct sip_dialog *dialog_in)\n{\n\tif (session && dialog_in) {\n\t\tSIPE_DIALOG_FOREACH {\n\t\t\tif (\tdialog_in->callid &&\n\t\t\t\tdialog_in->ourtag &&\n\t\t\t\tdialog_in->theirtag &&\n\n\t\t\t\tdialog->callid &&\n\t\t\t\tdialog->ourtag &&\n\t\t\t\tdialog->theirtag &&\n\n\t\t\t\tsipe_strcase_equal(dialog_in->callid, dialog->callid) &&\n\t\t\t\tsipe_strcase_equal(dialog_in->ourtag, dialog->ourtag) &&\n\t\t\t\tsipe_strcase_equal(dialog_in->theirtag, dialog->theirtag))\n\t\t\t{\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_dialog_find_3 who='%s'\",\n\t\t\t\t\t\tdialog->with ? dialog->with : \"\");\n\t\t\t\treturn dialog;\n\t\t\t}\n\t\t} SIPE_DIALOG_FOREACH_END;\n\t}\n\treturn NULL;\n}\n\nstruct sip_dialog *sipe_dialog_find(struct sip_session *session,\n\t\t\t\t    const gchar *who)\n{\n\tif (session && who) {\n\t\tSIPE_DIALOG_FOREACH {\n\t\t\tif (dialog->with && sipe_strcase_equal(who, dialog->with)) {\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_dialog_find who='%s'\", who);\n\t\t\t\treturn dialog;\n\t\t\t}\n\t\t} SIPE_DIALOG_FOREACH_END;\n\t}\n\treturn NULL;\n}\n\nvoid sipe_dialog_remove(struct sip_session *session, const gchar *who)\n{\n\tstruct sip_dialog *dialog = sipe_dialog_find(session, who);\n\tif (dialog) {\n\t\tSIPE_DEBUG_INFO(\"sipe_dialog_remove who='%s' with='%s'\", who, dialog->with ? dialog->with : \"\");\n\t\tsession->dialogs = g_slist_remove(session->dialogs, dialog);\n\t\tsipe_dialog_free(dialog);\n\t}\n}\n\nvoid\nsipe_dialog_remove_3(struct sip_session *session,\n\t\t     struct sip_dialog *dialog_in)\n{\n\tstruct sip_dialog *dialog = sipe_dialog_find_3(session, dialog_in);\n\tif (dialog) {\n\t\tSIPE_DEBUG_INFO(\"sipe_dialog_remove_3 with='%s'\",\n\t\t\t\tdialog->with ? dialog->with : \"\");\n\t\tsession->dialogs = g_slist_remove(session->dialogs, dialog);\n\t\tsipe_dialog_free(dialog);\n\t}\n}\n\nvoid sipe_dialog_remove_all(struct sip_session *session)\n{\n\tGSList *entry = session->dialogs;\n\twhile (entry) {\n\t\tstruct sip_dialog *dialog = entry->data;\n\t\tentry = g_slist_remove(entry, dialog);\n\t\tsipe_dialog_free(dialog);\n\t}\n}\n\nstatic void sipe_dialog_parse_routes(struct sip_dialog *dialog,\n\t\t\t\t     const struct sipmsg *msg,\n\t\t\t\t     gboolean outgoing)\n{\n        GSList *hdr = msg->headers;\n\tgchar *contact = sipmsg_parse_contact_address(msg);\n\n\t/* Remove old routes */\n\twhile (dialog->routes) {\n\t\tvoid *data = dialog->routes->data;\n\t\tdialog->routes = g_slist_remove(dialog->routes, data);\n\t\tg_free(data);\n\t}\n\tg_free(dialog->request);\n        dialog->request = NULL;\n\n        while (hdr) {\n                struct sipnameval *elem = hdr->data;\n                if (sipe_strcase_equal(elem->name, \"Record-Route\")) {\n\t\t\tgchar **parts = g_strsplit(elem->value, \",\", 0);\n\t\t\tgchar **part = parts;\n\n\t\t\twhile (*part) {\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_dialog_parse_routes: route %s\", *part);\n\t\t\t\tdialog->routes = g_slist_append(dialog->routes,\n\t\t\t\t\t\t\t\tg_strdup(*part));\n\t\t\t\tpart++;\n\t\t\t}\n\t\t\tg_strfreev(parts);\n                }\n                hdr = g_slist_next(hdr);\n        }\n        if (outgoing) {\n\t\tdialog->routes = g_slist_reverse(dialog->routes);\n        }\n\n        if (contact) {\n\t\tdialog->request = contact;\n\t}\n\n\t/* logic for strict router only - RFC3261 - 12.2.1.1 */\n\t/* @TODO: proper check for presence of 'lr' PARAMETER in URI */\n\tif (dialog->routes && !strstr(dialog->routes->data, \";lr\")) {\n\t\tgchar *route = dialog->routes->data;\n\t\tdialog->request = sipmsg_find_part_of_header(route, \"<\", \">\", NULL);\n\t\tSIPE_DEBUG_INFO(\"sipe_dialog_parse_routes: strict route, contact %s\", dialog->request);\n\t\tdialog->routes = g_slist_remove(dialog->routes, route);\n\t\tg_free(route);\n\t\tif (contact) {\n\t\t\tdialog->routes = g_slist_append(dialog->routes,\n\t\t\t\t\t\t\tg_strdup_printf(\"<%s>\", contact));\n\t\t\tg_free(contact);\n\t\t}\n\t}\n}\n\nstatic void\nsipe_get_supported_header(const struct sipmsg *msg,\n\t\t\t  struct sip_dialog *dialog,\n\t\t\t  SIPE_UNUSED_PARAMETER gboolean outgoing)\n{\n\tGSList *hdr = msg->headers;\n\tstruct sipnameval *elem;\n\twhile(hdr)\n\t{\n\t\telem = hdr->data;\n\t\tif (sipe_strcase_equal(elem->name, \"Supported\")\n\t\t\t&& !g_slist_find_custom(dialog->supported, elem->value, (GCompareFunc)g_ascii_strcasecmp))\n\t\t{\n\t\t\tdialog->supported = g_slist_append(dialog->supported, g_strdup(elem->value));\n\n\t\t}\n\t\thdr = g_slist_next(hdr);\n\t}\n}\n\nstatic gchar *find_tag(const gchar *hdr)\n{\n\tgchar * tag = sipmsg_find_part_of_header (hdr, \"tag=\", \";\", NULL);\n\tif (!tag) {\n\t\t// In case it's at the end and there's no trailing ;\n\t\ttag = sipmsg_find_part_of_header (hdr, \"tag=\", NULL, NULL);\n\t}\n\treturn tag;\n}\n\nvoid sipe_dialog_parse(struct sip_dialog *dialog,\n\t\t       const struct sipmsg *msg,\n\t\t       gboolean outgoing)\n{\n\tconst gchar *us = outgoing ? \"From\" : \"To\";\n\tconst gchar *them = outgoing ? \"To\" : \"From\";\n\tconst gchar *session_expires_header;\n\n\tg_free(dialog->ourtag);\n\tg_free(dialog->theirtag);\n\n\tdialog->ourtag = find_tag(sipmsg_find_header(msg, us));\n\tdialog->theirtag = find_tag(sipmsg_find_header(msg, them));\n\tif (!dialog->theirepid) {\n\t\tdialog->theirepid = sipmsg_find_part_of_header(sipmsg_find_header(msg, them), \"epid=\", \";\", NULL);\n\t\tif (!dialog->theirepid) {\n\t\t\tdialog->theirepid = sipmsg_find_part_of_header(sipmsg_find_header(msg, them), \"epid=\", NULL, NULL);\n\t\t}\n\t}\n\n\t// Catch a tag on the end of the To Header and get rid of it.\n\tif (dialog->theirepid && strstr(dialog->theirepid, \"tag=\")) {\n\t\tdialog->theirepid = strtok(dialog->theirepid, \";\");\n\t}\n\n\tif ((session_expires_header = sipmsg_find_header(msg, \"Session-Expires\"))) {\n\t\tdialog->expires = atoi(session_expires_header);\n\t}\n\n\tsipe_dialog_parse_routes(dialog, msg, outgoing);\n\tsipe_get_supported_header(msg, dialog, outgoing);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-dialog.h",
    "content": "/**\n * @file sipe-dialog.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2009-11 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/*\n * Interface dependencies:\n *\n * <glib.h>\n */\n\n/* Forward declarations */\nstruct sipe_delayed_invite;\nstruct sipmsg;\n\n/* Helper macros to iterate over dialog list in a SIP session */\n#define SIPE_DIALOG_FOREACH {                            \\\n\tGSList *entry = session->dialogs;                \\\n\twhile (entry) {                                  \\\n\t\tstruct sip_dialog *dialog = entry->data; \\\n\t\tentry = entry->next;\n#define SIPE_DIALOG_FOREACH_END }}\n\n/* dialog is the new term for call-leg */\nstruct sip_dialog {\n\tgchar *with; /* URI */\n\tgchar *endpoint_GUID;\n\t/**\n\t *  >0 - pro\n\t *  <0 - contra\n\t *   0 - didn't participate\n\t */\n\tint election_vote;\n\tgchar *ourtag;\n\tgchar *theirtag;\n\tgchar *theirepid;\n\tgchar *callid;\n\tGSList *routes;\n\tgchar *request;\n\tGSList *supported; /* counterparty capabilities */\n\tGSList *filetransfers;\n\tint cseq;\n\t/** corresponds to Session-Expires SIP header value */\n\tint expires;\n\tgboolean is_established;\n\tstruct transaction *outgoing_invite;\n        struct sipe_delayed_invite *delayed_invite;\n};\n\n/* Forward declaration */\nstruct sip_session;\n\n/**\n * Free dialog structure\n *\n * @param dialog (in) Dialog to be freed. May be NULL.\n */\nvoid sipe_dialog_free(struct sip_dialog *dialog);\n\n/**\n * Add a new, empty dialog to a session\n *\n * @param session (in)\n *\n * @return dialog the new dialog structure\n */\nstruct sip_dialog *sipe_dialog_add(struct sip_session *session);\n\n/**\n * Find a dialog in a session\n *\n * @param session (in) may be NULL\n * @param who (in) dialog identifier. May be NULL\n *\n * @return dialog the requested dialog or NULL\n */\nstruct sip_dialog *sipe_dialog_find(struct sip_session *session,\n\t\t\t\t    const gchar *who);\n\n/**\n * Remove a dialog from a session\n *\n * @param session (in) may be NULL\n * @param who (in) dialog identifier. May be NULL\n */\nvoid sipe_dialog_remove(struct sip_session *session, const gchar *who);\n\n/**\n * Remove a dialog from a session\n *\n * @param session (in) may be NULL\n * @param dialog (in) dialog identifier. Should contain Call-ID, to-tag and from-tag\n *                    to unambiguously identify dialog. May be NULL\n */\nvoid\nsipe_dialog_remove_3(struct sip_session *session,\n\t\t     struct sip_dialog *dialog_in);\n\n/**\n * Remove all dialogs from a session\n *\n * @param session (in)\n */\nvoid sipe_dialog_remove_all(struct sip_session *session);\n\n/**\n * Does a session have any dialogs?\n *\n * @param session (in)\n */\n#define sipe_dialog_any(session) (session->dialogs != NULL)\n\n/**\n * Return first dialog of a session\n *\n * @param session (in)\n */\n#define sipe_dialog_first(session) ((struct sip_dialog *)session->dialogs->data)\n\n/**\n * Fill dialog structure from SIP message\n *\n * @param dialog   (in,out) dialog to fill\n * @param msg      (in)     mesage\n * @param outgoing (in)     outgoing or incoming message\n */\nvoid sipe_dialog_parse(struct sip_dialog *dialog,\n\t\t       const struct sipmsg *msg,\n\t\t       gboolean outgoing);\n"
  },
  {
    "path": "src/core/sipe-digest-nss.c",
    "content": "/**\n * @file sipe-digest-nss.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2016 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2010 pier11 <pier11@operamail.com>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/**\n * Digest routines implementation based on NSS.\n * Includes: SHA1, MD5, HMAC_SHA_1, HMAC_MD5\n */\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include \"glib.h\"\n\n#include \"nss.h\"\n/*\n * Work around a compiler error in NSS 3.13.x. Let's hope they fix it for\n * 3.14.x. See also: https://bugzilla.mozilla.org/show_bug.cgi?id=702090\n */\n#if (NSS_VMAJOR == 3) && (NSS_VMINOR == 13)\n#define __GNUC_MINOR __GNUC_MINOR__\n#endif\n#include \"pk11pub.h\"\n\n#include \"sipe-digest.h\"\n#if !(defined(HAVE_GSSAPI_ONLY) || defined(HAVE_SSPI))\n#include \"md4.h\"\n#endif\n\n\n/* PRIVATE methods */\n\nstatic PK11Context *sipe_digest_ctx_create(const SECOidTag algorithm)\n{\n\tPK11Context *context = PK11_CreateDigestContext(algorithm);\n\tPK11_DigestBegin(context);\n\treturn(context);\n}\n\nstatic PK11Context*\nsipe_digest_hmac_ctx_create(CK_MECHANISM_TYPE hmacMech, const guchar *key, gsize key_length)\n{\n\tPK11SlotInfo* slot;\n\tSECItem keyItem;\n\tSECItem noParams;\n\tPK11SymKey* SymKey;\n\tPK11Context* DigestContext;\n\n\t/* For key */\n\tslot = PK11_GetBestSlot(hmacMech, NULL);\n\n\tkeyItem.type = siBuffer;\n\tkeyItem.data = (unsigned char *)key;\n\tkeyItem.len = key_length;\n\n\tSymKey = PK11_ImportSymKey(slot, hmacMech, PK11_OriginUnwrap, CKA_SIGN,  &keyItem, NULL);\n\n\t/* Parameter for crypto context */\n\tnoParams.type = siBuffer;\n\tnoParams.data = NULL;\n\tnoParams.len = 0;\n\n\tDigestContext = PK11_CreateContextBySymKey(hmacMech, CKA_SIGN, SymKey, &noParams);\n\n\tPK11_DigestBegin(DigestContext);\n\n\tPK11_FreeSymKey(SymKey);\n\tPK11_FreeSlot(slot);\n\n\treturn DigestContext;\n}\n\nstatic void sipe_digest_ctx_append(PK11Context* DigestContext, const guchar *data, gsize data_length)\n{\n\tPK11_DigestOp(DigestContext, data, data_length);\n}\n\nstatic void sipe_digest_ctx_digest(PK11Context* DigestContext, guchar *digest, gsize digest_length)\n{\n\tunsigned int len;\n\n\tPK11_DigestFinal(DigestContext, digest, &len, digest_length);\n}\n\nstatic void sipe_digest_ctx_destroy(PK11Context* DigestContext)\n{\n\tPK11_DestroyContext(DigestContext, PR_TRUE);\n}\n\nstatic void sipe_digest(const SECOidTag algorithm,\n\t\t\tconst guchar *data, gsize data_length,\n\t\t\tguchar *digest, gsize digest_length)\n{\n\tvoid *DigestContext;\n\n\tDigestContext = sipe_digest_ctx_create(algorithm);\n\tsipe_digest_ctx_append(DigestContext, data, data_length);\n\tsipe_digest_ctx_digest(DigestContext, digest, digest_length);\n\tsipe_digest_ctx_destroy(DigestContext);\n}\n\nstatic void sipe_digest_hmac(CK_MECHANISM_TYPE hmacMech,\n\t\t\t     const guchar *key, gsize key_length,\n\t\t\t     const guchar *data, gsize data_length,\n\t\t\t     guchar *digest, gsize digest_length)\n{\n\tvoid *DigestContext;\n\n\tDigestContext = sipe_digest_hmac_ctx_create(hmacMech, key, key_length);\n\tsipe_digest_ctx_append(DigestContext, data, data_length);\n\tsipe_digest_ctx_digest(DigestContext, digest, digest_length);\n\tsipe_digest_ctx_destroy(DigestContext);\n}\n\n\n/* PUBLIC methods */\n\n#if !(defined(HAVE_GSSAPI_ONLY) || defined(HAVE_SSPI))\n/* One-shot MD4 digest - only used by internal NTLMv2 implementation */\nvoid sipe_digest_md4(const guchar *data, gsize length, guchar *digest)\n{\n\t/* NSS does not provide MD4 - use Mozilla Firefox implementation */\n\tmd4sum(data, length, digest);\n}\n#endif\n\nvoid sipe_digest_md5(const guchar *data, gsize length, guchar *digest)\n{\n\tsipe_digest(SEC_OID_MD5, data, length, digest, SIPE_DIGEST_MD5_LENGTH);\n}\n\nvoid sipe_digest_sha1(const guchar *data, gsize length, guchar *digest)\n{\n\tsipe_digest(SEC_OID_SHA1, data, length, digest, SIPE_DIGEST_SHA1_LENGTH);\n}\n\nvoid sipe_digest_hmac_md5(const guchar *key, gsize key_length,\n\t\t\t  const guchar *data, gsize data_length,\n\t\t\t  guchar *digest)\n{\n\tsipe_digest_hmac(CKM_MD5_HMAC, key, key_length, data, data_length, digest, SIPE_DIGEST_HMAC_MD5_LENGTH);\n}\n\nvoid sipe_digest_hmac_sha1(const guchar *key, gsize key_length,\n\t\t\t   const guchar *data, gsize data_length,\n\t\t\t   guchar *digest)\n{\n\tsipe_digest_hmac(CKM_SHA_1_HMAC, key, key_length, data, data_length, digest, SIPE_DIGEST_HMAC_SHA1_LENGTH);\n}\n\n/* Stream HMAC(SHA1) digest for file transfer */\ngpointer sipe_digest_ft_start(const guchar *sha1_digest)\n{\n\t/* used only the first 16 bytes of the 20 byte SHA1 digest */\n\treturn sipe_digest_hmac_ctx_create(CKM_SHA_1_HMAC, sha1_digest, 16);\n}\n\nvoid sipe_digest_ft_update(gpointer context, const guchar *data, gsize length)\n{\n\tsipe_digest_ctx_append(context, data, length);\n}\n\nvoid sipe_digest_ft_end(gpointer context, guchar *digest)\n{\n\tsipe_digest_ctx_digest(context, digest, SIPE_DIGEST_FILETRANSFER_LENGTH);\n}\n\nvoid sipe_digest_ft_destroy(gpointer context)\n{\n\tsipe_digest_ctx_destroy(context);\n}\n\n/* Stream digests, e.g. for TLS */\ngpointer sipe_digest_md5_start(void)\n{\n\treturn sipe_digest_ctx_create(SEC_OID_MD5);\n}\n\nvoid sipe_digest_md5_update(gpointer context, const guchar *data, gsize length)\n{\n\tsipe_digest_ctx_append(context, data, length);\n}\n\nvoid sipe_digest_md5_end(gpointer context, guchar *digest)\n{\n\tunsigned int saved_length;\n\t/* save context to ensure this function can be called multiple times */\n\tguchar *saved = PK11_SaveContextAlloc(context,\n\t\t\t\t\t      NULL,\n\t\t\t\t\t      0,\n\t\t\t\t\t      &saved_length);\n\tsipe_digest_ctx_digest(context, digest, SIPE_DIGEST_MD5_LENGTH);\n\tPK11_RestoreContext(context, saved, saved_length);\n\tPORT_Free(saved);\n}\n\nvoid sipe_digest_md5_destroy(gpointer context)\n{\n\tsipe_digest_ctx_destroy(context);\n}\n\ngpointer sipe_digest_sha1_start(void)\n{\n\treturn sipe_digest_ctx_create(SEC_OID_SHA1);\n}\n\nvoid sipe_digest_sha1_update(gpointer context, const guchar *data, gsize length)\n{\n\tsipe_digest_ctx_append(context, data, length);\n}\n\nvoid sipe_digest_sha1_end(gpointer context, guchar *digest)\n{\n\tunsigned int saved_length;\n\t/* save context to ensure this function can be called multiple times */\n\tguchar *saved = PK11_SaveContextAlloc(context,\n\t\t\t\t\t      NULL,\n\t\t\t\t\t      0,\n\t\t\t\t\t      &saved_length);\n\tsipe_digest_ctx_digest(context, digest, SIPE_DIGEST_SHA1_LENGTH);\n\tPK11_RestoreContext(context, saved, saved_length);\n\tPORT_Free(saved);\n}\n\nvoid sipe_digest_sha1_destroy(gpointer context)\n{\n\tsipe_digest_ctx_destroy(context);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-digest-openssl.c",
    "content": "/**\n * @file sipe-digest-openssl.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013-2017 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/**\n * Digest routines implementation based on OpenSSL\n */\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <openssl/evp.h>\n#include <openssl/hmac.h>\n#if !(defined(HAVE_GSSAPI_ONLY) || defined(HAVE_SSPI))\n#include <openssl/md4.h>\n#endif\n#include <openssl/md5.h>\n#include <openssl/opensslv.h>\n#include <openssl/sha.h>\n\n#include \"glib.h\"\n\n#include \"sipe-digest.h\"\n\n#if !(defined(HAVE_GSSAPI_ONLY) || defined(HAVE_SSPI))\n/* One-shot MD4 digest - only used by internal NTLMv2 implementation */\nvoid sipe_digest_md4(const guchar *data, gsize length, guchar *digest)\n{\n\tMD4(data, length, digest);\n}\n#endif\n\n/* One-shot MD5/SHA-1 digests */\nvoid sipe_digest_md5(const guchar *data, gsize length, guchar *digest)\n{\n\tMD5(data, length, digest);\n}\n\nvoid sipe_digest_sha1(const guchar *data, gsize length, guchar *digest)\n{\n\tSHA1(data, length, digest);\n}\n\n/* One-shot HMAC(MD5/SHA-1) digests */\nvoid sipe_digest_hmac_md5(const guchar *key, gsize key_length,\n\t\t\t  const guchar *data, gsize data_length,\n\t\t\t  guchar *digest)\n{\n\tHMAC(EVP_md5(), key, key_length, data, data_length, digest, NULL);\n}\n\nvoid sipe_digest_hmac_sha1(const guchar *key, gsize key_length,\n\t\t\t   const guchar *data, gsize data_length,\n\t\t\t   guchar *digest)\n{\n\tHMAC(EVP_sha1(), key, key_length, data, data_length, digest, NULL);\n}\n\n/* Stream HMAC(SHA1) digest for file transfer */\ngpointer sipe_digest_ft_start(const guchar *sha1_digest)\n{\n#if OPENSSL_VERSION_NUMBER < 0x10100000L\n\tHMAC_CTX *ctx = g_malloc(sizeof(HMAC_CTX));\n\tHMAC_CTX_init(ctx);\n#else\n\t/* OpenSSL 1.1.0 or newer */\n\tHMAC_CTX *ctx = HMAC_CTX_new();\n#endif\n\t/* used are only the first 16 bytes of the 20 byte SHA1 digest */\n\tHMAC_Init_ex(ctx, sha1_digest, 16, EVP_sha1(), NULL);\n\treturn(ctx);\n}\n\nvoid sipe_digest_ft_update(gpointer context, const guchar *data, gsize length)\n{\n\tHMAC_Update(context, data, length);\n}\n\nvoid sipe_digest_ft_end(gpointer context, guchar *digest)\n{\n\tHMAC_Final(context, digest, NULL);\n}\n\nvoid sipe_digest_ft_destroy(gpointer context)\n{\n#if OPENSSL_VERSION_NUMBER < 0x10100000L\n\tHMAC_CTX_cleanup(context);\n\tg_free(context);\n#else\n\t/* OpenSSL 1.1.0 or newer */\n\tHMAC_CTX_free(context);\n#endif\n}\n\n/* Stream digests, e.g. for TLS */\ngpointer sipe_digest_md5_start(void)\n{\n\tMD5_CTX *ctx = g_malloc(sizeof(MD5_CTX));\n\tMD5_Init(ctx);\n\treturn(ctx);\n}\n\nvoid sipe_digest_md5_update(gpointer context, const guchar *data, gsize length)\n{\n\tMD5_Update(context, data, length);\n}\n\nvoid sipe_digest_md5_end(gpointer context, guchar *digest)\n{\n\t/* save context to ensure this function can be called multiple times */\n\tMD5_CTX *orig_ctx = context;\n\tMD5_CTX saved_ctx = *orig_ctx;\n\tMD5_Final(digest, orig_ctx);\n\t*orig_ctx = saved_ctx;\n}\n\nvoid sipe_digest_md5_destroy(gpointer context)\n{\n\tg_free(context);\n}\n\ngpointer sipe_digest_sha1_start(void)\n{\n\tSHA_CTX *ctx = g_malloc(sizeof(SHA_CTX));\n\tSHA1_Init(ctx);\n\treturn(ctx);\n}\n\nvoid sipe_digest_sha1_update(gpointer context, const guchar *data, gsize length)\n{\n\tSHA1_Update(context, data, length);\n}\n\nvoid sipe_digest_sha1_end(gpointer context, guchar *digest)\n{\n\t/* save context to ensure this function can be called multiple times */\n\tSHA_CTX *orig_ctx = context;\n\tSHA_CTX saved_ctx = *orig_ctx;\n\tSHA1_Final(digest, orig_ctx);\n\t*orig_ctx = saved_ctx;\n}\n\nvoid sipe_digest_sha1_destroy(gpointer context)\n{\n\tg_free(context);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-digest.h",
    "content": "/**\n * @file sipe-digest.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Plain digests */\n/* NOTE: can only be used by internal NTLMv2 implementation */\n#define SIPE_DIGEST_MD4_LENGTH 16\nvoid sipe_digest_md4(const guchar *data, gsize length, guchar *digest);\n\n#define SIPE_DIGEST_MD5_LENGTH 16\nvoid sipe_digest_md5(const guchar *data, gsize length, guchar *digest);\n\n#define SIPE_DIGEST_SHA1_LENGTH 20\nvoid sipe_digest_sha1(const guchar *data, gsize length, guchar *digest);\n\n/* HMAC digests */\n#define SIPE_DIGEST_HMAC_MD5_LENGTH SIPE_DIGEST_MD5_LENGTH\nvoid sipe_digest_hmac_md5(const guchar *key, gsize key_length,\n\t\t\t  const guchar *data, gsize data_length,\n\t\t\t  guchar *digest);\n\n#define SIPE_DIGEST_HMAC_SHA1_LENGTH SIPE_DIGEST_SHA1_LENGTH\nvoid sipe_digest_hmac_sha1(const guchar *key, gsize key_length,\n\t\t\t  const guchar *data, gsize data_length,\n\t\t\t  guchar *digest);\n\n/* Stream HMAC(SHA1) digest for file transfer */\n#define SIPE_DIGEST_FILETRANSFER_LENGTH SIPE_DIGEST_SHA1_LENGTH\ngpointer sipe_digest_ft_start(const guchar *sha1_digest);\nvoid sipe_digest_ft_update(gpointer context, const guchar *data, gsize length);\nvoid sipe_digest_ft_end(gpointer context, guchar *digest);\nvoid sipe_digest_ft_destroy(gpointer context);\n\n/* Stream digests, e.g. for TLS */\ngpointer sipe_digest_md5_start(void);\nvoid sipe_digest_md5_update(gpointer context, const guchar *data, gsize length);\nvoid sipe_digest_md5_end(gpointer context, guchar *digest);\nvoid sipe_digest_md5_destroy(gpointer context);\ngpointer sipe_digest_sha1_start(void);\nvoid sipe_digest_sha1_update(gpointer context, const guchar *data, gsize length);\nvoid sipe_digest_sha1_end(gpointer context, guchar *digest);\nvoid sipe_digest_sha1_destroy(gpointer context);\n"
  },
  {
    "path": "src/core/sipe-domino.c",
    "content": "/**\n * @file sipe-domino.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2017 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2010 pier11 <pier11@operamail.com>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/**\nFor communication with Lotus Domino groupware server.\n\nServer requirements: Domino 5.0.2 and above with Web Access.\n\n1) Tries to read user's notes.ini for mail database name.\nWindows registry keys for notes.ini location:\nHKEY_CURRENT_USER\\Software\\Lotus\\Notes\\6.0\\NotesIniPath\n\n2) Authenticates to server (HTTPS POST, plaintext login/password over SSL)\nhttps://[domino_server]/[databasename].nsf/?Login\nContent-Type=application/x-www-form-urlencoded\nUsername=[email]&Password=[password] (params are url-encoded)\nSaves auth cookie.\nSet-Cookie=DomAuthSessId=17D0428F7B9D57D4D0B064AE42FD21F9; path=/\n\n3) Queries Calendar data (HTTPS GET, result is XML)\nhttps://[domino_server]/[databasename].nsf/[viewname]?ReadViewEntries\nhttps://[domino_server]/[databasename].nsf/($Calendar)?ReadViewEntries&KeyType=time&StartKey=20090805T000000Z&UntilKey=20090806T000000Z&Count=-1&TZType=UTC\nUses auth cookie.\nCookie=DomAuthSessId=17D0428F7B9D57D4D0B064AE42FD21F9\n\nIt is able to retrieve our Calendar information (Meetings schedule,\nsubject and location) from Lotus Domino for subsequent publishing.\n\nRef. for more implementation details:\nhttps://sourceforge.net/tracker/?func=detail&aid=2945346&group_id=194563&atid=949934\n\nSimilar functionality for iCalendar/CalDAV/Google would be great to implement too.\n*/\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <string.h>\n#include <ctype.h>\n#include <stdio.h>\n#include <errno.h>\n#include <time.h>\n\n#include <glib.h>\n\n/* for registry read */\n#ifdef _WIN32\n#include \"sipe-win32dep.h\"\n#endif\n\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n#include \"sipe-cal.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-domino.h\"\n#include \"sipe-http.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n\n/**\n * POST request for Login to Domino server\n * @param email      (%s) Should be URL-encoded. Ex.: alice@cosmo.local\n * @param password   (%s) Should be URL-encoded.\n */\n#define SIPE_DOMINO_LOGIN_REQUEST \\\n\"Username=%s&Password=%s\"\n\n/**\n * GET request to Domino server\n * to obtain our Calendar information.\n * @param start_time (%s) Ex.: 20090805T000000Z\n * @param end_time   (%s) Ex.: 20090806T000000Z\n */\n#define SIPE_DOMINO_CALENDAR_REQUEST \\\n\"/($Calendar)?ReadViewEntries&KeyType=time&StartKey=%s&UntilKey=%s&Count=-1&TZType=UTC\"\n\n/*\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<viewentries timestamp=\"20100416T112140,02Z\" toplevelentries=\"77\" rangeentries=\"\n1000\">\n\t<viewentry position=\"77\" unid=\"C3A77CC76EAA7D08802576FD0043D7D0\" noteid=\"27B42\" siblings=\"77\">\n\t\t<entrydata columnnumber=\"0\" name=\"$134\">\n\t\t\t<datetime>20100423T103000,00Z</datetime>\n\t\t</entrydata>\n\t\t<entrydata columnnumber=\"1\" name=\"$149\">\n\t\t\t<number>158</number>\n\t\t</entrydata>\n\t\t<entrydata columnnumber=\"2\" name=\"$144\">\n\t\t\t<datetime>20100423T103000,00Z</datetime>\n\t\t</entrydata>\n\t\t<entrydata columnnumber=\"3\" name=\"$145\">\n\t\t\t<text>-</text>\n\t\t</entrydata>\n\t\t<entrydata columnnumber=\"4\" name=\"$146\">\n\t\t\t<datetime>20100423T120000,00Z</datetime>\n\t\t</entrydata>\n\t\t<entrydata columnnumber=\"5\" name=\"$147\">\n\t\t\t<textlist>\n\t\t\t\t<text>G. S. ..I. L. T. Hall</text>\n\t\t\t\t<text>Location: Auditorium - W. House</text>\n\t\t\t\t<text>Chair: S. S.</text>\n\t\t\t</textlist>\n\t\t</entrydata>\n\t</viewentry>\n\t<viewentry .........\n</viewentries>\n*/\n\n#define VIEWENTITY_START0_TIME\t\"$134\"\n#define VIEWENTITY_START_TIME\t\"$144\"\n#define VIEWENTITY_END_TIME\t\"$146\"\n#define VIEWENTITY_TEXT_LIST\t\"$147\"\n\n\nstatic int\nsipe_domino_get_slot_no(time_t fb_start, time_t in)\n{\n\treturn (in - fb_start) / SIPE_FREE_BUSY_GRANULARITY_SEC;\n}\n\nstatic char *\nsipe_domino_get_free_busy(time_t fb_start,\n\t\t\t  GSList *cal_events)\n{\n\tGSList *entry = cal_events;\n\tchar *res;\n\n\tif (!cal_events) return NULL;\n\n\tres = g_strnfill(SIPE_FREE_BUSY_PERIOD_SEC / SIPE_FREE_BUSY_GRANULARITY_SEC,\n\t\t\t SIPE_CAL_FREE + '0');\n\n\twhile (entry) {\n\t\tstruct sipe_cal_event *cal_event = entry->data;\n\t\tint start = sipe_domino_get_slot_no(fb_start, cal_event->start_time);\n\t\tint end = sipe_domino_get_slot_no(fb_start, (cal_event->end_time - 1));\n\t\tint i;\n\n\t\tfor (i = start; i <= end; i++) {\n\t\t\tres[i] = SIPE_CAL_BUSY + '0';\n\t\t}\n\t\tentry = entry->next;\n\t}\n\tSIPE_DEBUG_INFO(\"sipe_domino_get_free_busy: res=\\n%s\", res);\n\treturn res;\n}\n\nstatic void sipe_domino_process_calendar_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t  guint status,\n\t\t\t\t\t\t  GSList *headers,\n\t\t\t\t\t\t  const gchar *body,\n\t\t\t\t\t\t  gpointer data)\n{\n\tstruct sipe_calendar *cal = data;\n\tconst gchar *content_type = sipe_utils_nameval_find(headers, \"Content-Type\");\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_domino_process_calendar_response: cb started.\");\n\n\tcal->request = NULL;\n\n\tif (content_type && !g_str_has_prefix(content_type, \"text/xml\")) {\n\t\tcal->is_domino_disabled = TRUE;\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_domino_process_calendar_response: not XML, disabling.\");\n\t\treturn;\n\t}\n\n\tif ((status == SIPE_HTTP_STATUS_OK) && body) {\n\t\tconst sipe_xml *node, *node2, *node3;\n\t\tsipe_xml *xml;\n\n\t\tSIPE_DEBUG_INFO(\"sipe_domino_process_calendar_response: SUCCESS, ret=%d\", status);\n\t\txml = sipe_xml_parse(body, strlen(body));\n\n\t\tsipe_cal_events_free(cal->cal_events);\n\t\tcal->cal_events = NULL;\n\t\t/* viewentry */\n\t\tfor (node = sipe_xml_child(xml, \"viewentry\");\n\t\t     node;\n\t\t     node = sipe_xml_twin(node))\n\t\t{\n\t\t\tstruct sipe_cal_event *cal_event = g_new0(struct sipe_cal_event, 1);\n\t\t\tcal->cal_events = g_slist_append(cal->cal_events, cal_event);\n\t\t\tcal_event->cal_status = SIPE_CAL_BUSY;\n\t\t\tcal_event->is_meeting = TRUE;\n\n\t\t\t/* SIPE_DEBUG_INFO(\"viewentry unid=%s\", sipe_xml_attribute(node, \"unid\")); */\n\n\t\t\t/* entrydata */\n\t\t\tfor (node2 = sipe_xml_child(node, \"entrydata\");\n\t\t\t     node2;\n\t\t\t     node2 = sipe_xml_twin(node2))\n\t\t\t{\n\t\t\t\tconst char *name = sipe_xml_attribute(node2, \"name\");\n\n\t\t\t\tSIPE_DEBUG_INFO(\"\\tentrydata name=%s\", name);\n\n\t\t\t\tif (sipe_strequal(name, VIEWENTITY_START0_TIME) ||\n\t\t\t\t    sipe_strequal(name, VIEWENTITY_START_TIME) ||\n\t\t\t\t    sipe_strequal(name, VIEWENTITY_END_TIME))\n\t\t\t\t{\n\t\t\t\t\tchar *tmp = sipe_xml_data(sipe_xml_child(node2, \"datetime\"));\n\t\t\t\t\ttime_t time_val = sipe_utils_str_to_time(tmp);\n\n\t\t\t\t\tif (sipe_strequal(name, VIEWENTITY_START_TIME)) {\n\t\t\t\t\t\tcal_event->start_time = time_val;\n\t\t\t\t\t} else if (sipe_strequal(name, VIEWENTITY_END_TIME)) {\n\t\t\t\t\t\tcal_event->end_time = time_val;\n\t\t\t\t\t}\n\n\t\t\t\t\tSIPE_DEBUG_INFO(\"\\t\\tdatetime=%s\", sipe_utils_time_to_debug_str(gmtime(&time_val)));\n\t\t\t\t\tg_free(tmp);\n\t\t\t\t} else if (sipe_strequal(name, VIEWENTITY_TEXT_LIST)) {\n\t\t\t\t\tint i = 0;\n\n\t\t\t\t\t/* test */\n\t\t\t\t\tfor (node3 = sipe_xml_child(node2, \"textlist/text\");\n\t\t\t\t\t     node3;\n\t\t\t\t\t     node3 = sipe_xml_twin(node3))\n\t\t\t\t\t{\n\t\t\t\t\t\tchar *tmp = sipe_xml_data(node3);\n\n\t\t\t\t\t\tif (!tmp) continue;\n\n\t\t\t\t\t\tSIPE_DEBUG_INFO(\"\\t\\ttext=%s\", tmp);\n\t\t\t\t\t\tif (i == 0) {\n\t\t\t\t\t\t\tcal_event->subject = g_strdup(tmp);\n\t\t\t\t\t\t\tSIPE_DEBUG_INFO(\"\\t\\t*Subj.=%s\", tmp);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t/* plain English, don't localize! */\n\t\t\t\t\t\t\tif (!g_ascii_strncasecmp(tmp, \"Location:\", 9)) {\n\t\t\t\t\t\t\t\tif (strlen(tmp) > 9) {\n\t\t\t\t\t\t\t\t\tcal_event->location = g_strdup(g_strstrip(tmp+9));\n\t\t\t\t\t\t\t\t\tSIPE_DEBUG_INFO(\"\\t\\t*Loc.=%s\", cal_event->location);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t/* Translators: (!) should be as in localized Lotus Notes to be able to extract meeting location */\n\t\t\t\t\t\t\t} else if (g_str_has_prefix(tmp, _(\"Location:\"))) {\n\t\t\t\t\t\t\t\tguint len = strlen(_(\"Location:\"));\n\t\t\t\t\t\t\t\tif (strlen(tmp) > len) {\n\t\t\t\t\t\t\t\t\tcal_event->location = g_strdup(g_strstrip(tmp+len));\n\t\t\t\t\t\t\t\t\tSIPE_DEBUG_INFO(\"\\t\\t*Loc.=%s\", cal_event->location);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\tg_free(tmp);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tsipe_xml_free(xml);\n\n\t\t/* creates FreeBusy from cal->cal_events */\n\t\tg_free(cal->free_busy);\n\t\tcal->free_busy = sipe_domino_get_free_busy(cal->fb_start, cal->cal_events);\n\n\t\t/* update SIP server */\n\t\tcal->is_updated = TRUE;\n\t\tsipe_cal_presence_publish(sipe_private, TRUE);\n\n\t} else if (!headers) {\n\t\tSIPE_DEBUG_INFO(\"sipe_domino_process_calendar_response: rather FAILURE, ret=%d\", status);\n\t}\n\n\tsipe_http_session_close(cal->session);\n\tcal->session = NULL;\n}\n\n/* Domino doesn't like '-' and ':' in ISO timestamps */\nstatic gchar *\nsipe_domino_time_to_str(time_t timestamp)\n{\n\tchar *res, *tmp;\n\n\tres = sipe_utils_time_to_str(timestamp);\n\tres = sipe_utils_str_replace((tmp = res), \"-\", \"\");\n\tg_free(tmp);\n\tres = sipe_utils_str_replace((tmp = res), \":\", \"\");\n\tg_free(tmp);\n\n\treturn res;\n}\n\nstatic void sipe_domino_send_http_request(struct sipe_calendar *cal)\n{\n\tif (cal->request) {\n\t\tsipe_core_email_authentication(cal->sipe_private,\n\t\t\t\t\t       cal->request);\n\t\tsipe_http_request_session(cal->request, cal->session);\n\t\tsipe_http_request_ready(cal->request);\n\t}\n}\n\nstatic void sipe_domino_do_calendar_request(struct sipe_calendar *cal)\n{\n\tif (cal->domino_url) {\n\t\tchar *url_req;\n\t\tchar *url;\n\t\ttime_t end;\n\t\ttime_t now = time(NULL);\n\t\tchar *start_str;\n\t\tchar *end_str;\n\t\tstruct tm *now_tm;\n\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_domino_do_calendar_request: going Calendar req.\");\n\n\t\tnow_tm = gmtime(&now);\n\t\t/* start -1 day, 00:00:00 */\n\t\tnow_tm->tm_sec = 0;\n\t\tnow_tm->tm_min = 0;\n\t\tnow_tm->tm_hour = 0;\n\t\tcal->fb_start = sipe_mktime_tz(now_tm, \"UTC\");\n\t\tcal->fb_start -= 24*60*60;\n\t\t/* end = start + 4 days - 1 sec */\n\t\tend = cal->fb_start + SIPE_FREE_BUSY_PERIOD_SEC - 1;\n\n\t\tstart_str = sipe_domino_time_to_str(cal->fb_start);\n\t\tend_str = sipe_domino_time_to_str(end);\n\n\t\turl_req = g_strdup_printf(SIPE_DOMINO_CALENDAR_REQUEST, start_str, end_str);\n\t\tg_free(start_str);\n\t\tg_free(end_str);\n\n\t\turl = g_strconcat(cal->domino_url, url_req, NULL);\n\t\tg_free(url_req);\n\t\tcal->request = sipe_http_request_get(cal->sipe_private,\n\t\t\t\t\t\t     url,\n\t\t\t\t\t\t     NULL,\n\t\t\t\t\t\t     sipe_domino_process_calendar_response,\n\t\t\t\t\t\t     cal);\n\t\tg_free(url);\n\n\t\tsipe_domino_send_http_request(cal);\n\t}\n}\n\nstatic void sipe_domino_process_login_response(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private,\n\t\t\t\t\t       guint status,\n\t\t\t\t\t       GSList *headers,\n\t\t\t\t\t       /* temporary? */\n\t\t\t\t\t       SIPE_UNUSED_PARAMETER const gchar *body,\n\t\t\t\t\t       gpointer data)\n{\n\tstruct sipe_calendar *cal = data;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_domino_process_login_response: cb started.\");\n\n\tcal->request = NULL;\n\n\tif ((status >= SIPE_HTTP_STATUS_OK) &&\n\t    (status <  SIPE_HTTP_STATUS_CLIENT_ERROR)) {\n\t\tSIPE_DEBUG_INFO(\"sipe_domino_process_login_response: rather SUCCESS, ret=%d\", status);\n\n\t\t/* next query */\n\t\tsipe_domino_do_calendar_request(cal);\n\n\t} else if (!headers ||\n\t\t   (status >= SIPE_HTTP_STATUS_CLIENT_ERROR)) {\n\t\tSIPE_DEBUG_INFO(\"sipe_domino_process_login_response: rather FAILURE, ret=%d\", status);\n\n\t\t/* stop here */\n\t\t/* cal->is_domino_disabled = TRUE; */\n\t}\n}\n\nstatic gchar *sipe_domino_uri_escape(const gchar *string)\n{\n\tif (!string) return(NULL);\n\tif (!g_utf8_validate(string, -1, NULL)) return(NULL);\n\n\treturn(g_uri_escape_string(string, NULL, FALSE));\n}\n\nstatic void\nsipe_domino_do_login_request(struct sipe_calendar *cal)\n{\n\tif (cal->domino_url) {\n\t\tstruct sipe_core_private *sipe_private = cal->sipe_private;\n\t\tchar *body;\n\t\tconst char *content_type = \"application/x-www-form-urlencoded\";\n\t\tchar *login_url = g_strconcat(cal->domino_url, \"/?Login\", NULL);\n\t\tchar *user;\n\t\tgchar *password = sipe_private->email_password ? sipe_private->email_password : sipe_private->password;\n\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_domino_do_login_request: going Login req.\");\n\n\t\tif (!password) return;\n\n\t\t/* @TODO replace purple_url_encode() with non-purple equiv. */\n\t\tuser     = sipe_domino_uri_escape(cal->email);\n\t\tpassword = sipe_domino_uri_escape(password);\n\n\t\tbody = g_strdup_printf(SIPE_DOMINO_LOGIN_REQUEST, user, password);\n\t\tg_free(user);\n\t\tg_free(password);\n\n\t\tcal->request = sipe_http_request_post(sipe_private,\n\t\t\t\t\t\t      login_url,\n\t\t\t\t\t\t      NULL,\n\t\t\t\t\t\t      body,\n\t\t\t\t\t\t      content_type,\n\t\t\t\t\t\t      sipe_domino_process_login_response,\n\t\t\t\t\t\t      cal);\n\t\tg_free(login_url);\n\t\tg_free(body);\n\n\t\tsipe_domino_send_http_request(cal);\n\t}\n}\n\n/* in notes.ni\nMailFile=mail5\\mhe111bm.nsf\nMailServer=CN=MSGM2222/OU=srv/O=xxcom\n\nOutput values should be freed if requested.\n*/\nstatic void\nsipe_domino_read_notes_ini(const char *filename_with_path, char **mail_server, char **mail_file)\n{\n\tchar rbuf[256];\n\tFILE *fp = fopen(filename_with_path, \"r+\");\n\n\tif (fp) {\n\t\twhile (fgets(rbuf, sizeof (rbuf), fp)) {\n\t\t\tchar *prop = \"MailFile=\";\n\t\t\tguint prop_len = strlen(prop);\n\n\t\t\t/* SIPE_DEBUG_INFO(\"\\t%s (%\"G_GSIZE_FORMAT\")\", rbuf, strlen(rbuf)); */\n\t\t\tif (mail_file && !g_ascii_strncasecmp(rbuf, prop, prop_len) && (strlen(rbuf) > prop_len)) {\n\t\t\t\t*mail_file = g_strdup(g_strstrip((rbuf+prop_len)));\n\t\t\t}\n\n\t\t\tprop = \"MailServer=\";\n\t\t\tprop_len = strlen(prop);\n\n\t\t\tif (mail_server && !g_ascii_strncasecmp(rbuf, prop, prop_len) && (strlen(rbuf) > prop_len)) {\n\t\t\t\t*mail_server = g_strdup(g_strstrip((rbuf+prop_len)));\n\t\t\t}\n\t\t}\n\t\tfclose(fp);\n\t} else {\n\t\tSIPE_DEBUG_ERROR(\"sipe_domino_read_notes_ini(): could not open `%s': %s\", filename_with_path, g_strerror (errno));\n\t}\n}\n\n/**\n@param protocol\t\tEx.: https\n@param mail_server\tEx.: CN=MSGM2222/OU=srv/O=xxcom\n@param mail_file\tEx.: mail5\\mhe111bm.nsf\n\n@return\t\t\tEx.: https://msgm2222/mail5/mhe111bm.nsf\n*/\nstatic char *\nsipe_domino_compose_url(const char *protocol, const char *mail_server, const char *mail_file)\n{\n\tconst char *ptr;\n\tchar *tmp, *tmp2, *tmp3;\n\n\tg_return_val_if_fail(protocol, NULL);\n\tg_return_val_if_fail(mail_server, NULL);\n\tg_return_val_if_fail(mail_file, NULL);\n\n\t/* mail_server: exptacting just common name */\n\tif ((ptr = strstr(mail_server, \"/\"))) {\n\t\ttmp = g_strndup(mail_server, (ptr-mail_server));\n\t} else {\n\t\ttmp = g_strdup(mail_server);\n\t}\n\tif ((!g_ascii_strncasecmp(tmp, \"CN=\", 3))) {\n\t\ttmp2 = g_strdup(tmp+3);\n\t} else {\n\t\ttmp2 = g_strdup(tmp);\n\t}\n\tg_free(tmp);\n\ttmp = g_ascii_strdown(tmp2, -1);\n\tg_free(tmp2);\n\n\t/* mail_file */\n\ttmp3 = sipe_utils_str_replace(mail_file, \"\\\\\", \"/\");\n\n\ttmp2 = g_strconcat(protocol, \"://\", tmp, \"/\", tmp3, NULL);\n\tg_free(tmp);\n\tg_free(tmp3);\n\n\treturn tmp2;\n}\n\nvoid\nsipe_domino_update_calendar(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_calendar* cal;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_domino_update_calendar: started.\");\n\n\tsipe_cal_calendar_init(sipe_private);\n\n\t/* check if URL is valid if provided */\n\tcal = sipe_private->calendar;\n\tif (cal && !is_empty(cal->domino_url)) {\n\t\tchar *tmp = g_ascii_strdown(cal->domino_url, -1);\n\t\tif (!g_str_has_suffix(tmp, \".nsf\")) {\n\t\t\t/* not valid Domino mail services URL */\n\t\t\tcal->is_domino_disabled = TRUE;\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_domino_update_calendar: invalid Domino URI supplied, disabling.\");\n\t\t}\n\t\tg_free(tmp);\n\t}\n\n\t/* Autodiscovery.\n\t * Searches location of notes.ini in Registry, reads it, extracts mail server and mail file,\n\t * composes HTTPS URL to Domino web, basing on that\n\t */\n\tif (cal && is_empty(cal->domino_url)) {\n\t\tchar *path = NULL;\n#ifdef _WIN32\n\t\t/* fine for Notes 8.5 too */\n\t\tpath = wpurple_read_reg_expand_string(HKEY_CURRENT_USER, \"Software\\\\Lotus\\\\Notes\\\\8.0\", \"NotesIniPath\");\n\t\tif (is_empty(path)) {\n\t\t\tg_free(path);\n\t\t\tpath = wpurple_read_reg_expand_string(HKEY_CURRENT_USER, \"Software\\\\Lotus\\\\Notes\\\\7.0\", \"NotesIniPath\");\n\t\t\tif (is_empty(path)) {\n\t\t\t\tg_free(path);\n\t\t\t\tpath = wpurple_read_reg_expand_string(HKEY_CURRENT_USER, \"Software\\\\Lotus\\\\Notes\\\\6.0\", \"NotesIniPath\");\n\t\t\t\tif (is_empty(path)) {\n\t\t\t\t\tg_free(path);\n\t\t\t\t\tpath = wpurple_read_reg_expand_string(HKEY_CURRENT_USER, \"Software\\\\Lotus\\\\Notes\\\\5.0\", \"NotesIniPath\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tSIPE_DEBUG_INFO(\"sipe_domino_update_calendar: notes.ini path:\\n%s\", path ? path : \"\");\n#else\n\t\t/* How to know location of notes.ini on *NIX ? */\n#endif\n\n\t\t/* get server url */\n\t\tif (path) {\n\t\t\tchar *mail_server = NULL;\n\t\t\tchar *mail_file = NULL;\n\n\t\t\tsipe_domino_read_notes_ini(path, &mail_server, &mail_file);\n\t\t\tg_free(path);\n\t\t\tSIPE_DEBUG_INFO(\"sipe_domino_update_calendar: mail_server=%s\", mail_server ? mail_server : \"\");\n\t\t\tSIPE_DEBUG_INFO(\"sipe_domino_update_calendar: mail_file=%s\", mail_file ? mail_file : \"\");\n\n\t\t\tg_free(cal->domino_url);\n\t\t\tcal->domino_url = sipe_domino_compose_url(\"https\", mail_server, mail_file);\n\t\t\tg_free(mail_server);\n\t\t\tg_free(mail_file);\n\t\t\tSIPE_DEBUG_INFO(\"sipe_domino_update_calendar: cal->domino_url=%s\", cal->domino_url ? cal->domino_url : \"\");\n\t\t} else {\n\t\t\t/* No domino_url, no path discovered, disabling */\n\t\t\tcal->is_domino_disabled = TRUE;\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_domino_update_calendar: Domino URI hasn't been discovered, neither provided, disabling.\");\n\t\t}\n\t}\n\n\tif (cal) {\n\n\t\tif (cal->is_domino_disabled) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_domino_update_calendar: disabled, exiting.\");\n\t\t\treturn;\n\t\t}\n\n\t\t/* re-create session */\n\t\tsipe_http_session_close(cal->session);\n\t\tcal->session = sipe_http_session_start();\n\n\t\tsipe_domino_do_login_request(cal);\n\t}\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_domino_update_calendar: finished.\");\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-domino.h",
    "content": "/**\n * @file sipe-domino.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010 pier11 <pier11@operamail.com>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\n\n/**\n * Connects to Lotus Domino Web Access server,\n * pulls out our Calendar information\n * and publishes it to Office Communications server.\n *\n * Advised schedule: 30 minutes.\n */\nvoid\nsipe_domino_update_calendar(struct sipe_core_private *sipe_private);\n"
  },
  {
    "path": "src/core/sipe-ews-autodiscover.c",
    "content": "/**\n * @file sipe-ews-autodiscover.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013-2015 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n * Specification references:\n *\n *   - POX: plain old XML autodiscover\n *   - [MS-OXDSCLI]:     http://msdn.microsoft.com/en-us/library/cc463896.aspx\n *   - Autdiscover for Exchange:\n *                       http://msdn.microsoft.com/en-us/library/office/jj900169.aspx\n *   - POX autodiscover: http://msdn.microsoft.com/en-us/library/office/aa581522.aspx\n *   - POX redirect:     http://msdn.microsoft.com/en-us/library/office/dn467392.aspx\n */\n\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-ews-autodiscover.h\"\n#include \"sipe-http.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n\nstruct sipe_ews_autodiscover_cb {\n\tsipe_ews_autodiscover_callback *cb;\n\tgpointer cb_data;\n};\n\nstruct autodiscover_method {\n\tconst gchar *template;\n\tgboolean redirect;\n};\n\nstruct sipe_ews_autodiscover {\n\tstruct sipe_ews_autodiscover_data *data;\n\tstruct sipe_http_request *request;\n\tGSList *callbacks;\n\tgchar *email;\n\tconst struct autodiscover_method *method;\n\tgboolean retry;\n\tgboolean completed;\n};\n\nstatic void sipe_ews_autodiscover_complete(struct sipe_core_private *sipe_private,\n\t\t\t\t\t   struct sipe_ews_autodiscover_data *ews_data)\n{\n\tstruct sipe_ews_autodiscover *sea = sipe_private->ews_autodiscover;\n\tGSList *entry = sea->callbacks;\n\n\twhile (entry) {\n\t\tstruct sipe_ews_autodiscover_cb *sea_cb = entry->data;\n\t\tsea_cb->cb(sipe_private, ews_data, sea_cb->cb_data);\n\t\tg_free(sea_cb);\n\t\tentry = entry->next;\n\t}\n\tg_slist_free(sea->callbacks);\n\tsea->callbacks = NULL;\n\tsea->completed = TRUE;\n}\n\nstatic void sipe_ews_autodiscover_request(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  gboolean next_method);\nstatic gboolean sipe_ews_autodiscover_url(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  const gchar *url);\nstatic void sipe_ews_autodiscover_parse(struct sipe_core_private *sipe_private,\n\t\t\t\t\tconst gchar *body)\n{\n\tstruct sipe_ews_autodiscover *sea = sipe_private->ews_autodiscover;\n\tstruct sipe_ews_autodiscover_data *ews_data = sea->data =\n\t\tg_new0(struct sipe_ews_autodiscover_data, 1);\n\tsipe_xml *xml = sipe_xml_parse(body, strlen(body));\n\tconst sipe_xml *account = sipe_xml_child(xml, \"Response/Account\");\n\tgboolean complete = TRUE;\n\n\t/* valid POX autodiscover response? */\n\tif (account) {\n\t\tconst sipe_xml *node;\n\n\t\t/* POX autodiscover settings? */\n\t\tif ((node = sipe_xml_child(account, \"Protocol\")) != NULL) {\n\n\t\t\t/* Autodiscover/Response/User/LegacyDN (requires trimming) */\n\t\t\tgchar *tmp = sipe_xml_data(sipe_xml_child(xml,\n\t\t\t\t\t\t\t\t  \"Response/User/LegacyDN\"));\n\t\t\tif (tmp)\n\t\t\t\tews_data->legacy_dn = g_strstrip(tmp);\n\n\t\t\t/* extract settings */\n\t\t\tfor (; node; node = sipe_xml_twin(node)) {\n\t\t\t\tgchar *type = sipe_xml_data(sipe_xml_child(node,\n\t\t\t\t\t\t\t\t\t   \"Type\"));\n\n\t\t\t\t/* Exchange or Office 365 */\n\t\t\t\tif (sipe_strequal(\"EXCH\", type) ||\n\t\t\t\t    sipe_strequal(\"EXPR\", type)) {\n\n#define _URL(name, field) \\\n\t\t\tif (!ews_data->field) {\t\\\n\t\t\t\tews_data->field = sipe_xml_data(sipe_xml_child(node, #name)); \\\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_ews_autodiscover_parse: \" #field \" = '%s'\", \\\n\t\t\t\t\t\tews_data->field ? ews_data->field : \"<NOT FOUND>\"); \\\n\t\t\t}\n\n\t\t\t\t\t/* use first entry */\n\t\t\t\t\t_URL(ASUrl,  as_url);\n\t\t\t\t\t_URL(EwsUrl, ews_url);\n\t\t\t\t\t_URL(OABUrl, oab_url);\n\t\t\t\t\t_URL(OOFUrl, oof_url);\n#undef _URL\n\n\t\t\t\t}\n\t\t\t\tg_free(type);\n\t\t\t}\n\n\t\t/* POX autodiscover redirect to new email address? */\n\t\t} else if ((node = sipe_xml_child(account, \"RedirectAddr\")) != NULL) {\n\t\t\tgchar *addr = sipe_xml_data(node);\n\n\t\t\t/*\n\t\t\t * Sanity checks for new email address:\n\t\t\t *  - must contain a \"@\" character\n\t\t\t *  - must be different from current address\n\t\t\t */\n\t\t\tif (addr && strchr(addr, '@') &&\n\t\t\t    !sipe_strequal(sea->email, addr)) {\n\t\t\t\tg_free(sea->email);\n\t\t\t\tsea->email = addr;\n\t\t\t\taddr = NULL; /* sea takes ownership */\n\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_ews_autodiscover_parse: restarting with email address '%s'\",\n\t\t\t\t\t\tsea->email);\n\n\t\t\t\t/* restart process with new email address */\n\t\t\t\tsea->method = NULL;\n\t\t\t\tcomplete    = FALSE;\n\t\t\t\tsipe_ews_autodiscover_request(sipe_private,\n\t\t\t\t\t\t\t      TRUE);\n\t\t\t}\n\t\t\tg_free(addr);\n\n\t\t/* POX autodiscover redirect to new URL? */\n\t\t} else if ((node = sipe_xml_child(account, \"RedirectUrl\")) != NULL) {\n\t\t\tgchar *url = sipe_xml_data(node);\n\n\t\t\tif (!is_empty(url)) {\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_ews_autodiscover_parse: redirected to URL '%s'\",\n\t\t\t\t\t\turl);\n\t\t\t\tcomplete = !sipe_ews_autodiscover_url(sipe_private,\n\t\t\t\t\t\t\t\t      url);\n\t\t\t}\n\t\t\tg_free(url);\n\n\t\t/* ignore all other POX autodiscover responses */\n\t\t} else {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_ews_autodiscover_parse: unknown response detected\");\n\t\t}\n\t}\n\tsipe_xml_free(xml);\n\n\tif (complete)\n\t\tsipe_ews_autodiscover_complete(sipe_private, ews_data);\n}\n\nstatic void sipe_ews_autodiscover_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\t   guint status,\n\t\t\t\t\t   GSList *headers,\n\t\t\t\t\t   const gchar *body,\n\t\t\t\t\t   gpointer data)\n{\n\tstruct sipe_ews_autodiscover *sea = data;\n\tconst gchar *type = sipe_utils_nameval_find(headers, \"Content-Type\");\n\n\tsea->request = NULL;\n\n\tswitch (status) {\n\tcase SIPE_HTTP_STATUS_OK:\n\t\t/* only accept XML responses */\n\t\tif (body && g_str_has_prefix(type, \"text/xml\"))\n\t\t\tsipe_ews_autodiscover_parse(sipe_private, body);\n\t\telse\n\t\t\tsipe_ews_autodiscover_request(sipe_private, TRUE);\n\t\tbreak;\n\n\tcase SIPE_HTTP_STATUS_CLIENT_FORBIDDEN:\n\t\t/*\n\t\t * Authentication succeeded but we still weren't allowed to\n\t\t * view the page. At least at our work place this error is\n\t\t * temporary, i.e. the next access with the exact same\n\t\t * authentication succeeds.\n\t\t *\n\t\t * Let's try again, but only once...\n\t\t */\n\t\tsipe_ews_autodiscover_request(sipe_private, !sea->retry);\n\t\tbreak;\n\n\tcase SIPE_HTTP_STATUS_ABORTED:\n\t\t/* we are not allowed to generate new requests */\n\t\tbreak;\n\n\tdefault:\n\t\tsipe_ews_autodiscover_request(sipe_private, TRUE);\n\t\tbreak;\n\t}\n}\n\nstatic gboolean sipe_ews_autodiscover_url(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  const gchar *url)\n{\n\tstruct sipe_ews_autodiscover *sea = sipe_private->ews_autodiscover;\n\tgchar *body = g_strdup_printf(\"<Autodiscover xmlns=\\\"http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006\\\">\"\n\t\t\t\t      \" <Request>\"\n\t\t\t\t      \"  <EMailAddress>%s</EMailAddress>\"\n\t\t\t\t      \"  <AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>\"\n\t\t\t\t      \" </Request>\"\n\t\t\t\t      \"</Autodiscover>\",\n\t\t\t\t      sea->email);\n\n\tSIPE_DEBUG_INFO(\"sipe_ews_autodiscover_url: trying '%s'\", url);\n\n\tsea->request = sipe_http_request_post(sipe_private,\n\t\t\t\t\t      url,\n\t\t\t\t\t      \"Accept: text/xml\\r\\n\",\n\t\t\t\t\t      body,\n\t\t\t\t\t      \"text/xml\",\n\t\t\t\t\t      sipe_ews_autodiscover_response,\n\t\t\t\t\t      sea);\n\tg_free(body);\n\n\tif (sea->request) {\n\t\tsipe_core_email_authentication(sipe_private,\n\t\t\t\t\t       sea->request);\n\t\tsipe_http_request_allow_redirect(sea->request);\n\t\tsipe_http_request_ready(sea->request);\n\t\treturn(TRUE);\n\t}\n\n\treturn(FALSE);\n}\n\nstatic void sipe_ews_autodiscover_redirect_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t    guint status,\n\t\t\t\t\t\t    GSList *headers,\n\t\t\t\t\t\t    SIPE_UNUSED_PARAMETER const gchar *body,\n\t\t\t\t\t\t    gpointer data)\n{\n\tstruct sipe_ews_autodiscover *sea = data;\n\tgboolean failed = (status != (guint) SIPE_HTTP_STATUS_ABORTED);\n\n\tsea->request = NULL;\n\n\t/* Start attempt with URL from redirect (3xx) response */\n\tif ((status >= SIPE_HTTP_STATUS_REDIRECTION) &&\n\t    (status <  SIPE_HTTP_STATUS_CLIENT_ERROR)) {\n\t\tconst gchar *location = sipe_utils_nameval_find_instance(headers,\n\t\t\t\t\t\t\t\t\t \"Location\",\n\t\t\t\t\t\t\t\t\t 0);\n\t\tif (location)\n\t\t\tfailed = !sipe_ews_autodiscover_url(sipe_private,\n\t\t\t\t\t\t\t    location);\n\t}\n\n\tif (failed)\n\t\tsipe_ews_autodiscover_request(sipe_private, TRUE);\n}\n\nstatic gboolean sipe_ews_autodiscover_redirect(struct sipe_core_private *sipe_private,\n\t\t\t\t\t       const gchar *url)\n{\n\tstruct sipe_ews_autodiscover *sea = sipe_private->ews_autodiscover;\n\n\tSIPE_DEBUG_INFO(\"sipe_ews_autodiscover_redirect: trying '%s'\", url);\n\n\tsea->request = sipe_http_request_get(sipe_private,\n\t\t\t\t\t     url,\n\t\t\t\t\t     NULL,\n\t\t\t\t\t     sipe_ews_autodiscover_redirect_response,\n\t\t\t\t\t     sea);\n\n\tif (sea->request) {\n\t\tsipe_http_request_ready(sea->request);\n\t\treturn(TRUE);\n\t}\n\n\treturn(FALSE);\n}\n\nstatic void sipe_ews_autodiscover_request(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  gboolean next_method)\n{\n\tstruct sipe_ews_autodiscover *sea = sipe_private->ews_autodiscover;\n\tstatic const struct autodiscover_method methods[] = {\n\t\t{ \"https://Autodiscover.%s/Autodiscover/Autodiscover.xml\", FALSE },\n\t\t{ \"http://Autodiscover.%s/Autodiscover/Autodiscover.xml\",  TRUE  },\n\t\t{ \"http://Autodiscover.%s/Autodiscover/Autodiscover.xml\",  FALSE },\n\t\t{ \"https://%s/Autodiscover/Autodiscover.xml\",              FALSE },\n\t\t{ NULL,                                                    FALSE },\n\t};\n\n\tsea->retry = next_method;\n\tif (sea->method) {\n\t\tif (next_method)\n\t\t\tsea->method++;\n\t} else\n\t\tsea->method = methods;\n\n\tif (sea->method->template) {\n\t\tgchar *url = g_strdup_printf(sea->method->template,\n\t\t\t\t\t     strstr(sea->email, \"@\") + 1);\n\n\t\tif (!(sea->method->redirect ?\n\t\t      sipe_ews_autodiscover_redirect(sipe_private, url) :\n\t\t      sipe_ews_autodiscover_url(sipe_private, url)))\n\t\t\tsipe_ews_autodiscover_request(sipe_private, TRUE);\n\n\t\tg_free(url);\n\n\t} else {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_ews_autodiscover_request: no more methods to try!\");\n\t\tsipe_ews_autodiscover_complete(sipe_private, NULL);\n\t}\n}\n\nvoid sipe_ews_autodiscover_start(struct sipe_core_private *sipe_private,\n\t\t\t\t sipe_ews_autodiscover_callback *callback,\n\t\t\t\t gpointer callback_data)\n{\n\tstruct sipe_ews_autodiscover *sea = sipe_private->ews_autodiscover;\n\n\tif (sea->completed) {\n\t\t(*callback)(sipe_private, sea->data, callback_data);\n\t} else {\n\t\tstruct sipe_ews_autodiscover_cb *sea_cb = g_new(struct sipe_ews_autodiscover_cb, 1);\n\t\tsea_cb->cb      = callback;\n\t\tsea_cb->cb_data = callback_data;\n\t\tsea->callbacks  = g_slist_prepend(sea->callbacks, sea_cb);\n\n\t\tif (!sea->method)\n\t\t\tsipe_ews_autodiscover_request(sipe_private, TRUE);\n\t}\n}\n\nvoid sipe_ews_autodiscover_init(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_ews_autodiscover *sea = g_new0(struct sipe_ews_autodiscover, 1);\n\n\tsea->email = g_strdup(sipe_private->email);\n\n\tsipe_private->ews_autodiscover = sea;\n}\n\nvoid sipe_ews_autodiscover_free(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_ews_autodiscover *sea = sipe_private->ews_autodiscover;\n\tstruct sipe_ews_autodiscover_data *ews_data = sea->data;\n\tsipe_ews_autodiscover_complete(sipe_private, NULL);\n\tif (ews_data) {\n\t\tg_free((gchar *)ews_data->as_url);\n\t\tg_free((gchar *)ews_data->ews_url);\n\t\tg_free((gchar *)ews_data->legacy_dn);\n\t\tg_free((gchar *)ews_data->oab_url);\n\t\tg_free((gchar *)ews_data->oof_url);\n\t\tg_free(ews_data);\n\t}\n\tg_free(sea->email);\n\tg_free(sea);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-ews-autodiscover.h",
    "content": "/**\n * @file sipe-ews-autodiscover.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\n\n/* EWS data determined by autodiscover */\nstruct sipe_ews_autodiscover_data {\n    const gchar *as_url;\n    const gchar *ews_url;\n    const gchar *legacy_dn;\n    const gchar *oab_url;\n    const gchar *oof_url;\n};\n\n/**\n *\n * EWS autodiscover callback\n *\n * @param sipe_private  SIPE core private data\n * @param ews_data      EWS autodiscover data (NULL when failed/aborted)\n * @param callback_data callback data\n */\ntypedef void (sipe_ews_autodiscover_callback)(struct sipe_core_private *sipe_private,\n\t\t\t\t\t      const struct sipe_ews_autodiscover_data *ews_data,\n\t\t\t\t\t      gpointer callback_data);\n\n/**\n * Trigger EWS autodiscover\n *\n * @param sipe_private  SIPE core private data\n * @param callback      callback function\n * @param callback_data callback data\n */\nvoid sipe_ews_autodiscover_start(struct sipe_core_private *sipe_private,\n\t\t\t\t sipe_ews_autodiscover_callback *callback,\n\t\t\t\t gpointer callback_data);\n\n/**\n * Initialize EWS autodiscover data\n *\n * @param sipe_private SIPE core private data\n */\nvoid sipe_ews_autodiscover_init(struct sipe_core_private *sipe_private);\n\n/**\n * Free EWS autodiscover data\n *\n * @param sipe_private SIPE core private data\n */\nvoid sipe_ews_autodiscover_free(struct sipe_core_private *sipe_private);\n"
  },
  {
    "path": "src/core/sipe-ews.c",
    "content": "/**\n * @file sipe-ews.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2015 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2010, 2009 pier11 <pier11@operamail.com>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/**\nFor communication with Exchange 2007/2010 Web Server/Web Services:\n\n1) Autodiscover (HTTPS POST request). With redirect support. XML content.\n1.1) DNS SRV record _autodiscover._tcp.<domain> may also be resolved.\n2) Availability Web service (SOAP = HTTPS POST + XML) call.\n3) Out of Office (OOF) Web Service (SOAP = HTTPS POST + XML) call.\n4) Web server authentication required - NTLM and/or Negotiate (Kerberos).\n\nNote: ews - EWS stands for Exchange Web Services.\n\nIt will be able to retrieve our Calendar information (FreeBusy, WorkingHours,\nMeetings Subject and Location, Is_Meeting) as well as our Out of Office (OOF) note\nfrom Exchange Web Services for subsequent publishing.\n\nRef. for more implementation details:\nhttp://sourceforge.net/projects/sipe/forums/forum/688535/topic/3403462\n\nSimilar functionality for Lotus Notes/Domino, iCalendar/CalDAV/Google would\nbe great to implement too.\n*/\n\n#include <string.h>\n#include <time.h>\n\n#include <glib.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n#include \"sipe-cal.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-ews.h\"\n#include \"sipe-ews-autodiscover.h\"\n#include \"sipe-http.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n\n/**\n * GetUserOofSettingsRequest SOAP request to Exchange Web Services\n * to obtain our Out-of-office (OOF) information.\n * @param email (%s) Ex.: alice@cosmo.local\n */\n#define SIPE_EWS_USER_OOF_SETTINGS_REQUEST \\\n\"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\"\\\n\"<soap:Envelope xmlns:xsi=\\\"http://www.w3.org/2001/XMLSchema-instance\\\" xmlns:xsd=\\\"http://www.w3.org/2001/XMLSchema\\\" xmlns:soap=\\\"http://schemas.xmlsoap.org/soap/envelope/\\\">\"\\\n  \"<soap:Body>\"\\\n    \"<GetUserOofSettingsRequest xmlns=\\\"http://schemas.microsoft.com/exchange/services/2006/messages\\\">\"\\\n      \"<Mailbox xmlns=\\\"http://schemas.microsoft.com/exchange/services/2006/types\\\">\"\\\n        \"<Address>%s</Address>\"\\\n      \"</Mailbox>\"\\\n    \"</GetUserOofSettingsRequest>\"\\\n  \"</soap:Body>\"\\\n\"</soap:Envelope>\"\n\n/**\n * GetUserAvailabilityRequest SOAP request to Exchange Web Services\n * to obtain our Availability (FreeBusy, WorkingHours, Meetings) information.\n * @param email      (%s) Ex.: alice@cosmo.local\n * @param start_time (%s) Ex.: 2009-12-06T00:00:00\n * @param end_time   (%s) Ex.: 2009-12-09T23:59:59\n */\n#define SIPE_EWS_USER_AVAILABILITY_REQUEST \\\n\"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\"\\\n\"<soap:Envelope xmlns:xsi=\\\"http://www.w3.org/2001/XMLSchema-instance\\\"\"\\\n              \" xmlns:xsd=\\\"http://www.w3.org/2001/XMLSchema\\\"\"\\\n              \" xmlns:soap=\\\"http://schemas.xmlsoap.org/soap/envelope/\\\"\"\\\n              \" xmlns:t=\\\"http://schemas.microsoft.com/exchange/services/2006/types\\\">\"\\\n  \"<soap:Body>\"\\\n    \"<GetUserAvailabilityRequest xmlns=\\\"http://schemas.microsoft.com/exchange/services/2006/messages\\\"\"\\\n                \" xmlns:t=\\\"http://schemas.microsoft.com/exchange/services/2006/types\\\">\"\\\n      \"<t:TimeZone xmlns=\\\"http://schemas.microsoft.com/exchange/services/2006/types\\\">\"\\\n        \"<Bias>0</Bias>\"\\\n        \"<StandardTime>\"\\\n          \"<Bias>0</Bias>\"\\\n          \"<Time>00:00:00</Time>\"\\\n          \"<DayOrder>0</DayOrder>\"\\\n          \"<Month>0</Month>\"\\\n          \"<DayOfWeek>Sunday</DayOfWeek>\"\\\n        \"</StandardTime>\"\\\n        \"<DaylightTime>\"\\\n          \"<Bias>0</Bias>\"\\\n          \"<Time>00:00:00</Time>\"\\\n          \"<DayOrder>0</DayOrder>\"\\\n          \"<Month>0</Month>\"\\\n          \"<DayOfWeek>Sunday</DayOfWeek>\"\\\n        \"</DaylightTime>\"\\\n      \"</t:TimeZone>\"\\\n      \"<MailboxDataArray>\"\\\n        \"<t:MailboxData>\"\\\n          \"<t:Email>\"\\\n            \"<t:Address>%s</t:Address>\"\\\n          \"</t:Email>\"\\\n          \"<t:AttendeeType>Required</t:AttendeeType>\"\\\n          \"<t:ExcludeConflicts>false</t:ExcludeConflicts>\"\\\n        \"</t:MailboxData>\"\\\n      \"</MailboxDataArray>\"\\\n      \"<t:FreeBusyViewOptions>\"\\\n        \"<t:TimeWindow>\"\\\n          \"<t:StartTime>%s</t:StartTime>\"\\\n          \"<t:EndTime>%s</t:EndTime>\"\\\n        \"</t:TimeWindow>\"\\\n        \"<t:MergedFreeBusyIntervalInMinutes>15</t:MergedFreeBusyIntervalInMinutes>\"\\\n        \"<t:RequestedView>DetailedMerged</t:RequestedView>\"\\\n      \"</t:FreeBusyViewOptions>\"\\\n    \"</GetUserAvailabilityRequest>\"\\\n  \"</soap:Body>\"\\\n\"</soap:Envelope>\"\n\n#define SIPE_EWS_STATE_IDLE\t\t\t 0\n#define SIPE_EWS_STATE_AUTODISCOVER_TRIGGERED\t 1\n#define SIPE_EWS_STATE_AVAILABILITY_SUCCESS\t 2\n#define SIPE_EWS_STATE_AVAILABILITY_FAILURE\t-2\n#define SIPE_EWS_STATE_OOF_SUCCESS\t\t 3\n#define SIPE_EWS_STATE_OOF_FAILURE\t\t-3\n\nchar *\nsipe_ews_get_oof_note(struct sipe_calendar *cal)\n{\n\ttime_t now = time(NULL);\n\n\tif (!cal || !cal->oof_state) return NULL;\n\n\tif (sipe_strequal(cal->oof_state, \"Enabled\") ||\n\t    (sipe_strequal(cal->oof_state, \"Scheduled\") && now >= cal->oof_start && now <= cal->oof_end))\n\t{\n\t\treturn cal->oof_note;\n\t}\n\telse\n\t{\n\t\treturn NULL;\n\t}\n}\n\nstatic void\nsipe_ews_run_state_machine(struct sipe_calendar *cal);\n\nstatic void sipe_ews_process_avail_response(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private,\n\t\t\t\t\t    guint status,\n\t\t\t\t\t    SIPE_UNUSED_PARAMETER GSList *headers,\n\t\t\t\t\t    const gchar *body,\n\t\t\t\t\t    gpointer data)\n{\n\tstruct sipe_calendar *cal = data;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_ews_process_avail_response: cb started.\");\n\n\tcal->request = NULL;\n\n\tif ((status == SIPE_HTTP_STATUS_OK) && body) {\n\t\tconst sipe_xml *node;\n\t\tconst sipe_xml *resp;\n\t\t/** ref: [MS-OXWAVLS] */\n\t\tsipe_xml *xml = sipe_xml_parse(body, strlen(body));\n\t\t/*\nEnvelope/Body/GetUserAvailabilityResponse/FreeBusyResponseArray/FreeBusyResponse/ResponseMessage@ResponseClass=\"Success\"\nEnvelope/Body/GetUserAvailabilityResponse/FreeBusyResponseArray/FreeBusyResponse/FreeBusyView/MergedFreeBusy\nEnvelope/Body/GetUserAvailabilityResponse/FreeBusyResponseArray/FreeBusyResponse/FreeBusyView/CalendarEventArray/CalendarEvent\nEnvelope/Body/GetUserAvailabilityResponse/FreeBusyResponseArray/FreeBusyResponse/FreeBusyView/WorkingHours\n\t\t */\n\t\tresp = sipe_xml_child(xml, \"Body/GetUserAvailabilityResponse/FreeBusyResponseArray/FreeBusyResponse\");\n\t\tif (!resp) return; /* rather soap:Fault */\n\t\tif (!sipe_strequal(sipe_xml_attribute(sipe_xml_child(resp, \"ResponseMessage\"), \"ResponseClass\"), \"Success\")) {\n\t\t\treturn; /* Error response */\n\t\t}\n\n\t\t/* MergedFreeBusy */\n\t\tg_free(cal->free_busy);\n\t\tcal->free_busy = sipe_xml_data(sipe_xml_child(resp, \"FreeBusyView/MergedFreeBusy\"));\n\n\t\t/* WorkingHours */\n\t\tnode = sipe_xml_child(resp, \"FreeBusyView/WorkingHours\");\n\t\tg_free(cal->working_hours_xml_str);\n\t\tcal->working_hours_xml_str = sipe_xml_stringify(node);\n\t\tSIPE_DEBUG_INFO(\"sipe_ews_process_avail_response: cal->working_hours_xml_str:\\n%s\",\n\t\t\t\tcal->working_hours_xml_str ? cal->working_hours_xml_str : \"\");\n\n\t\tsipe_cal_events_free(cal->cal_events);\n\t\tcal->cal_events = NULL;\n\t\t/* CalendarEvents */\n\t\tfor (node = sipe_xml_child(resp, \"FreeBusyView/CalendarEventArray/CalendarEvent\");\n\t\t     node;\n\t\t     node = sipe_xml_twin(node))\n\t\t{\n\t\t\tchar *tmp;\n/*\n      <CalendarEvent>\n\t<StartTime>2009-12-07T13:30:00</StartTime>\n\t<EndTime>2009-12-07T14:30:00</EndTime>\n\t<BusyType>Busy</BusyType>\n\t<CalendarEventDetails>\n\t  <ID>0000000...</ID>\n\t  <Subject>Lunch</Subject>\n\t  <Location>Cafe</Location>\n\t  <IsMeeting>false</IsMeeting>\n\t  <IsRecurring>true</IsRecurring>\n\t  <IsException>false</IsException>\n\t  <IsReminderSet>true</IsReminderSet>\n\t  <IsPrivate>false</IsPrivate>\n\t</CalendarEventDetails>\n      </CalendarEvent>\n*/\n\t\t\tstruct sipe_cal_event *cal_event = g_new0(struct sipe_cal_event, 1);\n\t\t\tcal->cal_events = g_slist_append(cal->cal_events, cal_event);\n\n\t\t\ttmp = sipe_xml_data(sipe_xml_child(node, \"StartTime\"));\n\t\t\tcal_event->start_time = sipe_utils_str_to_time(tmp);\n\t\t\tg_free(tmp);\n\n\t\t\ttmp = sipe_xml_data(sipe_xml_child(node, \"EndTime\"));\n\t\t\tcal_event->end_time = sipe_utils_str_to_time(tmp);\n\t\t\tg_free(tmp);\n\n\t\t\ttmp = sipe_xml_data(sipe_xml_child(node, \"BusyType\"));\n\t\t\tif (sipe_strequal(\"Free\", tmp)) {\n\t\t\t\tcal_event->cal_status = SIPE_CAL_FREE;\n\t\t\t} else if (sipe_strequal(\"Tentative\", tmp)) {\n\t\t\t\tcal_event->cal_status = SIPE_CAL_TENTATIVE;\n\t\t\t} else if (sipe_strequal(\"Busy\", tmp)) {\n\t\t\t\tcal_event->cal_status = SIPE_CAL_BUSY;\n\t\t\t} else if (sipe_strequal(\"OOF\", tmp)) {\n\t\t\t\tcal_event->cal_status = SIPE_CAL_OOF;\n\t\t\t} else {\n\t\t\t\tcal_event->cal_status = SIPE_CAL_NO_DATA;\n\t\t\t}\n\t\t\tg_free(tmp);\n\n\t\t\tcal_event->subject = sipe_xml_data(sipe_xml_child(node, \"CalendarEventDetails/Subject\"));\n\t\t\tcal_event->location = sipe_xml_data(sipe_xml_child(node, \"CalendarEventDetails/Location\"));\n\n\t\t\ttmp = sipe_xml_data(sipe_xml_child(node, \"CalendarEventDetails/IsMeeting\"));\n\t\t\tcal_event->is_meeting = tmp ? sipe_strequal(tmp, \"true\") : TRUE;\n\t\t\tg_free(tmp);\n\t\t}\n\n\t\tsipe_xml_free(xml);\n\n\t\tcal->state = SIPE_EWS_STATE_AVAILABILITY_SUCCESS;\n\t\tsipe_ews_run_state_machine(cal);\n\n\t} else {\n\t\tcal->state = SIPE_EWS_STATE_AVAILABILITY_FAILURE;\n\t\tsipe_ews_run_state_machine(cal);\n\t}\n}\n\nstatic void sipe_ews_process_oof_response(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private,\n\t\t\t\t\t  guint status,\n\t\t\t\t\t  SIPE_UNUSED_PARAMETER GSList *headers,\n\t\t\t\t\t  const gchar *body,\n\t\t\t\t\t  gpointer data)\n{\n\tstruct sipe_calendar *cal = data;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_ews_process_oof_response: cb started.\");\n\n\tcal->request = NULL;\n\n\tif ((status == SIPE_HTTP_STATUS_OK) && body) {\n\t\tchar *old_note;\n\t\tconst sipe_xml *resp;\n\t\tconst sipe_xml *xn_duration;\n\t\t/** ref: [MS-OXWOOF] */\n\t\tsipe_xml *xml = sipe_xml_parse(body, strlen(body));\n\t\t/* Envelope/Body/GetUserOofSettingsResponse/ResponseMessage@ResponseClass=\"Success\"\n\t\t * Envelope/Body/GetUserOofSettingsResponse/OofSettings/OofState=Enabled\n\t\t * Envelope/Body/GetUserOofSettingsResponse/OofSettings/Duration/StartTime\n\t\t * Envelope/Body/GetUserOofSettingsResponse/OofSettings/Duration/EndTime\n\t\t * Envelope/Body/GetUserOofSettingsResponse/OofSettings/InternalReply/Message\n\t\t */\n\t\tresp = sipe_xml_child(xml, \"Body/GetUserOofSettingsResponse\");\n\t\tif (!resp) return; /* rather soap:Fault */\n\t\tif (!sipe_strequal(sipe_xml_attribute(sipe_xml_child(resp, \"ResponseMessage\"), \"ResponseClass\"), \"Success\")) {\n\t\t\treturn; /* Error response */\n\t\t}\n\n\t\tg_free(cal->oof_state);\n\t\tcal->oof_state = sipe_xml_data(sipe_xml_child(resp, \"OofSettings/OofState\"));\n\n\t\told_note = cal->oof_note;\n\t\tcal->oof_note = NULL;\n\t\tif (!sipe_strequal(cal->oof_state, \"Disabled\")) {\n\t\t\tchar *tmp = sipe_xml_data(\n\t\t\t\tsipe_xml_child(resp, \"OofSettings/InternalReply/Message\"));\n\t\t\tchar *html;\n\n\t\t\t/* UTF-8 encoded BOM (0xEF 0xBB 0xBF) as a signature to mark the beginning of a UTF-8 file */\n\t\t\tif (g_str_has_prefix(tmp, \"\\xEF\\xBB\\xBF\")) {\n\t\t\t\thtml = g_strdup(tmp+3);\n\t\t\t} else {\n\t\t\t\thtml = g_strdup(tmp);\n\t\t\t}\n\t\t\tg_free(tmp);\n\t\t\ttmp = g_strstrip(sipe_backend_markup_strip_html(html));\n\t\t\tg_free(html);\n\t\t\tcal->oof_note = g_markup_escape_text(tmp, -1);\n\t\t\tg_free(tmp);\n\t\t}\n\n\t\tif (sipe_strequal(cal->oof_state, \"Scheduled\")\n\t\t    && (xn_duration = sipe_xml_child(resp, \"OofSettings/Duration\")))\n\t\t{\n\t\t\tchar *tmp = sipe_xml_data(sipe_xml_child(xn_duration, \"StartTime\"));\n\t\t\tcal->oof_start = sipe_utils_str_to_time(tmp);\n\t\t\tg_free(tmp);\n\n\t\t\ttmp = sipe_xml_data(sipe_xml_child(xn_duration, \"EndTime\"));\n\t\t\tcal->oof_end = sipe_utils_str_to_time(tmp);\n\t\t\tg_free(tmp);\n\t\t}\n\n\t\tif (!sipe_strequal(old_note, cal->oof_note)) { /* oof note changed */\n\t\t\tcal->updated = time(NULL);\n\t\t\tcal->published = FALSE;\n\t\t}\n\t\tg_free(old_note);\n\n\t\tsipe_xml_free(xml);\n\n\t\tcal->state = SIPE_EWS_STATE_OOF_SUCCESS;\n\t\tsipe_ews_run_state_machine(cal);\n\n\t} else {\n\t\tcal->state = SIPE_EWS_STATE_OOF_FAILURE;\n\t\tsipe_ews_run_state_machine(cal);\n\t}\n}\n\nstatic void sipe_ews_send_http_request(struct sipe_calendar *cal)\n{\n\tif (cal->request) {\n\t\tsipe_core_email_authentication(cal->sipe_private,\n\t\t\t\t\t       cal->request);\n\t\tsipe_http_request_allow_redirect(cal->request);\n\t\tsipe_http_request_ready(cal->request);\n\t}\n}\n\nstatic void sipe_ews_do_avail_request(struct sipe_calendar *cal)\n{\n\tif (cal->as_url) {\n\t\tchar *body;\n\t\ttime_t end;\n\t\ttime_t now = time(NULL);\n\t\tchar *start_str;\n\t\tchar *end_str;\n\t\tstruct tm *now_tm;\n\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_ews_do_avail_request: going Availability req.\");\n\n\t\tnow_tm = gmtime(&now);\n\t\t/* start -1 day, 00:00:00 */\n\t\tnow_tm->tm_sec = 0;\n\t\tnow_tm->tm_min = 0;\n\t\tnow_tm->tm_hour = 0;\n\t\tcal->fb_start = sipe_mktime_tz(now_tm, \"UTC\");\n\t\tcal->fb_start -= 24*60*60;\n\t\t/* end = start + 4 days - 1 sec */\n\t\tend = cal->fb_start + SIPE_FREE_BUSY_PERIOD_SEC - 1;\n\n\t\tstart_str = sipe_utils_time_to_str(cal->fb_start);\n\t\tend_str = sipe_utils_time_to_str(end);\n\n\t\tbody = g_strdup_printf(SIPE_EWS_USER_AVAILABILITY_REQUEST, cal->email, start_str, end_str);\n\t\tcal->request = sipe_http_request_post(cal->sipe_private,\n\t\t\t\t\t\t      cal->as_url,\n\t\t\t\t\t\t      NULL,\n\t\t\t\t\t\t      body,\n\t\t\t\t\t\t      \"text/xml; charset=UTF-8\",\n\t\t\t\t\t\t      sipe_ews_process_avail_response,\n\t\t\t\t\t\t      cal);\n\t\tg_free(body);\n\t\tg_free(start_str);\n\t\tg_free(end_str);\n\n\t\tsipe_ews_send_http_request(cal);\n\t}\n}\n\nstatic void sipe_ews_do_oof_request(struct sipe_calendar *cal)\n{\n\tif (cal->oof_url) {\n\t\tchar *body;\n\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_ews_do_oof_request: going OOF req.\");\n\n\t\tbody = g_strdup_printf(SIPE_EWS_USER_OOF_SETTINGS_REQUEST, cal->email);\n\t\tcal->request = sipe_http_request_post(cal->sipe_private,\n\t\t\t\t\t\t      cal->as_url,\n\t\t\t\t\t\t      NULL,\n\t\t\t\t\t\t      body,\n\t\t\t\t\t\t      \"text/xml; charset=UTF-8\",\n\t\t\t\t\t\t      sipe_ews_process_oof_response,\n\t\t\t\t\t\t      cal);\n\t\tg_free(body);\n\n\t\tsipe_ews_send_http_request(cal);\n\t}\n}\n\nstatic void\nsipe_ews_run_state_machine(struct sipe_calendar *cal)\n{\n\tswitch (cal->state) {\n\tcase SIPE_EWS_STATE_AVAILABILITY_FAILURE:\n\tcase SIPE_EWS_STATE_OOF_FAILURE:\n\t\tcal->is_ews_disabled = TRUE;\n\t\tbreak;\n\tcase SIPE_EWS_STATE_IDLE:\n\t\tsipe_ews_do_avail_request(cal);\n\t\tbreak;\n\tcase SIPE_EWS_STATE_AUTODISCOVER_TRIGGERED:\n\t\t/* do nothing */\n\t\tbreak;\n\tcase SIPE_EWS_STATE_AVAILABILITY_SUCCESS:\n\t\tsipe_ews_do_oof_request(cal);\n\t\tbreak;\n\tcase SIPE_EWS_STATE_OOF_SUCCESS:\n\t\t{\n\t\t\tstruct sipe_core_private *sipe_private = cal->sipe_private;\n\n\t\t\tcal->state = SIPE_EWS_STATE_IDLE;\n\t\t\tcal->is_updated = TRUE;\n\t\t\tsipe_cal_presence_publish(sipe_private, TRUE);\n\t\t}\n\t\tbreak;\n\t}\n}\n\nstatic void sipe_calendar_ews_autodiscover_cb(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private,\n\t\t\t\t\t      const struct sipe_ews_autodiscover_data *ews_data,\n\t\t\t\t\t      gpointer callback_data)\n{\n\tstruct sipe_calendar *cal = callback_data;\n\n\tif (ews_data) {\n\t\tcal->as_url    = g_strdup(ews_data->as_url);\n\t\tcal->legacy_dn = g_strdup(ews_data->legacy_dn);\n\t\tcal->oab_url   = g_strdup(ews_data->oab_url);\n\t\tcal->oof_url   = g_strdup(ews_data->oof_url);\n\t\tcal->state     = SIPE_EWS_STATE_IDLE;\n\t\tsipe_ews_run_state_machine(cal);\n\t} else {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_calendar_ews_autodiscover_cb: EWS disabled\");\n\t\tcal->is_ews_disabled = TRUE;\n\t}\n}\n\nvoid sipe_ews_update_calendar(struct sipe_core_private *sipe_private)\n{\n\t//char *autodisc_srv = g_strdup_printf(\"_autodiscover._tcp.%s\", maildomain);\n\tstruct sipe_calendar *cal;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_ews_update_calendar: started.\");\n\n\tsipe_cal_calendar_init(sipe_private);\n\tcal = sipe_private->calendar;\n\n\tif (cal->is_ews_disabled) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_ews_update_calendar: disabled, exiting.\");\n\t} else if (!cal->as_url && (cal->state != SIPE_EWS_STATE_AUTODISCOVER_TRIGGERED)) {\n\t\tcal->state = SIPE_EWS_STATE_AUTODISCOVER_TRIGGERED;\n\t\tsipe_ews_autodiscover_start(sipe_private,\n\t\t\t\t\t    sipe_calendar_ews_autodiscover_cb,\n\t\t\t\t\t    cal);\n\t} else {\n\t\tsipe_ews_run_state_machine(cal);\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_ews_update_calendar: finished.\");\n\t}\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-ews.h",
    "content": "/**\n * @file sipe-ews.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2009 pier11 <pier11@operamail.com>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipe_calendar;\nstruct sipe_core_private;\n\n/**\n * Connects to Exchange 2007/2010 Server's Web Services,\n * pulls out our Availability and Out-of-Office (OOF) information\n * and publishes it to Communications server.\n *\n * Advised schedule: 30 minutes.\n */\nvoid\nsipe_ews_update_calendar(struct sipe_core_private *sipe_private);\n\n/**\n * Returns OOF note if enabled in the moment\n * otherwise NULL.\n */\nchar *\nsipe_ews_get_oof_note(struct sipe_calendar *cal);\n"
  },
  {
    "path": "src/core/sipe-ft-lync.c",
    "content": "/**\n * @file sipe-ft-lync.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2014-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n\n#include <errno.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <string.h>\n#ifdef HAVE_UNISTD_H\n#include <unistd.h>\n#endif\n\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-ft-lync.h\"\n#include \"sipe-media.h\"\n#include \"sipe-mime.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n#include \"sipmsg.h\"\n\nstruct sipe_file_transfer_lync {\n\tstruct sipe_file_transfer public;\n\n\tgchar *sdp;\n\tgchar *file_name;\n\tgchar *id;\n\tgsize file_size;\n\tguint request_id;\n\n\tguint bytes_left_in_chunk;\n\n\tguint8 buffer[2048];\n\tguint buffer_len;\n\tguint buffer_read_pos;\n\n\tint backend_pipe[2];\n\tint backend_pipe_write_source_id;\n\n\tstruct sipe_core_private *sipe_private;\n\tstruct sipe_media_call *call;\n\n\tvoid (*call_reject_parent_cb)(struct sipe_media_call *call,\n\t\t\t\t      gboolean local);\n};\n#define SIPE_FILE_TRANSFER         ((struct sipe_file_transfer *) ft_private)\n#define SIPE_FILE_TRANSFER_PRIVATE ((struct sipe_file_transfer_lync *) ft)\n\ntypedef enum {\n\tSIPE_XDATA_DATA_CHUNK = 0x00,\n\tSIPE_XDATA_START_OF_STREAM = 0x01,\n\tSIPE_XDATA_END_OF_STREAM = 0x02\n} SipeXDataMessages;\n\n#define XDATA_HEADER_SIZE sizeof (guint8) + sizeof (guint16)\n\nstatic void\nsipe_file_transfer_lync_free(struct sipe_file_transfer_lync *ft_private)\n{\n\tint our_pipe_end;\n\n\tour_pipe_end = sipe_backend_ft_is_incoming(SIPE_FILE_TRANSFER) ? 1 : 0;\n\n\tif (ft_private->backend_pipe[our_pipe_end] != 0) {\n\t\t// Backend is responsible for closing the pipe's other end.\n\t\tclose(ft_private->backend_pipe[our_pipe_end]);\n\t}\n\n\tg_free(ft_private->file_name);\n\tg_free(ft_private->sdp);\n\tg_free(ft_private->id);\n\n\tif (ft_private->backend_pipe_write_source_id) {\n\t\tg_source_remove(ft_private->backend_pipe_write_source_id);\n\t}\n\n\tg_free(ft_private);\n}\n\nstatic void\nsend_ms_filetransfer_msg(char *body, struct sipe_file_transfer_lync *ft_private,\n\t\t\t TransCallback callback)\n{\n\tsip_transport_info(sipe_media_get_sipe_core_private(ft_private->call),\n\t\t\t   \"Content-Type: application/ms-filetransfer+xml\\r\\n\",\n\t\t\t   body,\n\t\t\t   sipe_media_get_sip_dialog(ft_private->call),\n\t\t\t   callback);\n\n\tg_free(body);\n}\n\nstatic void\nsend_ms_filetransfer_response(struct sipe_file_transfer_lync *ft_private,\n\t\t\t      const gchar *code, const gchar *reason,\n\t\t\t      TransCallback callback)\n{\n\tstatic const gchar *RESPONSE_STR =\n\t\t\t\"<response xmlns=\\\"http://schemas.microsoft.com/rtc/2009/05/filetransfer\\\" requestId=\\\"%d\\\" code=\\\"%s\\\" %s%s%s/>\";\n\n\tsend_ms_filetransfer_msg(g_strdup_printf(RESPONSE_STR,\n\t\t\t\t\t\t ft_private->request_id, code,\n\t\t\t\t\t\t reason ? \"reason=\\\"\" : \"\",\n\t\t\t\t\t\t reason ? reason : \"\",\n\t\t\t\t\t\t reason ? \"\\\"\" : \"\"),\n\t\t\t\t ft_private, callback);\n}\n\nstatic void\nmime_mixed_cb(gpointer user_data, const GSList *fields, const gchar *body,\n\t      gsize length)\n{\n\tstruct sipe_file_transfer_lync *ft_private = user_data;\n\tconst gchar *ctype = sipe_utils_nameval_find(fields, \"Content-Type\");\n\n\t/* Lync 2010 file transfer */\n\tif (g_str_has_prefix(ctype, \"application/ms-filetransfer+xml\")) {\n\t\tsipe_xml *xml = sipe_xml_parse(body, length);\n\n\t\tif (xml) {\n\t\t\tconst sipe_xml *node;\n\n\t\t\tft_private->request_id = sipe_xml_int_attribute(xml,\n\t\t\t\t\t\t\t\t\t\"requestId\",\n\t\t\t\t\t\t\t\t\tft_private->request_id);\n\n\t\t\tnode = sipe_xml_child(xml, \"publishFile/fileInfo/name\");\n\t\t\tif (node) {\n\t\t\t\tg_free(ft_private->file_name);\n\t\t\t\tft_private->file_name = sipe_xml_data(node);\n\t\t\t}\n\n\t\t\tnode = sipe_xml_child(xml, \"publishFile/fileInfo/id\");\n\t\t\tif (node) {\n\t\t\t\tg_free(ft_private->id);\n\t\t\t\tft_private->id = sipe_xml_data(node);\n\t\t\t}\n\n\t\t\tnode = sipe_xml_child(xml, \"publishFile/fileInfo/size\");\n\t\t\tif (node) {\n\t\t\t\tgchar *size_str = sipe_xml_data(node);\n\t\t\t\tif (size_str) {\n\t\t\t\t\tft_private->file_size = atoi(size_str);\n\t\t\t\t\tg_free(size_str);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsipe_xml_free(xml);\n\t\t}\n\t} else if (g_str_has_prefix(ctype, \"application/sdp\")) {\n\t\tg_free(ft_private->sdp);\n\t\tft_private->sdp = g_strndup(body, length);\n\t}\n}\n\nstatic void\ncandidate_pairs_established_cb(struct sipe_media_stream *stream)\n{\n\tstruct sipe_file_transfer_lync *ft_private;\n\tstatic const gchar *DOWNLOAD_FILE_REQUEST =\n\t\t\"<request xmlns=\\\"http://schemas.microsoft.com/rtc/2009/05/filetransfer\\\" requestId=\\\"%d\\\">\"\n\t\t\t\"<downloadFile>\"\n\t\t\t\t\"<fileInfo>\"\n\t\t\t\t\t\"<id>%s</id>\"\n\t\t\t\t\t\"<name>%s</name>\"\n\t\t\t\t\"</fileInfo>\"\n\t\t\t\"</downloadFile>\"\n\t\t\"</request>\";\n\n\tg_return_if_fail(sipe_strequal(stream->id, \"data\"));\n\n\tft_private = sipe_media_stream_get_data(stream);\n\n\tsend_ms_filetransfer_response(ft_private, \"success\", NULL, NULL);\n\n\tsend_ms_filetransfer_msg(g_strdup_printf(DOWNLOAD_FILE_REQUEST,\n\t\t\t\t\t\t ++ft_private->request_id,\n\t\t\t\t\t\t ft_private->id,\n\t\t\t\t\t\t ft_private->file_name),\n\t\t\t\t ft_private, NULL);\n}\n\nstatic gboolean\ncreate_pipe(int pipefd[2])\n{\n#ifdef _WIN32\n#error \"Pipes not implemented for Windows\"\n/* Those interested in porting the code may use Pidgin's wpurple_input_pipe() in\n * win32dep.c as an inspiration. */\n#else\n\tif (pipe(pipefd) != 0) {\n\t\treturn FALSE;\n\t}\n\n\t/* @TODO: ignoring potential error return - how to handle? */\n\t(void) fcntl(pipefd[0], F_SETFL, fcntl(pipefd[0], F_GETFL) | O_NONBLOCK);\n\t(void) fcntl(pipefd[1], F_SETFL, fcntl(pipefd[1], F_GETFL) | O_NONBLOCK);\n\n\treturn TRUE;\n#endif\n}\n\nstatic void\nxdata_start_of_stream_cb(struct sipe_media_stream *stream,\n\t\t\t guint8 *buffer, gsize len)\n{\n\tstruct sipe_file_transfer_lync *ft_private =\n\t\t\tsipe_media_stream_get_data(stream);\n\tstruct sipe_backend_fd *fd;\n\n\tbuffer[len] = 0;\n\tSIPE_DEBUG_INFO(\"Received new stream for requestId : %s\", buffer);\n\n\tif (!create_pipe(ft_private->backend_pipe)) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"Couldn't create backend pipe\");\n\t\tsipe_backend_ft_cancel_local(SIPE_FILE_TRANSFER);\n\t\treturn;\n\t}\n\n\tfd = sipe_backend_fd_from_int(ft_private->backend_pipe[0]);\n\tsipe_backend_ft_start(SIPE_FILE_TRANSFER, fd, NULL, 0);\n\tsipe_backend_fd_free(fd);\n}\n\nstatic void\nxdata_end_of_stream_cb(SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream,\n\t\t       guint8 *buffer, gsize len)\n{\n\tbuffer[len] = 0;\n\tSIPE_DEBUG_INFO(\"Received end of stream for requestId : %s\", buffer);\n}\n\nstatic void\nxdata_got_header_cb(struct sipe_media_stream *stream,\n\t\t    guint8 *buffer,\n\t\t    SIPE_UNUSED_PARAMETER gsize len)\n{\n\tstruct sipe_file_transfer_lync *ft_private =\n\t\t\tsipe_media_stream_get_data(stream);\n\n\tguint8 type = buffer[0];\n\tguint16 size = (buffer[1] << 8) + buffer[2]; /* stored as big-endian */\n\n\tswitch (type) {\n\t\tcase SIPE_XDATA_START_OF_STREAM:\n\t\t\tsipe_media_stream_read_async(stream,\n\t\t\t\t\t\t     ft_private->buffer, size,\n\t\t\t\t\t\t     xdata_start_of_stream_cb);\n\t\t\tbreak;\n\t\tcase SIPE_XDATA_DATA_CHUNK:\n\t\t\tSIPE_DEBUG_INFO(\"Received new data chunk of size %d\",\n\t\t\t\t\tsize);\n\t\t\tft_private->bytes_left_in_chunk = size;\n\t\t\tbreak;\n\t\t\t/* We'll read the data when read_cb is called again. */\n\t\tcase SIPE_XDATA_END_OF_STREAM:\n\t\t\tsipe_media_stream_read_async(stream,\n\t\t\t\t\t\t     ft_private->buffer, size,\n\t\t\t\t\t\t     xdata_end_of_stream_cb);\n\t\t\tbreak;\n\t}\n}\n\nstatic void\nread_cb(struct sipe_media_stream *stream)\n{\n\tstruct sipe_file_transfer_lync *ft_private =\n\t\t\tsipe_media_stream_get_data(stream);\n\n\tif (ft_private->buffer_read_pos < ft_private->buffer_len) {\n\t\t/* Have data in buffer, write them to the backend. */\n\n\t\tgpointer buffer;\n\t\tsize_t len;\n\t\tssize_t written;\n\n\t\tbuffer = ft_private->buffer + ft_private->buffer_read_pos;\n\t\tlen = ft_private->buffer_len - ft_private->buffer_read_pos;\n\t\twritten = write(ft_private->backend_pipe[1], buffer, len);\n\n\t\tif (written > 0) {\n\t\t\tft_private->buffer_read_pos += written;\n\t\t} else if (written < 0 && errno != EAGAIN) {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"Error while writing into \"\n\t\t\t\t\t\t  \"backend pipe\");\n\t\t\tsipe_backend_ft_cancel_local(SIPE_FILE_TRANSFER);\n\t\t\treturn;\n\t\t}\n\t} else if (ft_private->bytes_left_in_chunk != 0) {\n\t\t/* Have data from the sender, replenish our buffer with it. */\n\n\t\tft_private->buffer_len = MIN(ft_private->bytes_left_in_chunk,\n\t\t\t\t\t     sizeof (ft_private->buffer));\n\n\t\tft_private->buffer_len =\n\t\t\t\tsipe_backend_media_stream_read(stream,\n\t\t\t\t\t\t\t       ft_private->buffer,\n\t\t\t\t\t\t\t       ft_private->buffer_len);\n\n\t\tft_private->bytes_left_in_chunk -= ft_private->buffer_len;\n\t\tft_private->buffer_read_pos = 0;\n\n\t\tSIPE_DEBUG_INFO(\"Read %d bytes. %d left in this chunk.\",\n\t\t\t\tft_private->buffer_len, ft_private->bytes_left_in_chunk);\n\t} else {\n\t\t/* No data available. This is either stream start, beginning of\n\t\t * chunk, or stream end. */\n\n\t\tsipe_media_stream_read_async(stream, ft_private->buffer,\n\t\t\t\t\t     XDATA_HEADER_SIZE,\n\t\t\t\t\t     xdata_got_header_cb);\n\t}\n}\n\nstatic void\nft_lync_incoming_init(struct sipe_file_transfer *ft,\n\t\t      SIPE_UNUSED_PARAMETER const gchar *filename,\n\t\t      SIPE_UNUSED_PARAMETER gsize size,\n\t\t      SIPE_UNUSED_PARAMETER const gchar *who)\n{\n\tstruct sipe_media_call *call = SIPE_FILE_TRANSFER_PRIVATE->call;\n\n\tif (call) {\n\t\tsipe_backend_media_accept(call->backend_private, TRUE);\n\t}\n}\n\nstatic void\nft_lync_request_denied(struct sipe_file_transfer *ft)\n{\n\tstruct sipe_file_transfer_lync *ft_private = SIPE_FILE_TRANSFER_PRIVATE;\n\tstruct sipe_media_call *call;\n\n\tg_return_if_fail(ft_private);\n\n\tcall = ft_private->call;\n\n\tif (call && call->backend_private) {\n\t\tsipe_backend_media_reject(call->backend_private, TRUE);\n\t}\n}\n\nstatic struct sipe_file_transfer_lync *\nft_private_from_call(struct sipe_media_call *call)\n{\n\tstruct sipe_media_stream *stream =\n\t\t\tsipe_core_media_get_stream_by_id(call, \"data\");\n\tg_return_val_if_fail(stream, NULL);\n\n\treturn sipe_media_stream_get_data(stream);\n}\n\nstatic void\nsend_transfer_progress(struct sipe_file_transfer_lync *ft_private)\n{\n\tstatic const gchar *FILETRANSFER_PROGRESS =\n\t\t\t\"<notify xmlns=\\\"http://schemas.microsoft.com/rtc/2009/05/filetransfer\\\" notifyId=\\\"%d\\\">\"\n\t\t\t\t\"<fileTransferProgress>\"\n\t\t\t\t\t\"<transferId>%d</transferId>\"\n\t\t\t\t\t\"<bytesReceived>\"\n\t\t\t\t\t\t\"<from>0</from>\"\n\t\t\t\t\t\t\"<to>%d</to>\"\n\t\t\t\t\t\"</bytesReceived>\"\n\t\t\t\t\"</fileTransferProgress>\"\n\t\t\t\"</notify>\";\n\n\tsend_ms_filetransfer_msg(g_strdup_printf(FILETRANSFER_PROGRESS,\n\t\t\t\t\t\t rand(),\n\t\t\t\t\t\t ft_private->request_id,\n\t\t\t\t\t\t ft_private->file_size - 1),\n\t\t\t\t ft_private, NULL);\n}\n\nstatic gboolean\nft_lync_end(struct sipe_file_transfer *ft)\n{\n\tsend_transfer_progress(SIPE_FILE_TRANSFER_PRIVATE);\n\n\treturn TRUE;\n}\n\nstatic void\ncall_reject_cb(struct sipe_media_call *call, gboolean local)\n{\n\tstruct sipe_file_transfer_lync *ft_private = ft_private_from_call(call);\n\tg_return_if_fail(ft_private);\n\n\tif (ft_private->call_reject_parent_cb) {\n\t\tft_private->call_reject_parent_cb(call, local);\n\t}\n\n\tif (!local) {\n\t\tsipe_backend_ft_cancel_remote(&ft_private->public);\n\t}\n}\n\nstatic void\nft_lync_incoming_cancelled(struct sipe_file_transfer *ft)\n{\n\tstatic const gchar *FILETRANSFER_CANCEL_REQUEST =\n\t\t\t\"<request xmlns=\\\"http://schemas.microsoft.com/rtc/2009/05/filetransfer\\\" requestId=\\\"%d\\\"/>\"\n\t\t\t\t\"<cancelTransfer>\"\n\t\t\t\t\t\"<transferId>%d</transferId>\"\n\t\t\t\t\t\"<fileInfo>\"\n\t\t\t\t\t\t\"<id>%s</id>\"\n\t\t\t\t\t\t\"<name>%s</name>\"\n\t\t\t\t\t\"</fileInfo>\"\n\t\t\t\t\"</cancelTransfer>\"\n\t\t\t\"</request>\";\n\n\tstruct sipe_file_transfer_lync *ft_private = SIPE_FILE_TRANSFER_PRIVATE;\n\tstruct sipe_media_stream *stream;\n\n\tsend_ms_filetransfer_msg(g_strdup_printf(FILETRANSFER_CANCEL_REQUEST,\n\t\t\t\t\t\t ft_private->request_id + 1,\n\t\t\t\t\t\t ft_private->request_id,\n\t\t\t\t\t\t ft_private->id,\n\t\t\t\t\t\t ft_private->file_name),\n\t\t\t\t ft_private,\n\t\t\t\t NULL);\n\n\tstream = sipe_core_media_get_stream_by_id(ft_private->call, \"data\");\n\tif (stream) {\n\t\tstream->read_cb = NULL;\n\t}\n\n\tsipe_backend_media_hangup(ft_private->call->backend_private, FALSE);\n}\n\nvoid\nprocess_incoming_invite_ft_lync(struct sipe_core_private *sipe_private,\n\t\t\t\tstruct sipmsg *msg)\n{\n\tstruct sipe_file_transfer_lync *ft_private;\n\tstruct sipe_media_stream *stream;\n\n\tft_private = g_new0(struct sipe_file_transfer_lync, 1);\n\tsipe_mime_parts_foreach(sipmsg_find_content_type_header(msg),\n\t\t\t\tmsg->body, mime_mixed_cb, ft_private);\n\n\tif (!ft_private->file_name || !ft_private->file_size || !ft_private->sdp) {\n\t\tsip_transport_response(sipe_private, msg, 488, \"Not Acceptable Here\", NULL);\n\t\tsipe_file_transfer_lync_free(ft_private);\n\t\treturn;\n\t}\n\n\t/* Use the selected SDP part of multipart SIP message to initialize\n\t * media session. */\n\tft_private->call = process_incoming_invite_call(sipe_private,\n\t\t\t\t\t\t\tmsg,\n\t\t\t\t\t\t\tft_private->sdp);\n\tg_free(ft_private->sdp);\n\tft_private->sdp = NULL;\n\n\tif (!ft_private->call) {\n\t\tsip_transport_response(sipe_private, msg, 500, \"Server Internal Error\", NULL);\n\t\tsipe_file_transfer_lync_free(ft_private);\n\t\treturn;\n\t}\n\n\tft_private->public.ft_init = ft_lync_incoming_init;\n\tft_private->public.ft_request_denied = ft_lync_request_denied;\n\tft_private->public.ft_cancelled = ft_lync_incoming_cancelled;\n\tft_private->public.ft_end = ft_lync_end;\n\n\tft_private->call_reject_parent_cb = ft_private->call->call_reject_cb;\n\tft_private->call->call_reject_cb = call_reject_cb;\n\n\tstream = sipe_core_media_get_stream_by_id(ft_private->call, \"data\");\n\tif (stream) {\n\t\tstream->candidate_pairs_established_cb = candidate_pairs_established_cb;\n\t\tstream->read_cb = read_cb;\n\t\tsipe_media_stream_add_extra_attribute(stream, \"recvonly\", NULL);\n\t\tsipe_media_stream_set_data(stream, ft_private,\n\t\t\t\t\t   (GDestroyNotify)sipe_file_transfer_lync_free);\n\n\t\tsipe_backend_ft_incoming(SIPE_CORE_PUBLIC, SIPE_FILE_TRANSFER,\n\t\t\t\t\t ft_private->call->with,\n\t\t\t\t\t ft_private->file_name,\n\t\t\t\t\t ft_private->file_size);\n\t} else {\n\t\tsip_transport_response(sipe_private, msg, 500, \"Server Internal Error\", NULL);\n\t\tsipe_file_transfer_lync_free(ft_private);\n\t\treturn;\n\t}\n}\n\nstatic void\nprocess_response_incoming(struct sipe_file_transfer_lync *ft_private,\n\t\t\t  sipe_xml *xml)\n{\n\tconst gchar *attr;\n\tguint request_id = sipe_xml_int_attribute(xml, \"requestId\", 0);\n\n\tif (request_id != ft_private->request_id) {\n\t\treturn;\n\t}\n\n\tattr = sipe_xml_attribute(xml, \"code\");\n\tif (sipe_strequal(attr, \"failure\")) {\n\t\tconst gchar *reason = sipe_xml_attribute(xml, \"reason\");\n\t\tif (sipe_strequal(reason, \"requestCancelled\")) {\n\t\t\tsipe_backend_ft_cancel_remote(SIPE_FILE_TRANSFER);\n\t\t}\n\t}\n}\n\nstatic void\nwrite_chunk(struct sipe_media_stream *stream,\n\t    guint8 type, guint16 len, const gchar *buffer)\n{\n\tguint16 len_be = GUINT16_TO_BE(len);\n\n\tsipe_media_stream_write(stream, &type, sizeof (guint8));\n\tsipe_media_stream_write(stream, (guint8 *)&len_be, sizeof (guint16));\n\tsipe_media_stream_write(stream, (guint8 *)buffer, len);\n}\n\nstatic gboolean\nsend_file_chunk(SIPE_UNUSED_PARAMETER GIOChannel *source,\n\t\tSIPE_UNUSED_PARAMETER GIOCondition condition,\n\t\tgpointer data)\n{\n\tstruct sipe_file_transfer_lync *ft_private = data;\n\tstruct sipe_media_call *call = ft_private->call;\n\tstruct sipe_media_stream *stream;\n\tgssize bytes_read;\n\n\tstream = sipe_core_media_get_stream_by_id(call, \"data\");\n\tif (!stream) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"Couldn't find data stream\");\n\t\tsipe_backend_ft_cancel_local(SIPE_FILE_TRANSFER);\n\t\tft_private->backend_pipe_write_source_id = 0;\n\t\treturn FALSE; /* G_SOURCE_REMOVE */\n\t}\n\n\tif (!sipe_media_stream_is_writable(stream)) {\n\t\treturn TRUE; /* G_SOURCE_CONTINUE */\n\t}\n\n\tbytes_read = read(ft_private->backend_pipe[0],\n\t\t\t  ft_private->buffer, sizeof (ft_private->buffer));\n\tif (bytes_read > 0) {\n\t\twrite_chunk(stream, SIPE_XDATA_DATA_CHUNK,\n\t\t\t    bytes_read, (const gchar *)ft_private->buffer);\n\t} else if (bytes_read == 0) {\n\t\t/* EOF, write end of stream */\n\t\tgchar *request_id_str;\n\n\t\trequest_id_str = g_strdup_printf(\"%u\", ft_private->request_id);\n\t\twrite_chunk(stream, SIPE_XDATA_END_OF_STREAM,\n\t\t\t    strlen(request_id_str), request_id_str);\n\t\tg_free(request_id_str);\n\n\t\treturn FALSE; /* G_SOURCE_REMOVE */\n\t}\n\n\treturn TRUE; /* G_SOURCE_CONTINUE */\n}\n\nstatic void\nstart_writing(struct sipe_file_transfer_lync *ft_private)\n{\n\tstruct sipe_media_stream *stream;\n\tgchar *request_id_str;\n\tstruct sipe_backend_fd *fd;\n\tGIOChannel *channel;\n\n\tstream = sipe_core_media_get_stream_by_id(ft_private->call, \"data\");\n\tif (!stream) {\n\t\treturn;\n\t}\n\n\tif (!create_pipe(ft_private->backend_pipe)) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"Couldn't create backend pipe\");\n\t\tsipe_backend_ft_cancel_local(SIPE_FILE_TRANSFER);\n\t\treturn;\n\t}\n\n\trequest_id_str = g_strdup_printf(\"%u\", ft_private->request_id);\n\twrite_chunk(stream, SIPE_XDATA_START_OF_STREAM,\n\t\t    strlen(request_id_str), request_id_str);\n\tg_free(request_id_str);\n\n\tchannel = g_io_channel_unix_new(ft_private->backend_pipe[0]);\n\tft_private->backend_pipe_write_source_id = g_io_add_watch(channel,\n\t\t\t\t\t\t\t\t  G_IO_IN | G_IO_HUP,\n\t\t\t\t\t\t\t\t  send_file_chunk,\n\t\t\t\t\t\t\t\t  ft_private);\n\tg_io_channel_unref(channel);\n\n\tfd = sipe_backend_fd_from_int(ft_private->backend_pipe[1]);\n\tsipe_backend_ft_start(SIPE_FILE_TRANSFER, fd, NULL, 0);\n\tsipe_backend_fd_free(fd);\n}\n\nstatic void\nprocess_request(struct sipe_file_transfer_lync *ft_private, sipe_xml *xml)\n{\n\tstatic const gchar *DOWNLOAD_PENDING_RESPONSE =\n\t\t\t\"<response xmlns=\\\"http://schemas.microsoft.com/rtc/2009/05/filetransfer\\\" \"\n\t\t\t  \"requestId=\\\"%u\\\" code=\\\"pending\\\"/>\";\n\n\tif (sipe_xml_child(xml, \"downloadFile\")) {\n\t\tft_private->request_id =\n\t\t\t\tatoi(sipe_xml_attribute(xml, \"requestId\"));\n\n\t\tsend_ms_filetransfer_msg(g_strdup_printf(DOWNLOAD_PENDING_RESPONSE,\n\t\t\t\t\t\t\t ft_private->request_id),\n\t\t\t\t\t ft_private, NULL);\n\n\t\tstart_writing(ft_private);\n\t}\n}\n\nstatic void\nprocess_notify(struct sipe_file_transfer_lync *ft_private, sipe_xml *xml)\n{\n\tstatic const gchar *DOWNLOAD_SUCCESS_RESPONSE =\n\t\t\"<response xmlns=\\\"http://schemas.microsoft.com/rtc/2009/05/filetransfer\\\" \"\n\t\t  \"requestId=\\\"%u\\\" code=\\\"success\\\"/>\";\n\n\tconst sipe_xml *progress_node = sipe_xml_child(xml, \"fileTransferProgress\");\n\n\tif (progress_node) {\n\t\tgchar *to_str = sipe_xml_data(sipe_xml_child(progress_node, \"bytesReceived/to\"));\n\n\t\tif (atoi(to_str) == (int)(ft_private->file_size - 1)) {\n\t\t\tsend_ms_filetransfer_msg(g_strdup_printf(DOWNLOAD_SUCCESS_RESPONSE,\n\t\t\t\t\t\t\t\t ft_private->request_id),\n\t\t\t\t\t\t ft_private, NULL);\n\t\t\tsipe_backend_media_hangup(ft_private->call->backend_private, TRUE);\n\t\t}\n\t\tg_free(to_str);\n\t}\n}\n\nvoid\nprocess_incoming_info_ft_lync(struct sipe_core_private *sipe_private,\n\t\t\t      struct sipmsg *msg)\n{\n\tstruct sipe_media_call *call;\n\tstruct sipe_file_transfer_lync *ft_private;\n\tsipe_xml *xml;\n\n\tcall = g_hash_table_lookup(sipe_private->media_calls,\n\t\t\t\t   sipmsg_find_call_id_header(msg));\n\tif (!call) {\n\t\treturn;\n\t}\n\n\tft_private = ft_private_from_call(call);\n\tif (!ft_private) {\n\t\treturn;\n\t}\n\n\txml = sipe_xml_parse(msg->body, msg->bodylen);\n\tif (!xml) {\n\t\treturn;\n\t}\n\n\tsip_transport_response(sipe_private, msg, 200, \"OK\", NULL);\n\n\tif (sipe_backend_ft_is_incoming(SIPE_FILE_TRANSFER)) {\n\t\tif (sipe_strequal(sipe_xml_name(xml), \"response\")) {\n\t\t\tprocess_response_incoming(ft_private, xml);\n\t\t}\n\t} else {\n\t\tif (sipe_strequal(sipe_xml_name(xml), \"request\")) {\n\t\t\tprocess_request(ft_private, xml);\n\t\t} else if (sipe_strequal(sipe_xml_name(xml), \"notify\")) {\n\t\t\tprocess_notify(ft_private, xml);\n\t\t}\n\t}\n\n\tsipe_xml_free(xml);\n}\n\nstatic void\nappend_publish_file_invite(struct sipe_media_call *call,\n\t\t\t   struct sipe_file_transfer_lync *ft_private)\n{\n\tstatic const gchar *PUBLISH_FILE_REQUEST =\n\t\t\t\"Content-Type: application/ms-filetransfer+xml\\r\\n\"\n\t\t\t\"Content-Transfer-Encoding: 7bit\\r\\n\"\n\t\t\t\"Content-Disposition: render; handling=optional\\r\\n\"\n\t\t\t\"\\r\\n\"\n\t\t\t\"<request xmlns=\\\"http://schemas.microsoft.com/rtc/2009/05/filetransfer\\\" \"\n\t\t\t  \"requestId=\\\"%u\\\">\"\n\t\t\t\t\"<publishFile>\"\n\t\t\t\t\t\"<fileInfo>\"\n\t\t\t\t\t\t\"<id>{6244F934-2EB1-443F-8E2C-48BA64AF463D}</id>\"\n\t\t\t\t\t\t\"<name>%s</name>\"\n\t\t\t\t\t\t\"<size>%u</size>\"\n\t\t\t\t\t\"</fileInfo>\"\n\t\t\t\t\"</publishFile>\"\n\t\t\t\"</request>\\r\\n\";\n\tgchar *body;\n\n\tft_private->request_id =\n\t\t\t++ft_private->sipe_private->ms_filetransfer_request_id;\n\n\tbody = g_strdup_printf(PUBLISH_FILE_REQUEST, ft_private->request_id,\n\t\t\t       ft_private->file_name, ft_private->file_size);\n\n\tsipe_media_add_extra_invite_section(call, \"multipart/mixed\", body);\n}\n\nstatic void\nft_lync_outgoing_init(struct sipe_file_transfer *ft, const gchar *filename,\n\t\t      gsize size, SIPE_UNUSED_PARAMETER const gchar *who)\n{\n\tstruct sipe_core_private *sipe_private =\n\t\t\tSIPE_FILE_TRANSFER_PRIVATE->sipe_private;\n\tstruct sipe_file_transfer_lync *ft_private = SIPE_FILE_TRANSFER_PRIVATE;\n\tstruct sipe_media_call *call;\n\tstruct sipe_media_stream *stream;\n\n\tft_private->file_name = g_strdup(filename);\n\tft_private->file_size = size;\n\n\tcall = sipe_media_call_new(sipe_private, who, NULL, SIPE_ICE_RFC_5245,\n\t\t\t\t   SIPE_MEDIA_CALL_NO_UI);\n\n\tft_private->call = call;\n\n\tft_private->call_reject_parent_cb = call->call_reject_cb;\n\tcall->call_reject_cb = call_reject_cb;\n\n\tstream = sipe_media_stream_add(call, \"data\", SIPE_MEDIA_APPLICATION,\n\t\t\t\t       SIPE_ICE_RFC_5245, TRUE, 0);\n\tif (!stream) {\n\t\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t  _(\"Error occurred\"),\n\t\t\t\t\t  _(\"Error creating data stream\"));\n\n\t\tsipe_backend_media_hangup(call->backend_private, FALSE);\n\t\tsipe_backend_ft_cancel_local(ft);\n\t\treturn;\n\t}\n\n\tsipe_media_stream_add_extra_attribute(stream, \"sendonly\", NULL);\n\tsipe_media_stream_add_extra_attribute(stream, \"mid\", \"1\");\n\tsipe_media_stream_set_data(stream, ft,\n\t\t\t\t   (GDestroyNotify)sipe_file_transfer_lync_free);\n\tappend_publish_file_invite(call, ft_private);\n}\n\nstruct sipe_file_transfer *\nsipe_file_transfer_lync_new_outgoing(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_file_transfer_lync *ft_private;\n\n\tft_private = g_new0(struct sipe_file_transfer_lync, 1);\n\n\tft_private->sipe_private = sipe_private;\n\tft_private->public.ft_init = ft_lync_outgoing_init;\n\n\treturn SIPE_FILE_TRANSFER;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-ft-lync.h",
    "content": "/**\n * @file sipe-ft-lync.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2014-2015 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\nstruct sipmsg;\n\nstruct sipe_file_transfer *\nsipe_file_transfer_lync_new_outgoing(struct sipe_core_private *sipe_private);\n\nvoid process_incoming_invite_ft_lync(struct sipe_core_private *sipe_private,\n\t\t\t\t     struct sipmsg *msg);\n\nvoid process_incoming_info_ft_lync(struct sipe_core_private *sipe_private,\n\t\t\t\t   struct sipmsg *msg);\n"
  },
  {
    "path": "src/core/sipe-ft-tftp.c",
    "content": "/**\n * @file sipe-ft-tftp.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2010 Jakub Adam <jakub.adam@ktknet.cz>\n * Copyright (C) 2010 Tomáš Hrabčík <tomas.hrabcik@tieto.com>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <string.h>\n\n#include <glib.h>\n#include <glib/gprintf.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-crypt.h\"\n#include \"sipe-dialog.h\"\n#include \"sipe-digest.h\"\n#include \"sipe-ft.h\"\n#include \"sipe-ft-tftp.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-utils.h\"\n\n#define BUFFER_SIZE 50\n#define SIPE_FT_CHUNK_HEADER_LENGTH  3\n\nstatic gboolean\nwrite_exact(struct sipe_file_transfer_private *ft_private, const guchar *data,\n\t    gsize size)\n{\n\tgssize bytes_written = sipe_backend_ft_write(SIPE_FILE_TRANSFER_PUBLIC,\n\t\t\t\t\t\t     data, size);\n\tif ((bytes_written < 0) || ((gsize) bytes_written != size))\n\t\treturn FALSE;\n\treturn TRUE;\n}\n\nstatic gboolean\nread_exact(struct sipe_file_transfer_private *ft_private, guchar *data,\n\t   gsize size)\n{\n\tconst gulong READ_TIMEOUT = 10000000;\n\tgulong time_spent = 0;\n\n\twhile (size) {\n\t\tgssize bytes_read = sipe_backend_ft_read(SIPE_FILE_TRANSFER_PUBLIC,\n\t\t\t\t\t\t\t data, size);\n\t\tif (bytes_read == 0) {\n\t\t\tg_usleep(100000);\n\t\t\ttime_spent += 100000;\n\t\t} else if (bytes_read < 0 || time_spent > READ_TIMEOUT) {\n\t\t\treturn FALSE;\n\t\t} else {\n\t\t\tsize -= bytes_read;\n\t\t\tdata += bytes_read;\n\t\t\ttime_spent = 0;\n\t\t}\n\t}\n\treturn TRUE;\n}\n\nstatic gboolean\nread_line(struct sipe_file_transfer_private *ft_private, guchar *data,\n\t  gsize size)\n{\n\tgsize pos = 0;\n\n\tif (size < 2) return FALSE;\n\n\tmemset(data, 0, size--);\n\tdo {\n\t\tif (!read_exact(ft_private, data + pos, 1))\n\t\t\treturn FALSE;\n\t} while ((data[pos] != '\\n') && (++pos < size));\n\n\t/* Buffer too short? */\n\tif ((pos == size) && (data[pos - 1] != '\\n')) {\n\t\treturn FALSE;\n\t}\n\n\treturn TRUE;\n}\n\n\nstatic void\nraise_ft_socket_read_error_and_cancel(struct sipe_file_transfer_private *ft_private)\n{\n\tsipe_ft_raise_error_and_cancel(ft_private, _(\"Socket read failed\"));\n}\n\nstatic void\nraise_ft_socket_write_error_and_cancel(struct sipe_file_transfer_private *ft_private)\n{\n\tsipe_ft_raise_error_and_cancel(ft_private, _(\"Socket write failed\"));\n}\n\nstatic gpointer\nsipe_cipher_context_init(const guchar *enc_key)\n{\n\t/*\n\t *      Decryption of file from SIPE file transfer\n\t *\n\t *      Decryption:\n\t *  1.) SHA1-Key = SHA1sum (Encryption-Key); Do SHA1 digest from Encryption-Key, return 20 bytes SHA1-Key.\n\t *  2.) Decrypt-Data = RC4 (Encrypt-Data, substr(SHA1-Key, 0, 15)); Decryption of encrypted data, used 16 bytes SHA1-Key;\n\t */\n\n\tguchar k2[SIPE_DIGEST_SHA1_LENGTH];\n\n\t/* 1.) SHA1 sum\t*/\n        sipe_digest_sha1(enc_key, SIPE_FT_KEY_LENGTH, k2);\n\n\t/* 2.) RC4 decryption */\n\treturn sipe_crypt_ft_start(k2);\n}\n\nstatic gpointer\nsipe_hmac_context_init(const guchar *hash_key)\n{\n\t/*\n\t * \tCount MAC digest\n\t *\n\t *  \tHMAC digest:\n\t *  1.) SHA1-Key = SHA1sum (Hash-Key); Do SHA1 digest from Hash-Key, return 20 bytes SHA1-Key.\n\t *  2.) MAC = HMAC_SHA1 (Decrypt-Data, substr(HMAC-Key,0,15)); Digest of decrypted file and SHA1-Key (used again only 16 bytes)\n\t */\n\n\tguchar k2[SIPE_DIGEST_SHA1_LENGTH];\n\n\t/* 1.) SHA1 sum\t*/\n\tsipe_digest_sha1(hash_key, SIPE_FT_KEY_LENGTH, k2);\n\n\t/* 2.) HMAC (initialization only) */\n\treturn sipe_digest_ft_start(k2);\n}\n\nstatic gchar *\nsipe_hmac_finalize(gpointer hmac_context)\n{\n\tguchar hmac_digest[SIPE_DIGEST_FILETRANSFER_LENGTH];\n\n\t/*  MAC = Digest of decrypted file and SHA1-Key (used again only 16 bytes) */\n\tsipe_digest_ft_end(hmac_context, hmac_digest);\n\n\treturn g_base64_encode(hmac_digest, sizeof (hmac_digest));\n}\n\nvoid\nsipe_ft_tftp_start_receiving(struct sipe_file_transfer *ft, gsize total_size)\n{\n\tstatic const guchar VER[]    = \"VER MSN_SECURE_FTP\\r\\n\";\n\tstatic const guchar TFR[]    = \"TFR\\r\\n\";\n\tconst gsize FILE_SIZE_OFFSET = 4;\n\n\tstruct sipe_file_transfer_private *ft_private = SIPE_FILE_TRANSFER_PRIVATE;\n\tguchar buf[BUFFER_SIZE];\n\tgchar *request;\n\tgsize file_size;\n\n\tif (!write_exact(ft_private, VER, sizeof(VER) - 1)) {\n\t\traise_ft_socket_read_error_and_cancel(ft_private);\n\t\treturn;\n\t}\n\tif (!read_line(ft_private, buf, BUFFER_SIZE)) {\n\t\traise_ft_socket_read_error_and_cancel(ft_private);\n\t\treturn;\n\t}\n\n\trequest = g_strdup_printf(\"USR %s %u\\r\\n\",\n\t\t\t\t  ft_private->sipe_private->username,\n\t\t\t\t  ft_private->auth_cookie);\n\tif (!write_exact(ft_private, (guchar *)request, strlen(request))) {\n\t\traise_ft_socket_write_error_and_cancel(ft_private);\n\t\tg_free(request);\n\t\treturn;\n\t}\n\tg_free(request);\n\n\tif (!read_line(ft_private, buf, BUFFER_SIZE)) {\n\t\traise_ft_socket_read_error_and_cancel(ft_private);\n\t\treturn;\n\t}\n\n\tfile_size = g_ascii_strtoull((gchar *) buf + FILE_SIZE_OFFSET, NULL, 10);\n\tif (file_size != total_size) {\n\t\tsipe_ft_raise_error_and_cancel(ft_private,\n\t\t\t\t\t       _(\"File size is different from the advertised value.\"));\n\t\treturn;\n\t}\n\n\tif (sipe_backend_ft_write(SIPE_FILE_TRANSFER_PUBLIC, TFR, sizeof(TFR) - 1) != (sizeof(TFR) - 1)) {\n\t\traise_ft_socket_write_error_and_cancel(ft_private);\n\t\treturn;\n\t}\n\n\tft_private->bytes_remaining_chunk = 0;\n\tft_private->cipher_context = sipe_cipher_context_init(ft_private->encryption_key);\n\tft_private->hmac_context   = sipe_hmac_context_init(ft_private->hash_key);\n}\n\ngboolean\nsipe_ft_tftp_stop_receiving(struct sipe_file_transfer *ft)\n{\n\tstatic const guchar BYE[] = \"BYE 16777989\\r\\n\";\n\tconst gsize MAC_OFFSET    = 4;\n\n\tstruct sipe_file_transfer_private *ft_private = SIPE_FILE_TRANSFER_PRIVATE;\n\tgchar buffer[BUFFER_SIZE];\n\tgsize mac_len;\n\tgchar *mac;\n\tgchar *mac1;\n\n\tif (sipe_backend_ft_write(SIPE_FILE_TRANSFER_PUBLIC, BYE, sizeof(BYE) - 1) != (sizeof(BYE) - 1)) {\n\t\traise_ft_socket_write_error_and_cancel(ft_private);\n\t\treturn FALSE;\n\t}\n\n\tif (!read_line(ft_private, (guchar *) buffer, BUFFER_SIZE)) {\n\t\traise_ft_socket_read_error_and_cancel(ft_private);\n\t\treturn FALSE;\n\t}\n\n\tmac_len = strlen(buffer);\n\tif (mac_len < (MAC_OFFSET)) {\n\t\tsipe_ft_raise_error_and_cancel(ft_private,\n\t\t\t\t\t       _(\"Received MAC is corrupted\"));\n\t\treturn FALSE;\n\t}\n\n\t/* Check MAC */\n\tmac  = g_strndup(buffer + MAC_OFFSET, mac_len - MAC_OFFSET);\n\tmac1 = sipe_hmac_finalize(ft_private->hmac_context);\n\tif (!sipe_strequal(mac, mac1)) {\n\t\tg_free(mac1);\n\t\tg_free(mac);\n\t\tsipe_ft_raise_error_and_cancel(ft_private,\n\t\t\t\t\t       _(\"Received file is corrupted\"));\n\t\treturn(FALSE);\n\t}\n\tg_free(mac1);\n\tg_free(mac);\n\n\tsipe_ft_free(ft);\n\n\treturn(TRUE);\n}\n\nvoid\nsipe_ft_tftp_start_sending(struct sipe_file_transfer *ft, gsize total_size)\n{\n\tstatic const guchar VER[] = \"VER MSN_SECURE_FTP\\r\\n\";\n\n\tstruct sipe_file_transfer_private *ft_private = SIPE_FILE_TRANSFER_PRIVATE;\n\tguchar buf[BUFFER_SIZE];\n\tgchar **parts;\n\tunsigned auth_cookie_received;\n\tgboolean users_match;\n\n\tif (!read_line(ft_private, buf, BUFFER_SIZE)) {\n\t\traise_ft_socket_read_error_and_cancel(ft_private);\n\t\treturn;\n\t}\n\n\tif (!sipe_strequal((gchar *)buf, (gchar *)VER)) {\n\t\tsipe_ft_raise_error_and_cancel(ft_private,\n\t\t\t\t\t       _(\"File transfer initialization failed.\"));\n\t\tSIPE_DEBUG_INFO(\"File transfer VER string incorrect, received: %s expected: %s\",\n\t\t\t\tbuf, VER);\n\t\treturn;\n\t}\n\n\tif (!write_exact(ft_private, VER, sizeof(VER) - 1)) {\n\t\traise_ft_socket_write_error_and_cancel(ft_private);\n\t\treturn;\n\t}\n\n\tif (!read_line(ft_private, buf, BUFFER_SIZE)) {\n\t\traise_ft_socket_read_error_and_cancel(ft_private);\n\t\treturn;\n\t}\n\n\tparts = g_strsplit((gchar *)buf, \" \", 3);\n\tauth_cookie_received = g_ascii_strtoull(parts[2], NULL, 10);\n\t/* dialog->with has 'sip:' prefix, skip these four characters */\n\tusers_match = sipe_strcase_equal(parts[1],\n\t\t\t\t\t (ft_private->dialog->with + 4));\n\tg_strfreev(parts);\n\n\tSIPE_DEBUG_INFO(\"File transfer authentication: %s Expected: USR %s %u\",\n\t\t\tbuf,\n\t\t\tft_private->dialog->with + 4,\n\t\t\tft_private->auth_cookie);\n\n\tif (!users_match ||\n\t    (ft_private->auth_cookie != auth_cookie_received)) {\n\t\tsipe_ft_raise_error_and_cancel(ft_private,\n\t\t\t\t\t       _(\"File transfer authentication failed.\"));\n\t\treturn;\n\t}\n\n\tg_sprintf((gchar *)buf, \"FIL %\" G_GSIZE_FORMAT \"\\r\\n\", total_size);\n\tif (!write_exact(ft_private, buf, strlen((gchar *)buf))) {\n\t\traise_ft_socket_write_error_and_cancel(ft_private);\n\t\treturn;\n\t}\n\n\t/* TFR */\n\tif (!read_line(ft_private ,buf, BUFFER_SIZE)) {\n\t\traise_ft_socket_read_error_and_cancel(ft_private);\n\t\treturn;\n\t}\n\n\tft_private->bytes_remaining_chunk = 0;\n\tft_private->cipher_context = sipe_cipher_context_init(ft_private->encryption_key);\n\tft_private->hmac_context   = sipe_hmac_context_init(ft_private->hash_key);\n}\n\ngboolean\nsipe_ft_tftp_stop_sending(struct sipe_file_transfer *ft)\n{\n\tstruct sipe_file_transfer_private *ft_private = SIPE_FILE_TRANSFER_PRIVATE;\n\tguchar buffer[BUFFER_SIZE];\n\tgchar *mac;\n\tgsize mac_len;\n\n\t/* BYE */\n\tif (!read_line(ft_private, buffer, BUFFER_SIZE)) {\n\t\traise_ft_socket_read_error_and_cancel(ft_private);\n\t\treturn FALSE;\n\t}\n\n\tmac = sipe_hmac_finalize(ft_private->hmac_context);\n\tg_sprintf((gchar *)buffer, \"MAC %s \\r\\n\", mac);\n\tg_free(mac);\n\n\tmac_len = strlen((gchar *)buffer);\n\t/* There must be this zero byte between mac and \\r\\n */\n\tbuffer[mac_len - 3] = 0;\n\n\tif (!write_exact(ft_private, buffer, mac_len)) {\n\t\traise_ft_socket_write_error_and_cancel(ft_private);\n\t\treturn FALSE;\n\t}\n\n\tsipe_ft_free(ft);\n\n\treturn TRUE;\n}\n\nstatic void raise_ft_error(struct sipe_file_transfer_private *ft_private,\n\t\t\t   const gchar *errmsg)\n{\n\tgchar *tmp = g_strdup_printf(\"%s: %s\", errmsg,\n\t\t\t\t     sipe_backend_ft_get_error(SIPE_FILE_TRANSFER_PUBLIC));\n\tsipe_backend_ft_error(SIPE_FILE_TRANSFER_PUBLIC, tmp);\n\tg_free(tmp);\n}\n\ngssize\nsipe_ft_tftp_read(struct sipe_file_transfer *ft, guchar **buffer,\n\t\t  gsize bytes_remaining, gsize bytes_available)\n{\n\tstruct sipe_file_transfer_private *ft_private = SIPE_FILE_TRANSFER_PRIVATE;\n\tgsize  bytes_to_read;\n\tgssize bytes_read;\n\n\tif (ft_private->bytes_remaining_chunk == 0) {\n\t\tguchar hdr_buf[SIPE_FT_CHUNK_HEADER_LENGTH] = { 0, 0, 0 };\n\n\t\t/* read chunk header */\n\t\tif (!read_exact(ft_private, hdr_buf, sizeof(hdr_buf))) {\n\t\t\traise_ft_error(ft_private, _(\"Socket read failed\"));\n\t\t\treturn -1;\n\t\t}\n\n\t\t/* chunk header format:\n\t\t *\n\t\t *  0:  00   unknown             (always zero?)\n\t\t *  1:  LL   chunk size in bytes (low byte)\n\t\t *  2:  HH   chunk size in bytes (high byte)\n\t\t *\n\t\t * Convert size from little endian to host order\n\t\t */\n\t\tft_private->bytes_remaining_chunk =\n\t\t\thdr_buf[1] + (hdr_buf[2] << 8);\n\t}\n\n\tbytes_to_read = MIN(bytes_remaining, bytes_available);\n\tbytes_to_read = MIN(bytes_to_read, ft_private->bytes_remaining_chunk);\n\n\t*buffer = g_malloc(bytes_to_read);\n\tif (!*buffer) {\n\t\tsipe_backend_ft_error(SIPE_FILE_TRANSFER_PUBLIC, _(\"Out of memory\"));\n\t\tSIPE_DEBUG_ERROR(\"sipe_core_ft_read: can't allocate %\" G_GSIZE_FORMAT \" bytes for receive buffer\",\n\t\t\t\t bytes_to_read);\n\t\treturn -1;\n\t}\n\n\tbytes_read = sipe_backend_ft_read(SIPE_FILE_TRANSFER_PUBLIC, *buffer, bytes_to_read);\n\tif (bytes_read < 0) {\n\t\traise_ft_error(ft_private, _(\"Socket read failed\"));\n\t\tg_free(*buffer);\n\t\t*buffer = NULL;\n\t\treturn -1;\n\t}\n\n\tif (bytes_read > 0) {\n\t\tguchar *decrypted = g_malloc(bytes_read);\n\n\t\tif (!decrypted) {\n\t\t\tsipe_backend_ft_error(SIPE_FILE_TRANSFER_PUBLIC, _(\"Out of memory\"));\n\t\t\tSIPE_DEBUG_ERROR(\"sipe_core_ft_read: can't allocate %\" G_GSIZE_FORMAT \" bytes for decryption buffer\",\n\t\t\t\t\t (gsize)bytes_read);\n\t\t\tg_free(*buffer);\n\t\t\t*buffer = NULL;\n\t\t\treturn -1;\n\t\t}\n\t\tsipe_crypt_ft_stream(ft_private->cipher_context,\n\t\t\t\t     *buffer, bytes_read, decrypted);\n\t\tg_free(*buffer);\n\t\t*buffer = decrypted;\n\n\t\tsipe_digest_ft_update(ft_private->hmac_context,\n\t\t\t\t      decrypted, bytes_read);\n\n\t\tft_private->bytes_remaining_chunk -= bytes_read;\n\t}\n\n\treturn(bytes_read);\n}\n\ngssize\nsipe_ft_tftp_write(struct sipe_file_transfer *ft, const guchar *buffer,\n\t\t   gsize size)\n{\n\tstruct sipe_file_transfer_private *ft_private = SIPE_FILE_TRANSFER_PRIVATE;\n\tgssize bytes_written;\n\n\t/* When sending data via server with ForeFront installed, block bigger than\n\t * this default causes ending of transmission. Hard limit block to this value\n\t * when libpurple sends us more data. */\n\tconst gsize DEFAULT_BLOCK_SIZE = 2045;\n\tif (size > DEFAULT_BLOCK_SIZE)\n\t\tsize = DEFAULT_BLOCK_SIZE;\n\n\tif (ft_private->bytes_remaining_chunk == 0) {\n\t\tgssize bytes_read;\n\t\tguchar local_buf[16 + 1]; /* space for string terminator */\n\t\tguchar hdr_buf[SIPE_FT_CHUNK_HEADER_LENGTH];\n\n\t\t/* Check if receiver did not cancel the transfer\n\t\t   before it is finished */\n\t\tbytes_read = sipe_backend_ft_read(SIPE_FILE_TRANSFER_PUBLIC,\n\t\t\t\t\t\t  local_buf,\n\t\t\t\t\t\t  sizeof(local_buf) - 1);\n\t\tlocal_buf[sizeof(local_buf) - 1] = '\\0';\n\n\t\tif (bytes_read < 0) {\n\t\t\tsipe_backend_ft_error(SIPE_FILE_TRANSFER_PUBLIC,\n\t\t\t\t\t      _(\"Socket read failed\"));\n\t\t\treturn -1;\n\t\t} else if ((bytes_read > 0) &&\n\t\t\t   (g_str_has_prefix((gchar *)local_buf, \"CCL\\r\\n\") ||\n\t\t\t    g_str_has_prefix((gchar *)local_buf, \"BYE 2164261682\\r\\n\"))) {\n\t\t\treturn -1;\n\t\t}\n\n\t\tif (ft_private->outbuf_size < size) {\n\t\t\tg_free(ft_private->encrypted_outbuf);\n\t\t\tft_private->outbuf_size = size;\n\t\t\tft_private->encrypted_outbuf = g_malloc(ft_private->outbuf_size);\n\t\t\tif (!ft_private->encrypted_outbuf) {\n\t\t\t\tsipe_backend_ft_error(SIPE_FILE_TRANSFER_PUBLIC,\n\t\t\t\t\t\t      _(\"Out of memory\"));\n\t\t\t\tSIPE_DEBUG_ERROR(\"sipe_core_ft_write: can't allocate %\" G_GSIZE_FORMAT \" bytes for send buffer\",\n\t\t\t\t\t\t ft_private->outbuf_size);\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\n\t\tft_private->bytes_remaining_chunk = size;\n\t\tft_private->outbuf_ptr = ft_private->encrypted_outbuf;\n\t\tsipe_crypt_ft_stream(ft_private->cipher_context,\n\t\t\t\t     buffer, size,\n\t\t\t\t     ft_private->encrypted_outbuf);\n\t\tsipe_digest_ft_update(ft_private->hmac_context,\n\t\t\t\t      buffer, size);\n\n\t\t/* chunk header format:\n\t\t *\n\t\t *  0:  00   unknown             (always zero?)\n\t\t *  1:  LL   chunk size in bytes (low byte)\n\t\t *  2:  HH   chunk size in bytes (high byte)\n\t\t *\n\t\t * Convert size from host order to little endian\n\t\t */\n\t\thdr_buf[0] = 0;\n\t\thdr_buf[1] = (ft_private->bytes_remaining_chunk & 0x00FF);\n\t\thdr_buf[2] = (ft_private->bytes_remaining_chunk & 0xFF00) >> 8;\n\n\t\t/* write chunk header */\n\t\tif (sipe_backend_ft_write(SIPE_FILE_TRANSFER_PUBLIC, hdr_buf, sizeof(hdr_buf)) != sizeof(hdr_buf)) {\n\t\t\tsipe_backend_ft_error(SIPE_FILE_TRANSFER_PUBLIC,\n\t\t\t\t\t      _(\"Socket write failed\"));\n\t\t\treturn -1;\n\t\t}\n\t}\n\n\tbytes_written = sipe_backend_ft_write(SIPE_FILE_TRANSFER_PUBLIC,\n\t\t\t\t\t      ft_private->outbuf_ptr,\n\t\t\t\t\t      ft_private->bytes_remaining_chunk);\n\tif (bytes_written < 0) {\n\t\traise_ft_error(ft_private, _(\"Socket write failed\"));\n\t} else if (bytes_written > 0) {\n\t\tft_private->bytes_remaining_chunk -= bytes_written;\n\t\tft_private->outbuf_ptr += bytes_written;\n\t}\n\n\treturn bytes_written;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-ft-tftp.h",
    "content": "/**\n * @file sipe-ft-tftp.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2014-2015 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\nvoid\nsipe_ft_tftp_start_receiving(struct sipe_file_transfer *ft, gsize total_size);\n\ngboolean\nsipe_ft_tftp_stop_receiving(struct sipe_file_transfer *ft);\n\ngssize\nsipe_ft_tftp_read(struct sipe_file_transfer *ft, guchar **buffer,\n\t\t  gsize bytes_remaining, gsize bytes_available);\n\nvoid\nsipe_ft_tftp_start_sending(struct sipe_file_transfer *ft, gsize total_size);\n\ngboolean\nsipe_ft_tftp_stop_sending(struct sipe_file_transfer *ft);\n\ngssize\nsipe_ft_tftp_write(struct sipe_file_transfer *ft, const guchar *buffer,\n\t\t   gsize size);\n"
  },
  {
    "path": "src/core/sipe-ft.c",
    "content": "/**\n * @file sipe-ft.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2016 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2010 Jakub Adam <jakub.adam@ktknet.cz>\n * Copyright (C) 2010 Tomáš Hrabčík <tomas.hrabcik@tieto.com>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipmsg.h\"\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-crypt.h\"\n#include \"sipe-dialog.h\"\n#include \"sipe-digest.h\"\n#include \"sipe-ft.h\"\n#include \"sipe-ft-lync.h\"\n#include \"sipe-ft-tftp.h\"\n#include \"sipe-im.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-session.h\"\n#include \"sipe-utils.h\"\n\n/*\n * DO NOT CHANGE THE FOLLOWING CONSTANTS!!!\n *\n * It seems that Microsoft Office Communicator client will accept\n * file transfer invitations *only* within this port range!\n *\n * If a firewall is active on your system you need to open these ports if\n * you want to *send* files to other users. Receiving files uses an outgoing\n * connection and should therefore automatically penetrate your firewall.\n */\n#define SIPE_FT_TCP_PORT_MIN 6891\n#define SIPE_FT_TCP_PORT_MAX 6901\n\nstatic void\nft_outgoing_init(struct sipe_file_transfer *ft, const gchar *filename,\n\t\t gsize size, const gchar *who);\n\nvoid sipe_ft_raise_error_and_cancel(struct sipe_file_transfer_private *ft_private,\n\t\t\t\t    const gchar *errmsg)\n{\n\tsipe_backend_ft_error(SIPE_FILE_TRANSFER_PUBLIC, errmsg);\n\tsipe_backend_ft_cancel_local(SIPE_FILE_TRANSFER_PUBLIC);\n}\n\nstatic void generate_key(guchar *buffer, gsize size)\n{\n\tgsize i = 0;\n\twhile (i < size) buffer[i++] = rand();\n}\n\nstatic struct sipe_file_transfer *\nsipe_file_transfer_new_outgoing(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_file_transfer_private *ft_private;\n\n\tft_private = g_new0(struct sipe_file_transfer_private, 1);\n\n\tft_private->sipe_private         = sipe_private;\n\n\tft_private->public.ft_init       = ft_outgoing_init;\n\tft_private->public.ft_start      = sipe_ft_tftp_start_sending;\n\tft_private->public.ft_write      = sipe_ft_tftp_write;\n\tft_private->public.ft_cancelled  = sipe_ft_free;\n\tft_private->public.ft_end        = sipe_ft_tftp_stop_sending;\n\n\tft_private->invitation_cookie = g_strdup_printf(\"%u\",\n\t\t\t\t\t\t\trand() % 1000000000);\n\n\treturn SIPE_FILE_TRANSFER_PUBLIC;\n}\n\nstruct sipe_file_transfer *\nsipe_core_ft_create_outgoing(struct sipe_core_public *sipe_public,\n\t\t\t     const gchar *who,\n\t\t\t     const gchar *file)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tstruct sipe_file_transfer *ft;\n\n#ifdef HAVE_XDATA\n\tif (SIPE_CORE_PRIVATE_FLAG_IS(LYNC2013)) {\n\t\tft = sipe_file_transfer_lync_new_outgoing(sipe_private);\n\t} else\n#endif\n\t{\n\t\tft = sipe_file_transfer_new_outgoing(sipe_private);\n\t}\n\n\tif (!ft) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"Couldn't initialize core file \"\n\t\t\t\t\t  \"transfer structure\");\n\t\treturn NULL;\n\t}\n\n\tsipe_backend_ft_outgoing(sipe_public, ft, who, file);\n\n\treturn ft;\n}\n\nvoid\nsipe_ft_free(struct sipe_file_transfer *ft)\n{\n\tstruct sipe_file_transfer_private *ft_private = SIPE_FILE_TRANSFER_PRIVATE;\n\tstruct sip_dialog *dialog = ft_private->dialog;\n\n\tif (dialog)\n\t\tdialog->filetransfers =\n\t\t\t\tg_slist_remove(dialog->filetransfers, ft_private);\n\n\tif (ft->backend_private)\n\t\tsipe_backend_ft_deallocate(ft);\n\n\tif (ft_private->listendata)\n\t\tsipe_backend_network_listen_cancel(ft_private->listendata);\n\n\tif (ft_private->cipher_context)\n\t\tsipe_crypt_ft_destroy(ft_private->cipher_context);\n\n\tif (ft_private->hmac_context)\n\t\tsipe_digest_ft_destroy(ft_private->hmac_context);\n\n\tg_free(ft_private->invitation_cookie);\n\tg_free(ft_private->encrypted_outbuf);\n\tg_free(ft_private);\n}\n\nstatic void sipe_ft_request(struct sipe_file_transfer_private *ft_private,\n\t\t\t    const gchar *body)\n{\n\tstruct sip_dialog *dialog = ft_private->dialog;\n\tsip_transport_request(ft_private->sipe_private,\n\t\t\t      \"MESSAGE\",\n\t\t\t      dialog->with,\n\t\t\t      dialog->with,\n\t\t\t      \"Content-Type: text/x-msmsgsinvite; charset=UTF-8\\r\\n\",\n\t\t\t      body,\n\t\t\t      dialog,\n\t\t\t      NULL);\n}\n\nstatic void\nft_request_denied(struct sipe_file_transfer *ft)\n{\n\tstruct sipe_file_transfer_private *ft_private = SIPE_FILE_TRANSFER_PRIVATE;\n\n\tgchar *body = g_strdup_printf(\"Invitation-Command: CANCEL\\r\\n\"\n\t\t\t\t      \"Invitation-Cookie: %s\\r\\n\"\n\t\t\t\t      \"Cancel-Code: REJECT\\r\\n\",\n\t\t\t\t      ft_private->invitation_cookie);\n\tsipe_ft_request(ft_private, body);\n\tg_free(body);\n\n\tsipe_ft_free(ft);\n}\n\nstatic void\nsend_ft_accept(struct sipe_file_transfer_private *ft_private,\n\t       gboolean send_enc_key,\n\t       gboolean send_connect_data,\n\t       gboolean sender_connect)\n{\n\tGString *body = g_string_new(\"\");\n\n\tg_string_append_printf(body,\n\t\t\t       \"Invitation-Command: ACCEPT\\r\\n\"\n\t\t\t       \"Request-Data: IP-Address:\\r\\n\"\n\t\t\t       \"Invitation-Cookie: %s\\r\\n\",\n\t\t\t       ft_private->invitation_cookie);\n\n\tif (send_enc_key) {\n\t\tgchar *b64_encryption_key;\n\t\tgchar *b64_hash_key;\n\n\t\tb64_encryption_key = g_base64_encode(ft_private->encryption_key,\n\t\t\t\t\t\t     SIPE_FT_KEY_LENGTH);\n\t\tb64_hash_key = g_base64_encode(ft_private->hash_key,\n\t\t\t\t\t       SIPE_FT_KEY_LENGTH);\n\n\t\tg_string_append_printf(body,\n\t\t\t\t       \"Encryption-Key: %s\\r\\n\"\n\t\t\t\t       \"Hash-Key: %s\\r\\n\",\n\t\t\t\t       b64_encryption_key,\n\t\t\t\t       b64_hash_key);\n\n\t\tg_free(b64_hash_key);\n\t\tg_free(b64_encryption_key);\n\t}\n\n\tif (send_connect_data) {\n\t\tstruct sipe_core_private *sipe_private = ft_private->sipe_private;\n\n\t\tg_string_append_printf(body,\n\t\t\t\t       \"IP-Address: %s\\r\\n\"\n\t\t\t\t       \"Port: %d\\r\\n\"\n\t\t\t\t       \"PortX: 11178\\r\\n\"\n\t\t\t\t       \"AuthCookie: %u\\r\\n\",\n\t\t\t\t       sip_transport_ip_address(sipe_private),\n\t\t\t\t       ft_private->port,\n\t\t\t\t       ft_private->auth_cookie);\n\t}\n\n\tif (sender_connect) {\n\t\tg_string_append(body,\n\t\t\t\t\"Sender-Connect: TRUE\\r\\n\");\n\t}\n\n\tsipe_ft_request(ft_private, body->str);\n\n\tg_string_free(body, TRUE);\n}\n\nstatic void\nlisten_socket_created_cb(unsigned short port, gpointer data)\n{\n\tstruct sipe_file_transfer *ft = data;\n\n\tSIPE_FILE_TRANSFER_PRIVATE->port = port;\n\tSIPE_FILE_TRANSFER_PRIVATE->auth_cookie = rand() % 1000000000;\n\n\tif (sipe_backend_ft_is_incoming(ft))\n\t\tsend_ft_accept(SIPE_FILE_TRANSFER_PRIVATE, TRUE, TRUE, TRUE);\n\telse\n\t\tsend_ft_accept(SIPE_FILE_TRANSFER_PRIVATE, FALSE, TRUE, FALSE);\n}\n\nstatic void\nclient_connected_cb(struct sipe_backend_fd *fd, gpointer data)\n{\n\tstruct sipe_file_transfer *ft = data;\n\n\tSIPE_FILE_TRANSFER_PRIVATE->listendata = NULL;\n\n\tif (!sipe_backend_fd_is_valid(fd)) {\n\t\tsipe_backend_ft_error(ft, _(\"Socket read failed\"));\n\t\tsipe_backend_ft_cancel_local(ft);\n\t} else {\n\t\tsipe_backend_ft_start(ft, fd, NULL, 0);\n\t}\n\n\tsipe_backend_fd_free(fd);\n}\n\nstatic void\nft_incoming_init(struct sipe_file_transfer *ft,\n\t\t SIPE_UNUSED_PARAMETER const gchar *filename,\n\t\t SIPE_UNUSED_PARAMETER gsize size,\n\t\t SIPE_UNUSED_PARAMETER const gchar *who)\n{\n\tstruct sipe_file_transfer_private *ft_private = SIPE_FILE_TRANSFER_PRIVATE;\n\n\tif (ft_private->peer_using_nat) {\n\t\tft_private->listendata =\n\t\t\tsipe_backend_network_listen_range(SIPE_FT_TCP_PORT_MIN,\n\t\t\t\t\t\t\t  SIPE_FT_TCP_PORT_MAX,\n\t\t\t\t\t\t\t  listen_socket_created_cb,\n\t\t\t\t\t\t\t  client_connected_cb,\n\t\t\t\t\t\t\t  ft);\n\t} else {\n\t\tsend_ft_accept(ft_private, TRUE, FALSE, FALSE);\n\t}\n}\n\nstatic void\nft_outgoing_init(struct sipe_file_transfer *ft, const gchar *filename,\n\t\t gsize size, const gchar *who)\n{\n\tstruct sipe_file_transfer_private *ft_private = SIPE_FILE_TRANSFER_PRIVATE;\n\tstruct sipe_core_private *sipe_private = ft_private->sipe_private;\n\tstruct sip_dialog *dialog;\n\n\tconst gchar *ip = sip_transport_ip_address(sipe_private);\n\tgchar *body = g_strdup_printf(\"Application-Name: File Transfer\\r\\n\"\n\t\t\t\t      \"Application-GUID: {5D3E02AB-6190-11d3-BBBB-00C04F795683}\\r\\n\"\n\t\t\t\t      \"Invitation-Command: INVITE\\r\\n\"\n\t\t\t\t      \"Invitation-Cookie: %s\\r\\n\"\n\t\t\t\t      \"Application-File: %s\\r\\n\"\n\t\t\t\t      \"Application-FileSize: %\" G_GSIZE_FORMAT \"\\r\\n\"\n\t\t\t\t      \"%s\"\n\t\t\t\t      \"Encryption: R\\r\\n\", // TODO: non encrypted file transfer support\n\t\t\t\t      ft_private->invitation_cookie,\n\t\t\t\t      filename,\n\t\t\t\t      size,\n\t\t\t\t      sipe_utils_ip_is_private(ip) ? \"Connectivity: N\\r\\n\" : \"\");\n\n\tstruct sip_session *session = sipe_session_find_or_add_im(sipe_private, who);\n\n\t// Queue the message\n\tsipe_session_enqueue_message(session, body, \"text/x-msmsgsinvite\");\n\n\tdialog = sipe_dialog_find(session, who);\n\tif (dialog && !dialog->outgoing_invite) {\n\t\tsipe_im_process_queue(sipe_private, session);\n\t} else if (!dialog || !dialog->outgoing_invite) {\n\t\t// Need to send the INVITE to get the outgoing dialog setup\n\t\tsipe_im_invite(sipe_private, session, who, body, \"text/x-msmsgsinvite\", NULL, FALSE);\n\t\tdialog = sipe_dialog_find(session, who);\n\t}\n\n\tdialog->filetransfers = g_slist_append(dialog->filetransfers, ft_private);\n\tft_private->dialog = dialog;\n\n\tg_free(body);\n}\n\nvoid sipe_ft_incoming_transfer(struct sipe_core_private *sipe_private,\n\t\t\t       struct sip_dialog *dialog,\n\t\t\t       const GSList *body)\n{\n\tstruct sipe_file_transfer_private *ft_private;\n\tgsize file_size;\n\n\tft_private = g_new0(struct sipe_file_transfer_private, 1);\n\tft_private->sipe_private = sipe_private;\n\n\tft_private->public.ft_init           = ft_incoming_init;\n\tft_private->public.ft_start          = sipe_ft_tftp_start_receiving;\n\tft_private->public.ft_read           = sipe_ft_tftp_read;\n\tft_private->public.ft_cancelled      = sipe_ft_free;\n\tft_private->public.ft_end            = sipe_ft_tftp_stop_receiving;\n\tft_private->public.ft_request_denied = ft_request_denied;\n\n\tgenerate_key(ft_private->encryption_key, SIPE_FT_KEY_LENGTH);\n\tgenerate_key(ft_private->hash_key, SIPE_FT_KEY_LENGTH);\n\n\tft_private->invitation_cookie = g_strdup(sipe_utils_nameval_find(body, \"Invitation-Cookie\"));\n\tft_private->peer_using_nat = sipe_strequal(sipe_utils_nameval_find(body, \"Connectivity\"), \"N\");\n\n\tft_private->dialog = dialog;\n\n\tfile_size = g_ascii_strtoull(sipe_utils_nameval_find(body,\n\t\t\t\t\t\t\t     \"Application-FileSize\"),\n\t\t\t\t     NULL, 10);\n\tsipe_backend_ft_incoming(SIPE_CORE_PUBLIC,\n\t\t\t\t SIPE_FILE_TRANSFER_PUBLIC,\n\t\t\t\t dialog->with,\n\t\t\t\t sipe_utils_nameval_find(body, \"Application-File\"),\n\t\t\t\t file_size);\n\n\tif (ft_private->public.backend_private != NULL) {\n\t\tft_private->dialog->filetransfers = g_slist_append(ft_private->dialog->filetransfers, ft_private);\n\t} else {\n\t\tsipe_ft_free(SIPE_FILE_TRANSFER_PUBLIC);\n\t}\n}\n\nstatic struct sipe_file_transfer_private *\nsipe_find_ft(const struct sip_dialog *dialog, const gchar *inv_cookie)\n{\n\tGSList *ftlist = dialog->filetransfers;\n\tfor (; ftlist != NULL; ftlist = ftlist->next) {\n\t\tstruct sipe_file_transfer_private *ft_private = ftlist->data;\n\t\tif (sipe_strequal(ft_private->invitation_cookie, inv_cookie))\n\t\t\treturn ft_private;\n\t}\n\treturn NULL;\n}\n\nvoid sipe_ft_incoming_accept(struct sip_dialog *dialog, const GSList *body)\n{\n\tconst gchar *inv_cookie = sipe_utils_nameval_find(body, \"Invitation-Cookie\");\n\tstruct sipe_file_transfer_private *ft_private = sipe_find_ft(dialog, inv_cookie);\n\n\tif (ft_private) {\n\t\tconst gchar *ip           = sipe_utils_nameval_find(body, \"IP-Address\");\n\t\tconst gchar *port_str     = sipe_utils_nameval_find(body, \"Port\");\n\t\tconst gchar *auth_cookie  = sipe_utils_nameval_find(body, \"AuthCookie\");\n\t\tconst gchar *enc_key_b64  = sipe_utils_nameval_find(body, \"Encryption-Key\");\n\t\tconst gchar *hash_key_b64 = sipe_utils_nameval_find(body, \"Hash-Key\");\n\n\t\tif (auth_cookie)\n\t\t\tft_private->auth_cookie = g_ascii_strtoull(auth_cookie,\n\t\t\t\t\t\t\t\t   NULL, 10);\n\t\tif (enc_key_b64) {\n\t\t\tgsize ret_len;\n\t\t\tguchar *enc_key = g_base64_decode(enc_key_b64,\n\t\t\t\t\t\t\t  &ret_len);\n\t\t\tif (ret_len == SIPE_FT_KEY_LENGTH) {\n\t\t\t\tmemcpy(ft_private->encryption_key,\n\t\t\t\t       enc_key, SIPE_FT_KEY_LENGTH);\n\t\t\t} else {\n\t\t\t\tsipe_ft_raise_error_and_cancel(ft_private,\n\t\t\t\t\t\t\t  _(\"Received encryption key has wrong size.\"));\n\t\t\t\tg_free(enc_key);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tg_free(enc_key);\n\t\t}\n\t\tif (hash_key_b64) {\n\t\t\tgsize ret_len;\n\t\t\tguchar *hash_key = g_base64_decode(hash_key_b64,\n\t\t\t\t\t\t\t   &ret_len);\n\t\t\tif (ret_len == SIPE_FT_KEY_LENGTH) {\n\t\t\t\tmemcpy(ft_private->hash_key,\n\t\t\t\t       hash_key, SIPE_FT_KEY_LENGTH);\n\t\t\t} else {\n\t\t\t\tsipe_ft_raise_error_and_cancel(ft_private,\n\t\t\t\t\t\t\t  _(\"Received hash key has wrong size.\"));\n\t\t\t\tg_free(hash_key);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tg_free(hash_key);\n\t\t}\n\n\n\t\tif (ip && port_str) {\n\t\t\tsipe_backend_ft_start(SIPE_FILE_TRANSFER_PUBLIC, NULL, ip,\n\t\t\t\t\t      g_ascii_strtoull(port_str, NULL, 10));\n\t\t} else {\n\t\t\tft_private->listendata =\n\t\t\t\tsipe_backend_network_listen_range(SIPE_FT_TCP_PORT_MIN,\n\t\t\t\t\t\t\t\t  SIPE_FT_TCP_PORT_MAX,\n\t\t\t\t\t\t\t\t  listen_socket_created_cb,\n\t\t\t\t\t\t\t\t  client_connected_cb,\n\t\t\t\t\t\t\t\t  ft_private);\n\t\t\tif (!ft_private->listendata)\n\t\t\t\tsipe_ft_raise_error_and_cancel(ft_private,\n\t\t\t\t\t\t\t  _(\"Could not create listen socket\"));\n\t\t}\n\t}\n}\n\nvoid sipe_ft_incoming_cancel(struct sip_dialog *dialog, const GSList *body)\n{\n\tconst gchar *inv_cookie = sipe_utils_nameval_find(body, \"Invitation-Cookie\");\n\tstruct sipe_file_transfer_private *ft_private = sipe_find_ft(dialog, inv_cookie);\n\n\tif (ft_private)\n\t\tsipe_backend_ft_cancel_remote(SIPE_FILE_TRANSFER_PUBLIC);\n}\n\nGSList *sipe_ft_parse_msg_body(const gchar *body)\n{\n\tGSList *list = NULL;\n\tgchar **lines = g_strsplit(body, \"\\r\\n\", 0);\n\tif (sipe_utils_parse_lines(&list, lines, \":\") == FALSE) {\n\t\tsipe_utils_nameval_free(list);\n\t\tlist = NULL;\n\t}\n\tg_strfreev(lines);\n\treturn list;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-ft.h",
    "content": "/**\n * @file sipe-ft.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2010 Jakub Adam <jakub.adam@ktknet.cz>\n * Copyright (C) 2010 Tomáš Hrabčík <tomas.hrabcik@tieto.com>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\n\n#define SIPE_FT_KEY_LENGTH 24\n\n/**\n * File transport (private part)\n */\nstruct sipe_file_transfer_private {\n\tstruct sipe_file_transfer public;\n\n\tstruct sipe_core_private *sipe_private;\n\n\tgboolean peer_using_nat;\n\tunsigned short port;\n\n\tguchar encryption_key[SIPE_FT_KEY_LENGTH];\n\tguchar hash_key[SIPE_FT_KEY_LENGTH];\n\tunsigned auth_cookie;\n\tgchar *invitation_cookie;\n\n\tstruct sip_dialog *dialog;\n\n\tgpointer cipher_context;\n\tgpointer hmac_context;\n\n\tgsize bytes_remaining_chunk;\n\n\tguchar *encrypted_outbuf;\n\tguchar *outbuf_ptr;\n\tgsize outbuf_size;\n\n\tstruct sipe_backend_listendata *listendata;\n};\n#define SIPE_FILE_TRANSFER_PUBLIC  ((struct sipe_file_transfer *) ft_private)\n#define SIPE_FILE_TRANSFER_PRIVATE ((struct sipe_file_transfer_private *) ft)\n\n/**\n * Called when remote peer wants to send a file.\n *\n * Function initializes libpurple filetransfer API structure and calls\n * purple_xfer_request().\n *\n * @param sipe_private Sipe core private data\n * @param dialog       SIP dialog used for the file transfer\n * @param body         parsed SIP message body as name-value pairs\n */\nvoid sipe_ft_incoming_transfer(struct sipe_core_private *sipe_private,\n\t\t\t       struct sip_dialog *dialog,\n\t\t\t       const GSList *body);\n\n/**\n * Handles incoming filetransfer message with ACCEPT invitation command.\n *\n * This message is sent during the negotiation phase when parameters of the\n * transfer like IP address or TCP port are going to be set up.\n *\n * @param dialog       SIP dialog used for the file transfer\n * @param body         parsed SIP message body as name-value pairs\n */\nvoid sipe_ft_incoming_accept(struct sip_dialog *dialog, const GSList *body);\n\n/**\n * Called when remote peer cancels ongoing file transfer.\n *\n * Function dispatches the request to libpurple\n *\n * @param dialog       SIP dialog used for the file transfer\n * @param body         parsed SIP message body as name-value pairs\n */\nvoid sipe_ft_incoming_cancel(struct sip_dialog *dialog, const GSList *body);\n\n/**\n * Parses file transfer message body and creates a list with name-value pairs\n *\n * @param body file transfer SIP message body\n *\n * @return GSList of name-value pairs parsed from message body, NULL if body has\n * incorrect format\n */\nGSList *sipe_ft_parse_msg_body(const gchar *body);\n\nvoid sipe_ft_raise_error_and_cancel(struct sipe_file_transfer_private *ft_private,\n\t\t\t\t    const gchar *errmsg);\n\n/**\n * Deallocates a sipe_file_transfer structure.\n *\n * @param ft [in] a sipe_file_transfer structure.\n */\nvoid sipe_ft_free(struct sipe_file_transfer *ft);\n"
  },
  {
    "path": "src/core/sipe-generic-tests.c",
    "content": "/**\n * @file sipe-generic-tests.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdint.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-crypt.h\"\n#include \"sipe-utils.h\"\n#include \"sip-transport.h\"\n\n/*\n * Stubs\n */\ngboolean sipe_backend_debug_enabled(void)\n{\n\treturn(TRUE);\n}\n\nvoid sipe_backend_debug_literal(sipe_debug_level level,\n\t\t\t\tconst gchar *msg)\n{\n\tprintf(\"DEBUG(%d): %s\\n\", level, msg);\n}\n\nvoid sipe_backend_debug(sipe_debug_level level,\n\t\t\tconst gchar *format,\n\t\t\t...)\n{\n\tva_list ap;\n\tgchar *newformat = g_strdup_printf(\"DEBUG(%d): %s\\n\", level, format);\n\n\tva_start(ap, format);\n\tvprintf(newformat, ap);\n\tva_end(ap);\n\n\tg_free(newformat);\n}\n\nconst gchar *sip_transport_epid(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private)\n{\n\treturn(NULL);\n}\n\n/* needed when linking against NSS */\nvoid md4sum(const uint8_t *data, uint32_t length, uint8_t *digest);\nvoid md4sum(SIPE_UNUSED_PARAMETER const uint8_t *data,\n\t    SIPE_UNUSED_PARAMETER uint32_t length,\n\t    SIPE_UNUSED_PARAMETER uint8_t *digest)\n{\n}\n\n/*\n * Tester code\n */\nstatic guint succeeded = 0;\nstatic guint failed    = 0;\n\nstatic void assert_equal_str(const char *expected, const gchar *got)\n{\n\tif (sipe_strequal(expected, got)) {\n\t\tsucceeded++;\n\t} else {\n\t\tprintf(\"FAILED: %s\\n        %s\\n\", got, expected);\n\t\tfailed++;\n\t}\n}\n\nstatic void assert_equal_uint(gsize expected, gsize got)\n{\n\tif (expected == got) {\n\t\tsucceeded++;\n\t} else {\n\t\tprintf(\"FAILED: %\" G_GSIZE_FORMAT \"\\n        %\" G_GSIZE_FORMAT \"\\n\",\n\t\t       got, expected);\n\t\tfailed++;\n\t}\n}\n\nstatic void tests_sipe_utils_time(void) {\n\tgchar *result_str;\n\ttime_t result_time;\n\n#define UNIX_EPOCH_IN_ISO8601_UTC \"1970-01-01T00:00:00Z\"\n\n\tresult_str = sipe_utils_time_to_str(0);\n\tassert_equal_str(result_str, UNIX_EPOCH_IN_ISO8601_UTC);\n\tg_free(result_str);\n\n\tresult_time = sipe_utils_str_to_time(NULL);\n\tassert_equal_uint(result_time, 0);\n\tresult_time = sipe_utils_str_to_time(UNIX_EPOCH_IN_ISO8601_UTC);\n\tassert_equal_uint(result_time,                   0);\n\t/* handle missing \"Z\" */\n\tresult_time = sipe_utils_str_to_time(\"1970-01-01T00:00:01\");\n\tassert_equal_uint(result_time,                   1);\n\tresult_time = sipe_utils_str_to_time(\"1970-01-01T00:00:20Z\");\n\tassert_equal_uint(result_time,                  20);\n\tresult_time = sipe_utils_str_to_time(\"1970-01-01T00:03:00\");\n\tassert_equal_uint(result_time,              3 * 60);\n\tresult_time = sipe_utils_str_to_time(\"1970-01-01T00:40:00Z\");\n\tassert_equal_uint(result_time,             40 * 60);\n\tresult_time = sipe_utils_str_to_time(\"1970-01-01T05:00:00\");\n\tassert_equal_uint(result_time,         5 * 60 * 60);\n\tresult_time = sipe_utils_str_to_time(\"1970-01-01T23:00:00Z\");\n\tassert_equal_uint(result_time,        23 * 60 * 60);\n\t/* 6th day after epoch */\n\tresult_time = sipe_utils_str_to_time(\"1970-01-07T00:00:00\");\n\tassert_equal_uint(result_time,    6 * 24 * 60 * 60);\n\t/* 17th day after epoch */\n\tresult_time = sipe_utils_str_to_time(\"1970-01-18T00:00:00Z\");\n\tassert_equal_uint(result_time,   17 * 24 * 60 * 60);\n\tresult_time = sipe_utils_str_to_time(\"1970-02-01T00:00:00\");\n\tassert_equal_uint(result_time,   31 * 24 * 60 * 60);\n\tresult_time = sipe_utils_str_to_time(\"1970-12-01T00:00:00Z\");\n\t/* 365 - 31 days */\n\tassert_equal_uint(result_time,  334 * 24 * 60 * 60);\n\tresult_time = sipe_utils_str_to_time(\"1971-01-01T00:00:00\");\n\tassert_equal_uint(result_time,  365 * 24 * 60 * 60);\n}\n\nstatic void generic_tests(void) {\n\ttests_sipe_utils_time();\n}\n\nint main(SIPE_UNUSED_PARAMETER int argc,\n\t SIPE_UNUSED_PARAMETER char *argv[])\n{\n\t/* Initialization for crypto backend (test mode) */\n\tsipe_crypto_init(FALSE);\n\n\tgeneric_tests();\n\n\tprintf(\"Result: %d PASSED %d FAILED\\n\", succeeded, failed);\n\treturn(failed);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-group.c",
    "content": "/**\n * @file sipe-group.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2013 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n\n#include \"sipmsg.h\"\n#include \"sip-soap.h\"\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-buddy.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-group.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-ucs.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n\nstruct sipe_groups {\n\tGSList *list;\n};\n\nstruct group_user_context {\n\tgchar *group_name;\n\tgchar *user_name;\n};\n\nstatic void\nsipe_group_context_destroy(gpointer data)\n{\n\tstruct group_user_context *ctx = data;\n\tg_free(ctx->group_name);\n\tg_free(ctx->user_name);\n\tg_free(ctx);\n}\n\nstatic gboolean\nprocess_add_group_response(struct sipe_core_private *sipe_private,\n\t\t\t   struct sipmsg *msg,\n\t\t\t   struct transaction *trans)\n{\n\tif (msg->response == 200) {\n\t\tstruct sipe_group *group;\n\t\tstruct group_user_context *ctx = trans->payload->data;\n\t\tsipe_xml *xml;\n\t\tconst sipe_xml *node;\n\t\tchar *group_id;\n\n\t\txml = sipe_xml_parse(msg->body, msg->bodylen);\n\t\tif (!xml) {\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tnode = sipe_xml_child(xml, \"Body/addGroup/groupID\");\n\t\tif (!node) {\n\t\t\tsipe_xml_free(xml);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tgroup_id = sipe_xml_data(node);\n\t\tif (!group_id) {\n\t\t\tsipe_xml_free(xml);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tgroup = sipe_group_add(sipe_private,\n\t\t\t\t       ctx->group_name,\n\t\t\t\t       NULL,\n\t\t\t\t       NULL,\n\t\t\t\t       g_ascii_strtoull(group_id, NULL, 10));\n\t\tg_free(group_id);\n\n\t\tif (group) {\n\t\t\tstruct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private,\n\t\t\t\t\t\t\t\t\t  ctx->user_name);\n\t\t\tif (buddy) {\n\t\t\t\tsipe_buddy_insert_group(buddy, group);\n\t\t\t\tsipe_group_update_buddy(sipe_private, buddy);\n\t\t\t}\n\t\t}\n\n\t\tsipe_xml_free(xml);\n\t\treturn TRUE;\n\t}\n\treturn FALSE;\n}\n\nstruct sipe_group*\nsipe_group_find_by_id(struct sipe_core_private *sipe_private,\n\t\t      guint id)\n{\n\tstruct sipe_group *group;\n\tGSList *entry;\n\n\tif (!sipe_private)\n\t\treturn NULL;\n\n\tentry = sipe_private->groups->list;\n\twhile (entry) {\n\t\tgroup = entry->data;\n\t\tif (group->id == id) {\n\t\t\treturn group;\n\t\t}\n\t\tentry = entry->next;\n\t}\n\treturn NULL;\n}\n\nstruct sipe_group*\nsipe_group_find_by_name(struct sipe_core_private *sipe_private,\n\t\t\tconst gchar * name)\n{\n\tstruct sipe_group *group;\n\tGSList *entry;\n\n\tif (!sipe_private || !name)\n\t\treturn NULL;\n\n\tentry = sipe_private->groups->list;\n\twhile (entry) {\n\t\tgroup = entry->data;\n\t\tif (sipe_strequal(group->name, name)) {\n\t\t\treturn group;\n\t\t}\n\t\tentry = entry->next;\n\t}\n\treturn NULL;\n}\n\nvoid\nsipe_group_create(struct sipe_core_private *sipe_private,\n\t\t  struct sipe_ucs_transaction *trans,\n\t\t  const gchar *name,\n\t\t  const gchar *who)\n{\n\t/* \"trans\" is always set for UCS code paths, otherwise NULL */\n\tif (trans) {\n\t\tsipe_ucs_group_create(sipe_private,\n\t\t\t\t      trans,\n\t\t\t\t      name,\n\t\t\t\t      who);\n\t} else {\n\t\tstruct transaction_payload *payload = g_new0(struct transaction_payload, 1);\n\t\tstruct group_user_context *ctx = g_new0(struct group_user_context, 1);\n\t\tconst gchar *soap_name = sipe_strequal(name, _(\"Other Contacts\")) ? \"~\" : name;\n\t\tgchar *request;\n\t\tctx->group_name = g_strdup(name);\n\t\tctx->user_name = g_strdup(who);\n\t\tpayload->destroy = sipe_group_context_destroy;\n\t\tpayload->data = ctx;\n\n\t\t/* soap_name can contain restricted characters */\n\t\trequest = g_markup_printf_escaped(\"<m:name>%s</m:name>\"\n\t\t\t\t\t\t  \"<m:externalURI />\",\n\t\t\t\t\t\t  soap_name);\n\t\tsip_soap_request_cb(sipe_private,\n\t\t\t\t    \"addGroup\",\n\t\t\t\t    request,\n\t\t\t\t    process_add_group_response,\n\t\t\t\t    payload);\n\t\tg_free(request);\n\t}\n}\n\ngboolean sipe_group_rename(struct sipe_core_private *sipe_private,\n\t\t\t   struct sipe_group *group,\n\t\t\t   const gchar *name)\n{\n\tgboolean renamed = sipe_backend_buddy_group_rename(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t   group->name,\n\t\t\t\t\t\t\t   name);\n\tif (renamed) {\n\t\tg_free(group->name);\n\t\tgroup->name = g_strdup(name);\n\t}\n\treturn(renamed);\n}\n\nstruct sipe_group *sipe_group_add(struct sipe_core_private *sipe_private,\n\t\t\t\t  const gchar *name,\n\t\t\t\t  const gchar *exchange_key,\n\t\t\t\t  const gchar *change_key,\n\t\t\t\t  guint id)\n{\n\tstruct sipe_group *group = NULL;\n\n\tif (!is_empty(name)) {\n\t\tgroup = sipe_group_find_by_name(sipe_private, name);\n\n\t\tif (!group &&\n\t\t    sipe_backend_buddy_group_add(SIPE_CORE_PUBLIC, name)) {\n\n\t\t\tgroup       = g_new0(struct sipe_group, 1);\n\t\t\tgroup->name = g_strdup(name);\n\t\t\tgroup->id   = id;\n\n\t\t\tif (exchange_key)\n\t\t\t\tgroup->exchange_key = g_strdup(exchange_key);\n\t\t\tif (change_key)\n\t\t\t\tgroup->change_key = g_strdup(change_key);\n\n\t\t\tsipe_private->groups->list = g_slist_append(sipe_private->groups->list,\n\t\t\t\t\t\t\t\t    group);\n\n\t\t\tSIPE_DEBUG_INFO(\"sipe_group_add: created backend group '%s' with id %d\",\n\t\t\t\t\tgroup->name, group->id);\n\t\t} else {\n\t\t\tSIPE_DEBUG_INFO(\"sipe_group_add: backend group '%s' already exists\",\n\t\t\t\t\tname ? name : \"\");\n\t\t\tif (group)\n\t\t\t\tgroup->is_obsolete = FALSE;\n\t\t}\n\t}\n\n\treturn(group);\n}\n\nstatic void group_free(struct sipe_core_private *sipe_private,\n\t\t       struct sipe_group *group)\n{\n\tsipe_private->groups->list = g_slist_remove(sipe_private->groups->list,\n\t\t\t\t\t\t    group);\n\tg_free(group->name);\n\tg_free(group->exchange_key);\n\tg_free(group->change_key);\n\tg_free(group);\n}\n\nvoid sipe_group_remove(struct sipe_core_private *sipe_private,\n\t\t       struct sipe_group *group)\n{\n\tif (group) {\n\t\tSIPE_DEBUG_INFO(\"sipe_group_remove: %s (id %d)\", group->name, group->id);\n\t\tsipe_backend_buddy_group_remove(SIPE_CORE_PUBLIC, group->name);\n\t\tgroup_free(sipe_private, group);\n\t}\n}\n\nvoid\nsipe_core_group_rename(struct sipe_core_public *sipe_public,\n\t\t       const gchar *old_name,\n\t\t       const gchar *new_name)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tstruct sipe_group *s_group = sipe_group_find_by_name(sipe_private, old_name);\n\n\tif (s_group) {\n\t\tSIPE_DEBUG_INFO(\"sipe_core_group_rename: from '%s' to '%s'\", old_name, new_name);\n\n\t\tif (sipe_ucs_is_migrated(sipe_private)) {\n\t\t\tsipe_ucs_group_rename(sipe_private,\n\t\t\t\t\t      s_group,\n\t\t\t\t\t      new_name);\n\t\t} else {\n\t\t\t/* new_name can contain restricted characters */\n\t\t\tgchar *request = g_markup_printf_escaped(\"<m:groupID>%d</m:groupID>\"\n\t\t\t\t\t\t\t\t \"<m:name>%s</m:name>\"\n\t\t\t\t\t\t\t\t \"<m:externalURI />\",\n\t\t\t\t\t\t\t\t s_group->id,\n\t\t\t\t\t\t\t\t new_name);\n\t\t\tsip_soap_request(sipe_private,\n\t\t\t\t\t \"modifyGroup\",\n\t\t\t\t\t request);\n\t\t\tg_free(request);\n\t\t}\n\n\t\tg_free(s_group->name);\n\t\ts_group->name = g_strdup(new_name);\n\t} else {\n\t\tSIPE_DEBUG_INFO(\"sipe_core_group_rename: cannot find group '%s'\", old_name);\n\t}\n}\n\nvoid\nsipe_core_group_remove(struct sipe_core_public *sipe_public,\n\t\t       const gchar *name)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tstruct sipe_group *s_group = sipe_group_find_by_name(sipe_private, name);\n\n\tif (s_group) {\n\n\t\t/* ignore backend events while deleting obsoleted groups */\n\t\tif (!s_group->is_obsolete) {\n\t\t\tSIPE_DEBUG_INFO(\"sipe_core_group_remove: delete '%s'\", name);\n\n\t\t\tif (sipe_ucs_is_migrated(sipe_private)) {\n\t\t\t\tsipe_ucs_group_remove(sipe_private,\n\t\t\t\t\t\t      s_group);\n\t\t\t} else {\n\t\t\t\tgchar *request = g_strdup_printf(\"<m:groupID>%d</m:groupID>\",\n\t\t\t\t\t\t\t\t s_group->id);\n\t\t\t\tsip_soap_request(sipe_private,\n\t\t\t\t\t\t \"deleteGroup\",\n\t\t\t\t\t\t request);\n\t\t\t\tg_free(request);\n\t\t\t}\n\n\t\t\tgroup_free(sipe_private, s_group);\n\t\t}\n\t} else {\n\t\tSIPE_DEBUG_INFO(\"sipe_core_group_remove: cannot find group '%s'\", name);\n\t}\n}\n\n/**\n * Sends buddy update to server\n *\n * NOTE: must not be called when contact list has been migrated to UCS\n */\nstatic void send_buddy_update(struct sipe_core_private *sipe_private,\n\t\t\t      struct sipe_buddy *buddy,\n\t\t\t      const gchar *alias)\n{\n\tgchar *groups = sipe_buddy_groups_string(buddy);\n\n\tif (groups) {\n\t\tgchar *request;\n\t\tSIPE_DEBUG_INFO(\"Saving buddy %s with alias '%s' and groups '%s'\",\n\t\t\t\tbuddy->name, alias, groups);\n\n\t\t/* alias can contain restricted characters */\n\t\trequest = g_markup_printf_escaped(\"<m:displayName>%s</m:displayName>\"\n\t\t\t\t\t\t  \"<m:groups>%s</m:groups>\"\n\t\t\t\t\t\t  \"<m:subscribed>true</m:subscribed>\"\n\t\t\t\t\t\t  \"<m:URI>%s</m:URI>\"\n\t\t\t\t\t\t  \"<m:externalURI />\",\n\t\t\t\t\t\t  alias ? alias : \"\",\n\t\t\t\t\t\t  groups,\n\t\t\t\t\t\t  buddy->name);\n\t\tg_free(groups);\n\n\t\tsip_soap_request(sipe_private,\n\t\t\t\t \"setContact\",\n\t\t\t\t request);\n\t\tg_free(request);\n\t}\n}\n\n/**\n * indicates that buddy information on the server needs updating\n *\n * NOTE: must not be called when contact list has been migrated to UCS\n */\nvoid sipe_group_update_buddy(struct sipe_core_private *sipe_private,\n\t\t\t     struct sipe_buddy *buddy)\n{\n\tif (buddy) {\n\t\tsipe_backend_buddy backend_buddy = sipe_backend_buddy_find(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\t   buddy->name,\n\t\t\t\t\t\t\t\t\t   NULL);\n\t\tif (backend_buddy) {\n\t\t\tgchar *alias = sipe_backend_buddy_get_alias(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t    backend_buddy);\n\t\t\tsend_buddy_update(sipe_private, buddy, alias);\n\t\t\tg_free(alias);\n\t\t}\n\t}\n}\n\n/**\n * @param alias new alias (may be @c NULL)\n */\nvoid sipe_core_group_set_alias(struct sipe_core_public *sipe_public,\n\t\t\t       const gchar *who,\n\t\t\t       const gchar *alias)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\n\t/* UCS does not support setting of display name/alias */\n\tif (sipe_ucs_is_migrated(sipe_private))\n\t\tSIPE_DEBUG_INFO(\"sipe_core_group_set_alias: not supported for UCS (uri '%s' alias '%s')\",\n\t\t\t\twho, alias ? alias : \"<UNDEFINED>\");\n\telse {\n\t\tstruct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private,\n\t\t\t\t\t\t\t\t  who);\n\n\t\tif (buddy)\n\t\t\tsend_buddy_update(sipe_private, buddy, alias);\n\t}\n}\n\nvoid sipe_group_update_start(struct sipe_core_private *sipe_private)\n{\n\tGSList *entry = sipe_private->groups->list;\n\n\twhile (entry) {\n\t\t((struct sipe_group *) entry->data)->is_obsolete = TRUE;\n\t\tentry = entry->next;\n\t}\n}\n\nvoid sipe_group_update_finish(struct sipe_core_private *sipe_private)\n{\n\tGSList *entry = sipe_private->groups->list;\n\n\twhile (entry) {\n\t\tstruct sipe_group *group = entry->data;\n\n\t\t/* next group entry */\n\t\tentry = entry->next;\n\n\t\tif (group->is_obsolete)\n\t\t\tsipe_group_remove(sipe_private, group);\n\t}\n}\n\nstruct sipe_group *sipe_group_first(struct sipe_core_private *sipe_private)\n{\n\treturn(sipe_private->groups->list ? sipe_private->groups->list->data : NULL);\n}\n\nguint sipe_group_count(struct sipe_core_private *sipe_private)\n{\n\treturn(g_slist_length(sipe_private->groups->list));\n}\n\nvoid sipe_group_init(struct sipe_core_private *sipe_private)\n{\n\tsipe_private->groups = g_new0(struct sipe_groups, 1);\n}\n\nvoid sipe_group_free(struct sipe_core_private *sipe_private)\n{\n\tGSList *entry;\n\n\twhile ((entry = sipe_private->groups->list) != NULL)\n\t\tgroup_free(sipe_private, entry->data);\n\n\tg_free(sipe_private->groups);\n\tsipe_private->groups = NULL;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-group.h",
    "content": "/**\n * @file sipe-group.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipe_buddy;\nstruct sipe_core_private;\nstruct sipe_ucs_transaction;\n\nstruct sipe_group {\n\tgchar *name;\n\tgchar *exchange_key;\n\tgchar *change_key;\n\tguint id;\n\tgboolean is_obsolete;\n};\n\nstruct sipe_group *sipe_group_find_by_id(struct sipe_core_private *sipe_private,\n\t\t\t\t\t guint id);\n\nstruct sipe_group *sipe_group_find_by_name(struct sipe_core_private *sipe_private,\n\t\t\t\t\t   const gchar * name);\n\n/**\n * Request creation of group @c name on the server and add buddy @c who to it\n *\n * @param sipe_private SIPE core data\n * @param trans        UCS transaction (@c NULL when UCS is not in use)\n * @param name         name of group\n * @param who          SIP URI of buddy (may be @c NULL, i.e. empty group)\n */\nvoid sipe_group_create(struct sipe_core_private *sipe_private,\n\t\t       struct sipe_ucs_transaction *trans,\n\t\t       const gchar *name,\n\t\t       const gchar *who);\n\ngboolean sipe_group_rename(struct sipe_core_private *sipe_private,\n\t\t\t   struct sipe_group *group,\n\t\t\t   const gchar *name);\n\n/**\n * Creates @c sipe_group structure for a new group and adds it into the group\n * list of given account. If buddy is already in the list, its existing\n * structure is returned.\n *\n * @param sipe_private SIPE core data\n * @param name         name of group (may be @c NULL)\n * @param exchange_key Exchange key (may be @c NULL)\n * @param change_key   Change key (may be @c NULL)\n * @param id           numeric ID of group\n *\n * @return @c sipe_group structure or @c NULL if group creation failed\n */\nstruct sipe_group *sipe_group_add(struct sipe_core_private *sipe_private,\n\t\t\t\t  const gchar *name,\n\t\t\t\t  const gchar *exchange_key,\n\t\t\t\t  const gchar *change_key,\n\t\t\t\t  guint id);\n\n/* remove group from core & backend */\nvoid sipe_group_remove(struct sipe_core_private *sipe_private,\n\t\t       struct sipe_group *group);\n\n/* update alias/group list for a buddy on the server */\nvoid sipe_group_update_buddy(struct sipe_core_private *sipe_private,\n\t\t\t     struct sipe_buddy *buddy);\n\n/**\n * Prepare group list for an update\n *\n * @param sipe_private SIPE core data\n */\nvoid sipe_group_update_start(struct sipe_core_private *sipe_private);\n\n/**\n * Finish group list update. This will remove obsolete groups.\n *\n * NOTE: this must be call after sipe_buddy_update_finish(), i.e. it\n *       assumes that the group is no longer associated with any buddy.\n *\n * @param sipe_private SIPE core data\n */\nvoid sipe_group_update_finish(struct sipe_core_private *sipe_private);\n\n/**\n * Return first group\n *\n * @param sipe_private SIPE core data\n *\n * @return sipe_group structure or @c NULL if there are no groups\n */\nstruct sipe_group *sipe_group_first(struct sipe_core_private *sipe_private);\n\n/**\n * Number of groups\n *\n * @param sipe_private SIPE core data\n */\nguint sipe_group_count(struct sipe_core_private *sipe_private);\n\n/**\n * Initialize group data\n *\n * @param sipe_private SIPE core data\n */\nvoid sipe_group_init(struct sipe_core_private *sipe_private);\n\n/**\n * Free group data\n *\n * @param sipe_private SIPE core data\n */\nvoid sipe_group_free(struct sipe_core_private *sipe_private);\n"
  },
  {
    "path": "src/core/sipe-groupchat.c",
    "content": "/**\n * @file sipe-groupchat.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/**\n * This module implements the OCS2007R2 Group Chat functionality\n *\n * Documentation references:\n *\n *  Microsoft TechNet: Key Protocols and Windows Services Used by Group Chat\n *   <http://technet.microsoft.com/en-us/library/ee323484%28office.13%29.aspx>\n *  Microsoft TechNet: Group Chat Call Flows\n *   <http://technet.microsoft.com/en-us/library/ee323524%28office.13%29.aspx>\n *  Microsoft Office Communications Server 2007 R2 Technical Reference Guide\n *   <http://go.microsoft.com/fwlink/?LinkID=159649>\n *  Microsoft DevNet: [MS-XCCOSIP] Extensible Chat Control Over SIP\n *   <http://msdn.microsoft.com/en-us/library/hh624112.aspx>\n *  RFC 4028: Session Timers in the Session Initiation Protocol (SIP)\n *   <http://www.rfc-editor.org/rfc/rfc4028.txt>\n *\n *\n * @TODO:\n *\n *   -.cmd:getserverinfo\n *       <sib domain=\"<DOMAIN>\" infoType=\"123\" />\n *     rpl:getservinfo\n *       <sib infoType=\"123\"\n *          serverTime=\"2010-09-14T14:26:17.6206356Z\"\n *          searchLimit=\"999\"\n *          messageSizeLimit=\"512\"\n *          storySizeLimit=\"4096\"\n *          rootUri=\"ma-cat://<DOMAIN>/<GUID>\"\n *          dbVersion=\"3ea3a5a8-ef36-46cf-898f-7a5133931d63\"\n *       />\n *\n *     is there any information in there we would need/use?\n *\n *   - cmd:getpref/rpl:getpref/cmd:setpref/rpl:setpref\n *     probably useless, as libpurple stores configuration locally\n *\n *     can store base64 encoded \"free text\" in key/value fashion\n *       <cmd id=\"cmd:getpref\" seqid=\"x\">\n *         <data>\n *           <pref label=\"kedzie.GroupChannels\"\n *             seqid=\"71\"\n *             createdefault=\"true\" />\n *         </data>\n *       </cmd>\n *       <cmd id=\"cmd:setpref\" seqid=\"x\">\n *         <data>\n *           <pref label=\"kedzie.GroupChannels\"\n *             seqid=\"71\"\n *             createdefault=\"false\"\n *             content=\"<BASE64 text>\" />\n *         </data>\n *       </cmd>\n *\n *     use this to sync chats in buddy list on multiple clients?\n *\n *   - cmd:getinv\n *       <inv inviteId=\"1\" domain=\"<DOMAIN>\" />\n *     rpl:getinv\n *       ???\n *\n *     according to documentation should provide list of outstanding invites.\n *     [no log file examples]\n *     should we automatically join those channels or ask user to join/add?\n *\n *   - chatserver_command_message()\n *     needs to support multiple <grpchat> nodes?\n *     [no log file examples]\n *\n *   - create/delete chat rooms\n *     [no log file examples]\n *     are these related to this functionality?\n *\n *     <cmd id=\"cmd:nodespermcreatechild\" seqid=\"1\">\n *       <data />\n *     </cmd>\n *     <rpl id=\"rpl:nodespermcreatechild\" seqid=\"1\">\n *       <commandid seqid=\"1\" envid=\"xxx\" />\n *       <resp code=\"200\">SUCCESS_OK</resp>\n *       <data />\n *     </rpl>\n *\n *   - file transfer (uses HTTPS PUT/GET via a filestore server)\n *     [no log file examples]\n *\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipmsg.h\"\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-chat.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-dialog.h\"\n#include \"sipe-groupchat.h\"\n#include \"sipe-im.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-schedule.h\"\n#include \"sipe-session.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n\n#define GROUPCHAT_RETRY_TIMEOUT 5*60 /* seconds */\n\n/**\n * aib node - magic numbers?\n *\n * Example:\n * <aib key=\"3984\" value=\"0,1,2,3,4,5,7,9,10,12,13,14,15,16,17\" />\n * <aib key=\"12276\" value=\"6,8,11\" />\n *\n * \"value\" corresponds to the \"id\" attribute in uib nodes.\n *\n * @TODO: Confirm \"guessed\" meaning of the magic numbers:\n *        3984  = normal users\n *        12276 = channel operators\n */\n#define GROUPCHAT_AIB_KEY_USER    \"3984\"\n#define GROUPCHAT_AIB_KEY_CHANOP \"12276\"\n\nstruct sipe_groupchat {\n\tstruct sip_session *session;\n\tgchar *domain;\n\tGSList *join_queue;\n\tGHashTable *uri_to_chat_session;\n\tGHashTable *msgs;\n\tguint envid;\n\tguint expires;\n\tgboolean connected;\n};\n\nstruct sipe_groupchat_msg {\n\tGHashTable *container;\n\tstruct sipe_chat_session *session;\n\tgchar *content;\n\tgchar *xccos;\n\tguint envid;\n};\n\n/* GDestroyNotify */\nstatic void sipe_groupchat_msg_free(gpointer data) {\n\tstruct sipe_groupchat_msg *msg = data;\n\tg_free(msg->content);\n\tg_free(msg->xccos);\n\tg_free(msg);\n}\n\n/* GDestroyNotify */\nstatic void sipe_groupchat_msg_remove(gpointer data) {\n\tstruct sipe_groupchat_msg *msg = data;\n\tg_hash_table_remove(msg->container, &msg->envid);\n}\n\nstatic void sipe_groupchat_allocate(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_groupchat *groupchat = g_new0(struct sipe_groupchat, 1);\n\n\tgroupchat->uri_to_chat_session = g_hash_table_new(g_str_hash, g_str_equal);\n\tgroupchat->msgs = g_hash_table_new_full(g_int_hash, g_int_equal,\n\t\t\t\t\t\tNULL,\n\t\t\t\t\t\tsipe_groupchat_msg_free);\n\tgroupchat->envid = rand();\n\tgroupchat->connected = FALSE;\n\tsipe_private->groupchat = groupchat;\n}\n\nstatic void sipe_groupchat_free_join_queue(struct sipe_groupchat *groupchat)\n{\n\tsipe_utils_slist_free_full(groupchat->join_queue, g_free);\n\tgroupchat->join_queue = NULL;\n}\n\nvoid sipe_groupchat_free(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_groupchat *groupchat = sipe_private->groupchat;\n\tif (groupchat) {\n\t\tsipe_groupchat_free_join_queue(groupchat);\n\t\tg_hash_table_destroy(groupchat->msgs);\n\t\tg_hash_table_destroy(groupchat->uri_to_chat_session);\n\t\tg_free(groupchat->domain);\n\t\tg_free(groupchat);\n\t\tsipe_private->groupchat = NULL;\n\t}\n}\n\nstatic struct sipe_groupchat_msg *generate_xccos_message(struct sipe_groupchat *groupchat,\n\t\t\t\t\t\t\t const gchar *content)\n{\n\tstruct sipe_groupchat_msg *msg = g_new0(struct sipe_groupchat_msg, 1);\n\n\tmsg->container = groupchat->msgs;\n\tmsg->envid     = groupchat->envid++;\n\tmsg->xccos     = g_strdup_printf(\"<xccos ver=\\\"1\\\" envid=\\\"%u\\\" xmlns=\\\"urn:parlano:xml:ns:xccos\\\">\"\n\t\t\t\t\t \"%s\"\n\t\t\t\t\t \"</xccos>\",\n\t\t\t\t\t msg->envid,\n\t\t\t\t\t content);\n\n\tg_hash_table_insert(groupchat->msgs, &msg->envid, msg);\n\n\treturn(msg);\n}\n\n/**\n * Create short-lived dialog with ocschat@<domain> (or user specified value)\n * This initiates the Group Chat feature\n */\nvoid sipe_groupchat_init(struct sipe_core_private *sipe_private)\n{\n\tconst gchar *setting = sipe_backend_setting(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t    SIPE_SETTING_GROUPCHAT_USER);\n\tconst gchar *persistent = sipe_private->persistentChatPool_uri;\n\tgboolean user_set    = !is_empty(setting);\n\tgboolean provisioned = !is_empty(persistent);\n\tgchar **parts = g_strsplit(user_set ? setting :\n\t\t\t\t   provisioned ? persistent :\n\t\t\t\t   sipe_private->username, \"@\", 2);\n\tgboolean domain_found = !is_empty(parts[1]);\n\tconst gchar *user = \"ocschat\";\n\tconst gchar *domain = parts[domain_found ? 1 : 0];\n\tgchar *chat_uri;\n\tstruct sip_session *session;\n\tstruct sipe_groupchat *groupchat;\n\n\t/* User specified or provisioned URI is valid 'user@company.com' */\n\tif ((user_set || provisioned) && domain_found && !is_empty(parts[0]))\n\t\tuser = parts[0];\n\n\tSIPE_DEBUG_INFO(\"sipe_groupchat_init: username '%s' setting '%s' persistent '%s' split '%s'/'%s' GC user %s@%s\",\n\t\t\tsipe_private->username, setting ? setting : \"(null)\",\n\t\t\tpersistent ? persistent : \"(null)\",\n\t\t\tparts[0], parts[1] ? parts[1] : \"(null)\", user, domain);\n\n\tif (!sipe_private->groupchat)\n\t\tsipe_groupchat_allocate(sipe_private);\n\tgroupchat = sipe_private->groupchat;\n\n\tchat_uri = g_strdup_printf(\"sip:%s@%s\", user, domain);\n\tsession = sipe_session_find_or_add_im(sipe_private,\n\t\t\t\t\t      chat_uri);\n\tsession->is_groupchat = TRUE;\n\tsipe_im_invite(sipe_private, session, chat_uri,\n\t\t       NULL, NULL, NULL, FALSE);\n\n\tg_free(groupchat->domain);\n\tgroupchat->domain = g_strdup(domain);\n\n\tg_free(chat_uri);\n\tg_strfreev(parts);\n}\n\n/* sipe_schedule_action */\nstatic void groupchat_init_retry_cb(struct sipe_core_private *sipe_private,\n\t\t\t\t    SIPE_UNUSED_PARAMETER gpointer data)\n{\n\tsipe_groupchat_init(sipe_private);\n}\n\nstatic void groupchat_init_retry(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_groupchat *groupchat = sipe_private->groupchat;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"groupchat_init_retry: trying again later...\");\n\n\tgroupchat->session = NULL;\n\tgroupchat->connected = FALSE;\n\n\tsipe_schedule_seconds(sipe_private,\n\t\t\t      \"<+groupchat-retry>\",\n\t\t\t      NULL,\n\t\t\t      GROUPCHAT_RETRY_TIMEOUT,\n\t\t\t      groupchat_init_retry_cb,\n\t\t\t      NULL);\n}\n\nvoid sipe_groupchat_invite_failed(struct sipe_core_private *sipe_private,\n\t\t\t\t  struct sip_session *session)\n{\n\tstruct sipe_groupchat *groupchat = sipe_private->groupchat;\n\tconst gchar *setting = sipe_backend_setting(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t    SIPE_SETTING_GROUPCHAT_USER);\n\tgboolean retry = FALSE;\n\n\tif (groupchat->session) {\n\t\t/* response to group chat server invite */\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"can't connect to group chat server!\");\n\n\t\t/* group chat server exists, but communication failed */\n\t\tretry = TRUE;\n\t} else {\n\t\t/* response to initial invite */\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"no group chat server found.\");\n\t}\n\n\tsipe_session_close(sipe_private, session);\n\n\tif (!is_empty(setting)) {\n\t\tgchar *msg = g_strdup_printf(_(\"Group Chat Proxy setting is incorrect:\\n\\n\\t%s\\n\\nPlease update your Account.\"),\n\t\t\t\t\t     setting);\n\t\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t  _(\"Couldn't find Group Chat server!\"),\n\t\t\t\t\t  msg);\n\t\tg_free(msg);\n\n\t\t/* user specified group chat settings: we should retry */\n\t\tretry = TRUE;\n\t}\n\n\tif (retry) {\n\t\tgroupchat_init_retry(sipe_private);\n\t} else {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"disabling group chat feature.\");\n\t}\n}\n\nstatic gchar *generate_chanid_node(const gchar *uri, guint key)\n{\n\t/* ma-chan://<domain>/<value> */\n\tgchar **parts = g_strsplit(uri, \"/\", 4);\n\tgchar *chanid = NULL;\n\n\tif (parts[2] && parts[3]) {\n\t\tchanid = g_strdup_printf(\"<chanid key=\\\"%d\\\" domain=\\\"%s\\\" value=\\\"%s\\\"/>\",\n\t\t\t\t\t key, parts[2], parts[3]);\n\t} else {\n\t\tSIPE_DEBUG_ERROR(\"generate_chanid_node: mal-formed URI '%s'\",\n\t\t\t\t uri);\n\t}\n\tg_strfreev(parts);\n\n\treturn chanid;\n}\n\n/* TransCallback */\nstatic void groupchat_update_cb(struct sipe_core_private *sipe_private,\n\t\t\t\tgpointer data);\nstatic gboolean groupchat_expired_session_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t   struct sipmsg *msg,\n\t\t\t\t\t\t   SIPE_UNUSED_PARAMETER struct transaction *trans)\n{\n\tstruct sipe_groupchat *groupchat = sipe_private->groupchat;\n\n\t/* 481 Call Leg Does Not Exist -> server dropped session */\n\tif (msg->response == 481) {\n\t\tstruct sip_session *session = groupchat->session;\n\t\tstruct sip_dialog *dialog = sipe_dialog_find(session,\n\t\t\t\t\t\t\t     session->with);\n\n\t\tif (dialog) {\n\t\t\t/* close dialog from our side */\n\t\t\tsip_transport_bye(sipe_private, dialog);\n\t\t\tsipe_dialog_remove(session, session->with);\n\t\t\t/* dialog is no longer valid */\n\t\t}\n\n\t\t/* re-initialize groupchat session */\n\t\tgroupchat->session = NULL;\n\t\tgroupchat->connected = FALSE;\n\t\tsipe_groupchat_init(sipe_private);\n\t} else {\n\t\tsipe_schedule_seconds(sipe_private,\n\t\t\t\t      \"<+groupchat-expires>\",\n\t\t\t\t      NULL,\n\t\t\t\t      groupchat->expires,\n\t\t\t\t      groupchat_update_cb,\n\t\t\t\t      NULL);\n\t}\n\n\treturn(TRUE);\n}\n\n/* sipe_schedule_action */\nstatic void groupchat_update_cb(struct sipe_core_private *sipe_private,\n\t\t\t\tSIPE_UNUSED_PARAMETER gpointer data)\n{\n\tstruct sipe_groupchat *groupchat = sipe_private->groupchat;\n\n\tif (groupchat->session) {\n\t\tstruct sip_dialog *dialog = sipe_dialog_find(groupchat->session,\n\t\t\t\t\t\t\t     groupchat->session->with);\n\n\t\tif (dialog)\n\t\t\tsip_transport_update(sipe_private,\n\t\t\t\t\t     dialog,\n\t\t\t\t\t     groupchat_expired_session_response);\n\t}\n}\n\nstatic struct sipe_groupchat_msg *chatserver_command(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t     const gchar *cmd);\n\nvoid sipe_groupchat_invite_response(struct sipe_core_private *sipe_private,\n\t\t\t\t    struct sip_dialog *dialog,\n\t\t\t\t    struct sipmsg *response)\n{\n\tstruct sipe_groupchat *groupchat = sipe_private->groupchat;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_groupchat_invite_response\");\n\n\tif (!groupchat->session) {\n\t\t/* response to initial invite */\n\t\tstruct sipe_groupchat_msg *msg = generate_xccos_message(groupchat,\n\t\t\t\t\t\t\t\t\t\"<cmd id=\\\"cmd:requri\\\" seqid=\\\"1\\\"><data/></cmd>\");\n\t\tconst gchar *session_expires = sipmsg_find_header(response,\n\t\t\t\t\t\t\t\t  \"Session-Expires\");\n\n\t\tsip_transport_info(sipe_private,\n\t\t\t\t   \"Content-Type: text/plain\\r\\n\",\n\t\t\t\t   msg->xccos,\n\t\t\t\t   dialog,\n\t\t\t\t   NULL);\n\t\tsipe_groupchat_msg_remove(msg);\n\n\t\tif (session_expires) {\n\t\t\tgroupchat->expires = strtoul(session_expires, NULL, 10);\n\n\t\t\tif (groupchat->expires) {\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_groupchat_invite_response: session expires in %d seconds\",\n\t\t\t\t\t\tgroupchat->expires);\n\n\t\t\t\tif (groupchat->expires > 10)\n\t\t\t\t\tgroupchat->expires -= 10;\n\t\t\t\tsipe_schedule_seconds(sipe_private,\n\t\t\t\t\t\t      \"<+groupchat-expires>\",\n\t\t\t\t\t\t      NULL,\n\t\t\t\t\t\t      groupchat->expires,\n\t\t\t\t\t\t      groupchat_update_cb,\n\t\t\t\t\t\t      NULL);\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t/* response to group chat server invite */\n\t\tgchar *invcmd;\n\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"connection to group chat server established.\");\n\n\t\tgroupchat->connected = TRUE;\n\n\t\t/* Any queued joins? */\n\t\tif (groupchat->join_queue) {\n\t\t\tGString *cmd = g_string_new(\"<cmd id=\\\"cmd:bjoin\\\" seqid=\\\"1\\\">\"\n\t\t\t\t\t\t    \"<data>\");\n\t\t\tGSList *entry;\n\t\t\tguint i = 0;\n\n\t\t\t/* We used g_slist_prepend() to create the list */\n\t\t\tgroupchat->join_queue = entry = g_slist_reverse(groupchat->join_queue);\n\t\t\twhile (entry) {\n\t\t\t\tgchar *chanid = generate_chanid_node(entry->data, i++);\n\t\t\t\tg_string_append(cmd, chanid);\n\t\t\t\tg_free(chanid);\n\t\t\t\tentry = entry->next;\n\t\t\t}\n\t\t\tsipe_groupchat_free_join_queue(groupchat);\n\n\t\t\tg_string_append(cmd, \"</data></cmd>\");\n\t\t\tchatserver_command(sipe_private, cmd->str);\n\t\t\tg_string_free(cmd, TRUE);\n\t\t}\n\n\t\t/* Request outstanding invites from server */\n\t\tinvcmd = g_strdup_printf(\"<cmd id=\\\"cmd:getinv\\\" seqid=\\\"1\\\">\"\n\t\t\t\t\t \"<data>\"\n\t\t\t\t\t \"<inv inviteId=\\\"1\\\" domain=\\\"%s\\\"/>\"\n\t\t\t\t\t \"</data>\"\n\t\t\t\t\t \"</cmd>\", groupchat->domain);\n\t\tchatserver_command(sipe_private, invcmd);\n\t\tg_free(invcmd);\n\t}\n}\n\nstatic void chatserver_command_error_notify(struct sipe_core_private *sipe_private,\n\t\t\t\t\t    struct sipe_chat_session *chat_session,\n\t\t\t\t\t    const gchar *content)\n{\n\tgchar *label  = g_strdup_printf(_(\"This message was not delivered to chat room '%s'\"),\n\t\t\t\t\tchat_session->title);\n\tgchar *errmsg = g_strdup_printf(\"%s:\\n<font color=\\\"#888888\\\"></b>%s<b></font>\",\n\t\t\t\t\tlabel, content);\n\tg_free(label);\n\tsipe_backend_notify_message_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t  chat_session->backend,\n\t\t\t\t\t  NULL,\n\t\t\t\t\t  errmsg);\n\tg_free(errmsg);\n}\n\n/* TransCallback */\nstatic gboolean chatserver_command_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\t    struct sipmsg *msg,\n\t\t\t\t\t    struct transaction *trans)\n{\n\tif (msg->response != 200) {\n\t\tstruct sipe_groupchat_msg *gmsg = trans->payload->data;\n\t\tstruct sipe_chat_session *chat_session = gmsg->session;\n\n\t\tSIPE_DEBUG_INFO(\"chatserver_command_response: failure %d\", msg->response);\n\n\t\tif (chat_session)\n\t\t\tchatserver_command_error_notify(sipe_private,\n\t\t\t\t\t\t\tchat_session,\n\t\t\t\t\t\t\tgmsg->content);\n\n\t\tgroupchat_expired_session_response(sipe_private, msg, trans);\n\t}\n\treturn TRUE;\n}\n\nstatic struct sipe_groupchat_msg *chatserver_command(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t     const gchar *cmd)\n{\n\tstruct sipe_groupchat *groupchat = sipe_private->groupchat;\n\tstruct sipe_groupchat_msg *msg = NULL;\n\n\tif (groupchat->session) {\n\t\tstruct sip_dialog *dialog = sipe_dialog_find(groupchat->session,\n\t\t\t\t\t\t\t     groupchat->session->with);\n\n\t\tif (dialog) {\n\t\t\tstruct transaction *trans;\n\n\t\t\tmsg = generate_xccos_message(groupchat, cmd);\n\t\t\ttrans = sip_transport_info(sipe_private,\n\t\t\t\t\t\t   \"Content-Type: text/plain\\r\\n\",\n\t\t\t\t\t\t   msg->xccos,\n\t\t\t\t\t\t   dialog,\n\t\t\t\t\t\t   chatserver_command_response);\n\n\t\t\tif (trans) {\n\t\t\t\tstruct transaction_payload *payload = g_new0(struct transaction_payload, 1);\n\n\t\t\t\tpayload->destroy = sipe_groupchat_msg_remove;\n\t\t\t\tpayload->data    = msg;\n\t\t\t\ttrans->payload   = payload;\n\t\t\t} else {\n\t\t\t\t/* SIP transport is no longer valid - give up */\n\t\t\t\tsipe_groupchat_msg_remove(msg);\n\t\t\t\tmsg = NULL;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(msg);\n}\n\nstatic void chatserver_response_uri(struct sipe_core_private *sipe_private,\n\t\t\t\t    struct sip_session *session,\n\t\t\t\t    SIPE_UNUSED_PARAMETER guint result,\n\t\t\t\t    SIPE_UNUSED_PARAMETER const gchar *message,\n\t\t\t\t    const sipe_xml *xml)\n{\n\t\tconst sipe_xml *uib = sipe_xml_child(xml, \"uib\");\n\t\tconst gchar *uri = sipe_xml_attribute(uib, \"uri\");\n\n\t\t/* drop connection to ocschat@<domain> again */\n\t\tsipe_session_close(sipe_private, session);\n\n\t\tif (uri) {\n\t\t\tstruct sipe_groupchat *groupchat = sipe_private->groupchat;\n\n\t\t\tSIPE_DEBUG_INFO(\"chatserver_response_uri: '%s'\", uri);\n\n\t\t\tgroupchat->session = session = sipe_session_find_or_add_im(sipe_private,\n\t\t\t\t\t\t\t\t\t\t   uri);\n\n\t\t\tsession->is_groupchat = TRUE;\n\t\t\tsipe_im_invite(sipe_private, session, uri, NULL, NULL, NULL, FALSE);\n\t\t} else {\n\t\t\tSIPE_DEBUG_WARNING_NOFORMAT(\"chatserver_response_uri: no server URI found!\");\n\t\t\tgroupchat_init_retry(sipe_private);\n\t\t}\n}\n\nstatic void chatserver_response_channel_search(struct sipe_core_private *sipe_private,\n\t\t\t\t\t       SIPE_UNUSED_PARAMETER struct sip_session *session,\n\t\t\t\t\t       guint result,\n\t\t\t\t\t       const gchar *message,\n\t\t\t\t\t       const sipe_xml *xml)\n{\n\tstruct sipe_core_public *sipe_public = SIPE_CORE_PUBLIC;\n\n\tif (result != 200) {\n\t\tsipe_backend_notify_error(sipe_public,\n\t\t\t\t\t  _(\"Error retrieving room list\"),\n\t\t\t\t\t  message);\n\t} else {\n\t\tconst sipe_xml *chanib;\n\n\t\tfor (chanib = sipe_xml_child(xml, \"chanib\");\n\t\t     chanib;\n\t\t     chanib = sipe_xml_twin(chanib)) {\n\t\t\tconst gchar *name = sipe_xml_attribute(chanib, \"name\");\n\t\t\tconst gchar *desc = sipe_xml_attribute(chanib, \"description\");\n\t\t\tconst gchar *uri  = sipe_xml_attribute(chanib, \"uri\");\n\t\t\tconst sipe_xml *node;\n\t\t\tguint user_count = 0;\n\t\t\tguint32 flags = 0;\n\n\t\t\t/* information */\n\t\t\tfor (node = sipe_xml_child(chanib, \"info\");\n\t\t\t     node;\n\t\t\t     node = sipe_xml_twin(node)) {\n\t\t\t\tconst gchar *id = sipe_xml_attribute(node, \"id\");\n\t\t\t\tgchar *data;\n\n\t\t\t\tif (!id) continue;\n\n\t\t\t\tdata = sipe_xml_data(node);\n\t\t\t\tif (data) {\n\t\t\t\t\tif        (sipe_strcase_equal(id, \"urn:parlano:ma:info:ucnt\")) {\n\t\t\t\t\t\tuser_count = g_ascii_strtoll(data, NULL, 10);\n\t\t\t\t\t} else if (sipe_strcase_equal(id, \"urn:parlano:ma:info:visibilty\")) {\n\t\t\t\t\t\tif (sipe_strcase_equal(data, \"private\")) {\n\t\t\t\t\t\t\tflags |= SIPE_GROUPCHAT_ROOM_PRIVATE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tg_free(data);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* properties */\n\t\t\tfor (node = sipe_xml_child(chanib, \"prop\");\n\t\t\t     node;\n\t\t\t     node = sipe_xml_twin(node)) {\n\t\t\t\tconst gchar *id = sipe_xml_attribute(node, \"id\");\n\t\t\t\tgchar *data;\n\n\t\t\t\tif (!id) continue;\n\n\t\t\t\tdata = sipe_xml_data(node);\n\t\t\t\tif (data) {\n\t\t\t\t\tgboolean value = sipe_strcase_equal(data, \"true\");\n\t\t\t\t\tg_free(data);\n\n\t\t\t\t\tif (value) {\n\t\t\t\t\t\tguint32 add = 0;\n\t\t\t\t\t\tif        (sipe_strcase_equal(id, \"urn:parlano:ma:prop:filepost\")) {\n\t\t\t\t\t\t\tadd = SIPE_GROUPCHAT_ROOM_FILEPOST;\n\t\t\t\t\t\t} else if (sipe_strcase_equal(id, \"urn:parlano:ma:prop:invite\")) {\n\t\t\t\t\t\t\tadd = SIPE_GROUPCHAT_ROOM_INVITE;\n\t\t\t\t\t\t} else if (sipe_strcase_equal(id, \"urn:parlano:ma:prop:logged\")) {\n\t\t\t\t\t\t\tadd = SIPE_GROUPCHAT_ROOM_LOGGED;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tflags |= add;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tSIPE_DEBUG_INFO(\"group chat channel '%s': '%s' (%s) with %u users, flags 0x%x\",\n\t\t\t\t\tname, desc, uri, user_count, flags);\n\t\t\tsipe_backend_groupchat_room_add(sipe_public,\n\t\t\t\t\t\t\turi, name, desc,\n\t\t\t\t\t\t\tuser_count, flags);\n\t\t}\n\t}\n\n\tsipe_backend_groupchat_room_terminate(sipe_public);\n}\n\nstatic gboolean is_chanop(const sipe_xml *aib)\n{\n\treturn sipe_strequal(sipe_xml_attribute(aib, \"key\"),\n\t\t\t     GROUPCHAT_AIB_KEY_CHANOP);\n}\n\nstatic void add_user(struct sipe_chat_session *chat_session,\n\t\t     const gchar *uri,\n\t\t     gboolean new, gboolean chanop)\n{\n\tSIPE_DEBUG_INFO(\"add_user: %s%s%s to room %s (%s)\",\n\t\t\tnew ? \"new \" : \"\",\n\t\t\tchanop ? \"chanop \" : \"\",\n\t\t\turi,\n\t\t\tchat_session->title, chat_session->id);\n\tsipe_backend_chat_add(chat_session->backend, uri, new);\n\tif (chanop)\n\t\tsipe_backend_chat_operator(chat_session->backend, uri);\n}\n\nstatic void chatserver_response_join(struct sipe_core_private *sipe_private,\n\t\t\t\t     SIPE_UNUSED_PARAMETER struct sip_session *session,\n\t\t\t\t     guint result,\n\t\t\t\t     const gchar *message,\n\t\t\t\t     const sipe_xml *xml)\n{\n\tif (result != 200) {\n\t\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t  _(\"Error joining chat room\"),\n\t\t\t\t\t  message);\n\t} else {\n\t\tstruct sipe_groupchat *groupchat = sipe_private->groupchat;\n\t\tconst sipe_xml *node;\n\t\tGHashTable *user_ids = g_hash_table_new(g_str_hash, g_str_equal);\n\n\t\t/* Extract user IDs & URIs and generate ID -> URI map */\n\t\tfor (node = sipe_xml_child(xml, \"uib\");\n\t\t     node;\n\t\t     node = sipe_xml_twin(node)) {\n\t\t\tconst gchar *id  = sipe_xml_attribute(node, \"id\");\n\t\t\tconst gchar *uri = sipe_xml_attribute(node, \"uri\");\n\t\t\tif (id && uri)\n\t\t\t\tg_hash_table_insert(user_ids,\n\t\t\t\t\t\t    (gpointer) id,\n\t\t\t\t\t\t    (gpointer) uri);\n\t\t}\n\n\t\t/* Process channel data */\n\t\tfor (node = sipe_xml_child(xml, \"chanib\");\n\t\t     node;\n\t\t     node = sipe_xml_twin(node)) {\n\t\t\tconst gchar *uri = sipe_xml_attribute(node, \"uri\");\n\n\t\t\tif (uri) {\n\t\t\t\tstruct sipe_chat_session *chat_session = g_hash_table_lookup(groupchat->uri_to_chat_session,\n\t\t\t\t\t\t\t\t\t\t\t     uri);\n\t\t\t\tgboolean new = (chat_session == NULL);\n\t\t\t\tconst gchar *attr = sipe_xml_attribute(node, \"name\");\n\t\t\t\tgchar *self = sip_uri_self(sipe_private);\n\t\t\t\tconst sipe_xml *aib;\n\n\t\t\t\tif (new) {\n\t\t\t\t\tchat_session = sipe_chat_create_session(SIPE_CHAT_TYPE_GROUPCHAT,\n\t\t\t\t\t\t\t\t\t\tsipe_xml_attribute(node,\n\t\t\t\t\t\t\t\t\t\t\t\t   \"uri\"),\n\t\t\t\t\t\t\t\t\t\tattr ? attr : \"\");\n\t\t\t\t\tg_hash_table_insert(groupchat->uri_to_chat_session,\n\t\t\t\t\t\t\t    chat_session->id,\n\t\t\t\t\t\t\t    chat_session);\n\n\t\t\t\t\tSIPE_DEBUG_INFO(\"joined room '%s' (%s)\",\n\t\t\t\t\t\t\tchat_session->title,\n\t\t\t\t\t\t\tchat_session->id);\n\t\t\t\t\tchat_session->backend = sipe_backend_chat_create(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\t\t\t chat_session,\n\t\t\t\t\t\t\t\t\t\t\t chat_session->title,\n\t\t\t\t\t\t\t\t\t\t\t self);\n\t\t\t\t} else {\n\t\t\t\t\tSIPE_DEBUG_INFO(\"rejoining room '%s' (%s)\",\n\t\t\t\t\t\t\tchat_session->title,\n\t\t\t\t\t\t\tchat_session->id);\n\t\t\t\t\tsipe_backend_chat_rejoin(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t chat_session->backend,\n\t\t\t\t\t\t\t\t self,\n\t\t\t\t\t\t\t\t chat_session->title);\n\t\t\t\t}\n\t\t\t\tg_free(self);\n\n\t\t\t\tattr = sipe_xml_attribute(node, \"topic\");\n\t\t\t\tif (attr) {\n\t\t\t\t\tsipe_backend_chat_topic(chat_session->backend,\n\t\t\t\t\t\t\t\tattr);\n\t\t\t\t}\n\n\t\t\t\t/* Process user map for channel */\n\t\t\t\tfor (aib = sipe_xml_child(node, \"aib\");\n\t\t\t\t     aib;\n\t\t\t\t     aib = sipe_xml_twin(aib)) {\n\t\t\t\t\tconst gchar *value = sipe_xml_attribute(aib, \"value\");\n\t\t\t\t\tgboolean chanop = is_chanop(aib);\n\t\t\t\t\tgchar **ids = g_strsplit(value, \",\", 0);\n\n\t\t\t\t\tif (ids) {\n\t\t\t\t\t\tgchar **uid = ids;\n\n\t\t\t\t\t\twhile (*uid) {\n\t\t\t\t\t\t\tconst gchar *uri = g_hash_table_lookup(user_ids,\n\t\t\t\t\t\t\t\t\t\t\t       *uid);\n\t\t\t\t\t\t\tif (uri)\n\t\t\t\t\t\t\t\tadd_user(chat_session,\n\t\t\t\t\t\t\t\t\t uri,\n\t\t\t\t\t\t\t\t\t FALSE,\n\t\t\t\t\t\t\t\t\t chanop);\n\t\t\t\t\t\t\tuid++;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tg_strfreev(ids);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* Request last 25 entries from channel history */\n\t\t\t\tself = g_strdup_printf(\"<cmd id=\\\"cmd:bccontext\\\" seqid=\\\"1\\\">\"\n\t\t\t\t\t\t       \"<data>\"\n\t\t\t\t\t\t       \"<chanib uri=\\\"%s\\\"/>\"\n\t\t\t\t\t\t       \"<bcq><last cnt=\\\"25\\\"/></bcq>\"\n\t\t\t\t\t\t       \"</data>\"\n\t\t\t\t\t\t       \"</cmd>\", chat_session->id);\n\t\t\t\tchatserver_command(sipe_private, self);\n\t\t\t\tg_free(self);\n\t\t\t}\n\t\t}\n\n\t\tg_hash_table_destroy(user_ids);\n\t}\n}\n\nstatic void chatserver_grpchat_message(struct sipe_core_private *sipe_private,\n\t\t\t\t       const sipe_xml *grpchat);\n\nstatic void chatserver_response_history(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private,\n\t\t\t\t\tSIPE_UNUSED_PARAMETER struct sip_session *session,\n\t\t\t\t\tSIPE_UNUSED_PARAMETER guint result,\n\t\t\t\t\tSIPE_UNUSED_PARAMETER const gchar *message,\n\t\t\t\t\tconst sipe_xml *xml)\n{\n\tconst sipe_xml *grpchat;\n\n\tfor (grpchat = sipe_xml_child(xml, \"chanib/msg\");\n\t     grpchat;\n\t     grpchat = sipe_xml_twin(grpchat))\n\t\tif (sipe_strequal(sipe_xml_attribute(grpchat, \"id\"),\n\t\t\t\t  \"grpchat\"))\n\t\t\tchatserver_grpchat_message(sipe_private, grpchat);\n}\n\nstatic void chatserver_response_part(struct sipe_core_private *sipe_private,\n\t\t\t\t     SIPE_UNUSED_PARAMETER struct sip_session *session,\n\t\t\t\t     guint result,\n\t\t\t\t     const gchar *message,\n\t\t\t\t     const sipe_xml *xml)\n{\n\tif (result != 200) {\n\t\tSIPE_DEBUG_WARNING(\"chatserver_response_part: failed with %d: %s. Dropping room\",\n\t\t\t\t   result, message);\n\t} else {\n\t\tstruct sipe_groupchat *groupchat = sipe_private->groupchat;\n\t\tconst gchar *uri = sipe_xml_attribute(sipe_xml_child(xml, \"chanib\"),\n\t\t\t\t\t\t      \"uri\");\n\t\tstruct sipe_chat_session *chat_session;\n\n\t\tif (uri &&\n\t\t    (chat_session = g_hash_table_lookup(groupchat->uri_to_chat_session,\n\t\t\t\t\t\t\turi))) {\n\n\t\t\tSIPE_DEBUG_INFO(\"leaving room '%s' (%s)\",\n\t\t\t\t\tchat_session->title, chat_session->id);\n\n\t\t\tg_hash_table_remove(groupchat->uri_to_chat_session,\n\t\t\t\t\t    uri);\n\t\t\tsipe_chat_remove_session(chat_session);\n\n\t\t} else {\n\t\t\tSIPE_DEBUG_WARNING(\"chatserver_response_part: unknown chat room uri '%s'\",\n\t\t\t\t\t   uri ? uri : \"\");\n\t\t}\n\t}\n}\n\nstatic void chatserver_notice_join(struct sipe_core_private *sipe_private,\n\t\t\t\t   SIPE_UNUSED_PARAMETER struct sip_session *session,\n\t\t\t\t   SIPE_UNUSED_PARAMETER guint result,\n\t\t\t\t   SIPE_UNUSED_PARAMETER const gchar *message,\n\t\t\t\t   const sipe_xml *xml)\n{\n\tstruct sipe_groupchat *groupchat = sipe_private->groupchat;\n\tconst sipe_xml *uib;\n\n\tfor (uib = sipe_xml_child(xml, \"uib\");\n\t     uib;\n\t     uib = sipe_xml_twin(uib)) {\n\t\tconst gchar *uri = sipe_xml_attribute(uib, \"uri\");\n\n\t\tif (uri) {\n\t\t\tconst sipe_xml *aib;\n\n\t\t\tfor (aib = sipe_xml_child(uib, \"aib\");\n\t\t\t     aib;\n\t\t\t     aib = sipe_xml_twin(aib)) {\n\t\t\t\tconst gchar *domain = sipe_xml_attribute(aib, \"domain\");\n\t\t\t\tconst gchar *path   = sipe_xml_attribute(aib, \"value\");\n\n\t\t\t\tif (domain && path) {\n\t\t\t\t\tgchar *room_uri = g_strdup_printf(\"ma-chan://%s/%s\",\n\t\t\t\t\t\t\t\t\t  domain, path);\n\t\t\t\t\tstruct sipe_chat_session *chat_session = g_hash_table_lookup(groupchat->uri_to_chat_session,\n\t\t\t\t\t\t\t\t\t\t\t\t     room_uri);\n\t\t\t\t\tif (chat_session)\n\t\t\t\t\t\tadd_user(chat_session,\n\t\t\t\t\t\t\t uri,\n\t\t\t\t\t\t\t TRUE,\n\t\t\t\t\t\t\t is_chanop(aib));\n\n\t\t\t\t\tg_free(room_uri);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nstatic void chatserver_notice_part(struct sipe_core_private *sipe_private,\n\t\t\t\t   SIPE_UNUSED_PARAMETER struct sip_session *session,\n\t\t\t\t   SIPE_UNUSED_PARAMETER guint result,\n\t\t\t\t   SIPE_UNUSED_PARAMETER const gchar *message,\n\t\t\t\t   const sipe_xml *xml)\n{\n\tstruct sipe_groupchat *groupchat = sipe_private->groupchat;\n\tconst sipe_xml *chanib;\n\n\tfor (chanib = sipe_xml_child(xml, \"chanib\");\n\t     chanib;\n\t     chanib = sipe_xml_twin(chanib)) {\n\t\tconst gchar *room_uri = sipe_xml_attribute(chanib, \"uri\");\n\n\t\tif (room_uri) {\n\t\t\tstruct sipe_chat_session *chat_session = g_hash_table_lookup(groupchat->uri_to_chat_session,\n\t\t\t\t\t\t\t\t\t\t     room_uri);\n\n\t\t\tif (chat_session) {\n\t\t\t\tconst sipe_xml *uib;\n\n\t\t\t\tfor (uib = sipe_xml_child(chanib, \"uib\");\n\t\t\t\t     uib;\n\t\t\t\t     uib = sipe_xml_twin(uib)) {\n\t\t\t\t\tconst gchar *uri = sipe_xml_attribute(uib, \"uri\");\n\n\t\t\t\t\tif (uri) {\n\t\t\t\t\t\tSIPE_DEBUG_INFO(\"remove_user: %s from room %s (%s)\",\n\t\t\t\t\t\t\t\turi,\n\t\t\t\t\t\t\t\tchat_session->title,\n\t\t\t\t\t\t\t\tchat_session->id);\n\t\t\t\t\t\tsipe_backend_chat_remove(chat_session->backend,\n\t\t\t\t\t\t\t\t\t uri);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nstatic const struct response {\n\tconst gchar *key;\n\tvoid (* const handler)(struct sipe_core_private *,\n\t\t\t       struct sip_session *,\n\t\t\t       guint result, const gchar *,\n\t\t\t       const sipe_xml *xml);\n} response_table[] = {\n\t{ \"rpl:requri\",    chatserver_response_uri },\n\t{ \"rpl:chansrch\",  chatserver_response_channel_search },\n\t{ \"rpl:join\",      chatserver_response_join },\n\t{ \"rpl:bjoin\",     chatserver_response_join },\n\t{ \"rpl:bccontext\", chatserver_response_history },\n\t{ \"rpl:part\",      chatserver_response_part },\n\t{ \"ntc:join\",      chatserver_notice_join },\n\t{ \"ntc:bjoin\",     chatserver_notice_join },\n\t{ \"ntc:part\",      chatserver_notice_part },\n\t{ NULL, NULL }\n};\n\n/* Handles rpl:XXX & ntc:YYY */\nstatic void chatserver_response(struct sipe_core_private *sipe_private,\n\t\t\t\tconst sipe_xml *reply,\n\t\t\t\tstruct sip_session *session)\n{\n\tdo {\n\t\tconst sipe_xml *resp, *data;\n\t\tconst gchar *id;\n\t\tgchar *message;\n\t\tguint result = 500;\n\t\tconst struct response *r;\n\n\t\tid = sipe_xml_attribute(reply, \"id\");\n\t\tif (!id) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"chatserver_response: no reply ID found!\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tresp = sipe_xml_child(reply, \"resp\");\n\t\tif (resp) {\n\t\t\tresult = sipe_xml_int_attribute(resp, \"code\", 500);\n\t\t\tmessage = sipe_xml_data(resp);\n\t\t} else {\n\t\t\tmessage = g_strdup(\"\");\n\t\t}\n\n\t\tdata = sipe_xml_child(reply, \"data\");\n\n\t\tSIPE_DEBUG_INFO(\"chatserver_response: '%s' result (%d) %s\",\n\t\t\t\tid, result, message ? message : \"\");\n\n\t\tfor (r = response_table; r->key; r++) {\n\t\t\tif (sipe_strcase_equal(id, r->key)) {\n\t\t\t\t(*r->handler)(sipe_private, session, result, message, data);\n\t\t\t\t/* session can be invalid now */\n\t\t\t\tsession = NULL;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!r->key) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"chatserver_response: ignoring unknown response\");\n\t\t}\n\n\t\tg_free(message);\n\t} while ((reply = sipe_xml_twin(reply)) != NULL);\n}\n\nstatic void chatserver_grpchat_message(struct sipe_core_private *sipe_private,\n\t\t\t\t       const sipe_xml *grpchat)\n{\n\tstruct sipe_groupchat *groupchat = sipe_private->groupchat;\n\tconst gchar *uri = sipe_xml_attribute(grpchat, \"chanUri\");\n\tconst gchar *from = sipe_xml_attribute(grpchat, \"author\");\n\ttime_t when = sipe_utils_str_to_time(sipe_xml_attribute(grpchat, \"ts\"));\n\tgchar *text = sipe_xml_data(sipe_xml_child(grpchat, \"chat\"));\n\tstruct sipe_chat_session *chat_session;\n\tgchar *escaped;\n\n\tif (!uri || !from) {\n\t\tSIPE_DEBUG_INFO(\"chatserver_grpchat_message: message '%s' received without chat room URI or author!\",\n\t\t\t\ttext ? text : \"\");\n\t\tg_free(text);\n\t\treturn;\n\t}\n\n\tchat_session = g_hash_table_lookup(groupchat->uri_to_chat_session,\n\t\t\t\t\t   uri);\n\tif (!chat_session) {\n\t\tSIPE_DEBUG_INFO(\"chatserver_grpchat_message: message '%s' from '%s' received from unknown chat room '%s'!\",\n\t\t\t\ttext ? text : \"\", from, uri);\n\t\tg_free(text);\n\t\treturn;\n\t}\n\n\t/* libxml2 decodes all entities, but the backend expects HTML */\n\tescaped = g_markup_escape_text(text, -1);\n\tg_free(text);\n\tsipe_backend_chat_message(SIPE_CORE_PUBLIC, chat_session->backend,\n\t\t\t\t  from, when, escaped);\n\tg_free(escaped);\n}\n\nvoid process_incoming_info_groupchat(struct sipe_core_private *sipe_private,\n\t\t\t\t     struct sipmsg *msg,\n\t\t\t\t     struct sip_session *session)\n{\n\tsipe_xml *xml = sipe_xml_parse(msg->body, msg->bodylen);\n\tconst sipe_xml *node;\n\tconst gchar *callid;\n\tstruct sip_dialog *dialog;\n\n\tcallid = sipmsg_find_call_id_header(msg);\n\tdialog = sipe_dialog_find(session, session->with);\n\tif (sipe_strequal(callid, dialog->callid)) {\n\n\t\tsip_transport_response(sipe_private, msg, 200, \"OK\", NULL);\n\n\t\tif        (((node = sipe_xml_child(xml, \"rpl\")) != NULL) ||\n\t\t\t   ((node = sipe_xml_child(xml, \"ntc\")) != NULL)) {\n\t\t\tchatserver_response(sipe_private, node, session);\n\t\t} else if ((node = sipe_xml_child(xml, \"grpchat\")) != NULL) {\n\t\t\tchatserver_grpchat_message(sipe_private, node);\n\t\t} else {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_incoming_info_groupchat: ignoring unknown response\");\n\t\t}\n\n\t} else {\n\t\t/*\n\t\t * Our last session got disconnected without proper shutdown,\n\t\t * e.g. by Pidgin crashing or network connection loss. When\n\t\t * we reconnect to the group chat the server will send INFO\n\t\t * messages to the current *AND* the obsolete Call-ID, until\n\t\t * the obsolete session expires.\n\t\t *\n\t\t * Ignore these INFO messages to avoid, e.g. duplicate texts,\n\t\t * and respond with an error so that the server knows that we\n\t\t * consider this dialog to be terminated.\n\t\t */\n\t\tSIPE_DEBUG_INFO(\"process_incoming_info_groupchat: ignoring unsolicited INFO message to obsolete Call-ID: %s\",\n\t\t\t\tcallid);\n\n\t\tsip_transport_response(sipe_private, msg, 487, \"Request Terminated\", NULL);\n\t}\n\n\tsipe_xml_free(xml);\n}\n\nvoid sipe_groupchat_send(struct sipe_core_private *sipe_private,\n\t\t\t struct sipe_chat_session *chat_session,\n\t\t\t const gchar *what)\n{\n\tstruct sipe_groupchat *groupchat = sipe_private->groupchat;\n\tgchar *cmd, *self, *timestamp, *tmp;\n\tgchar **lines, **strvp;\n\tstruct sipe_groupchat_msg *msg;\n\n\tif (!groupchat || !chat_session)\n\t\treturn;\n\n\tSIPE_DEBUG_INFO(\"sipe_groupchat_send: '%s' to %s\",\n\t\t\twhat, chat_session->id);\n\n\tself = sip_uri_self(sipe_private);\n\ttimestamp = sipe_utils_time_to_str(time(NULL));\n\n\t/**\n\t * 'what' is already XML-escaped, e.g.\n\t *\n\t *    \" -> &quot;\n\t *    > -> &gt;\n\t *    < -> &lt;\n\t *    & -> &amp;\n\t *\n\t * Group Chat only accepts plain text, not full HTML. So we have to\n\t * strip all HTML tags and XML escape the text.\n\t *\n\t * Line breaks are encoded as <br> and therefore need to be replaced\n\t * before stripping. In order to prevent HTML stripping to strip line\n\t * endings, we need to split the text into lines on <br>.\n\t */\n\tlines = g_strsplit(what, \"<br>\", 0);\n\tfor (strvp = lines; *strvp; strvp++) {\n\t\t/* replace array entry with HTML stripped & XML escaped version */\n\t\tgchar *stripped = sipe_backend_markup_strip_html(*strvp);\n\t\tgchar *escaped  = g_markup_escape_text(stripped, -1);\n\t\tg_free(stripped);\n\t\tg_free(*strvp);\n\t\t*strvp = escaped;\n\t}\n\ttmp = g_strjoinv(\"\\r\\n\", lines);\n\tg_strfreev(lines);\n\tcmd = g_strdup_printf(\"<grpchat id=\\\"grpchat\\\" seqid=\\\"1\\\" chanUri=\\\"%s\\\" author=\\\"%s\\\" ts=\\\"%s\\\">\"\n\t\t\t      \"<chat>%s</chat>\"\n\t\t\t      \"</grpchat>\",\n\t\t\t      chat_session->id, self, timestamp, tmp);\n\tg_free(tmp);\n\tg_free(timestamp);\n\tg_free(self);\n\tmsg = chatserver_command(sipe_private, cmd);\n\tg_free(cmd);\n\n\tif (msg) {\n\t\tmsg->session = chat_session;\n\t\tmsg->content = g_strdup(what);\n\t} else {\n\t\tchatserver_command_error_notify(sipe_private,\n\t\t\t\t\t\tchat_session,\n\t\t\t\t\t\twhat);\n\t}\n}\n\nvoid sipe_groupchat_leave(struct sipe_core_private *sipe_private,\n\t\t\t  struct sipe_chat_session *chat_session)\n{\n\tstruct sipe_groupchat *groupchat = sipe_private->groupchat;\n\tgchar *cmd;\n\n\tif (!groupchat || !chat_session)\n\t\treturn;\n\n\tSIPE_DEBUG_INFO(\"sipe_groupchat_leave: %s\", chat_session->id);\n\n\tcmd = g_strdup_printf(\"<cmd id=\\\"cmd:part\\\" seqid=\\\"1\\\">\"\n\t\t\t      \"<data>\"\n\t\t\t      \"<chanib uri=\\\"%s\\\"/>\"\n\t\t\t      \"</data>\"\n\t\t\t      \"</cmd>\", chat_session->id);\n\tchatserver_command(sipe_private, cmd);\n\tg_free(cmd);\n}\n\ngboolean sipe_core_groupchat_query_rooms(struct sipe_core_public *sipe_public)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tstruct sipe_groupchat *groupchat = sipe_private->groupchat;\n\n\tif (!groupchat || !groupchat->connected)\n\t\treturn FALSE;\n\n\tchatserver_command(sipe_private,\n\t\t\t   \"<cmd id=\\\"cmd:chansrch\\\" seqid=\\\"1\\\">\"\n\t\t\t   \"<data>\"\n\t\t\t   \"<qib qtype=\\\"BYNAME\\\" criteria=\\\"\\\" extended=\\\"false\\\"/>\"\n\t\t\t   \"</data>\"\n\t\t\t   \"</cmd>\");\n\n\treturn TRUE;\n}\n\nvoid sipe_core_groupchat_join(struct sipe_core_public *sipe_public,\n\t\t\t      const gchar *uri)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tstruct sipe_groupchat *groupchat = sipe_private->groupchat;\n\n\tif (!g_str_has_prefix(uri, \"ma-chan://\"))\n\t\treturn;\n\n\tif (!groupchat) {\n\t\t/* This happens when a user has set auto-join on a channel */\n\t\tsipe_groupchat_allocate(sipe_private);\n\t\tgroupchat = sipe_private->groupchat;\n\t}\n\n\tif (groupchat->connected) {\n\t\tstruct sipe_chat_session *chat_session = g_hash_table_lookup(groupchat->uri_to_chat_session,\n\t\t\t\t\t\t\t\t\t     uri);\n\n\t\t/* Already joined? */\n\t\tif (chat_session) {\n\n\t\t\t/* Yes, update backend session */\n\t\t\tSIPE_DEBUG_INFO(\"sipe_core_groupchat_join: show '%s' (%s)\",\n\t\t\t\t\tchat_session->title,\n\t\t\t\t\tchat_session->id);\n\t\t\tsipe_backend_chat_show(chat_session->backend);\n\n\t\t} else {\n\t\t\t/* No, send command out directly */\n\t\t\tgchar *chanid = generate_chanid_node(uri, 0);\n\t\t\tif (chanid) {\n\t\t\t\tgchar *cmd = g_strdup_printf(\"<cmd id=\\\"cmd:join\\\" seqid=\\\"1\\\">\"\n\t\t\t\t\t\t\t     \"<data>%s</data>\"\n\t\t\t\t\t\t\t     \"</cmd>\",\n\t\t\t\t\t\t\t     chanid);\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_core_groupchat_join: join %s\",\n\t\t\t\t\t\turi);\n\t\t\t\tchatserver_command(sipe_private, cmd);\n\t\t\t\tg_free(cmd);\n\t\t\t\tg_free(chanid);\n\t\t\t}\n\t\t}\n\t} else {\n\t\t/* Add it to the queue but avoid duplicates */\n\t\tif (!g_slist_find_custom(groupchat->join_queue, uri,\n\t\t\t\t\t (GCompareFunc)g_strcmp0)) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_core_groupchat_join: URI queued\");\n\t\t\tgroupchat->join_queue = g_slist_prepend(groupchat->join_queue,\n\t\t\t\t\t\t\t\tg_strdup(uri));\n\t\t}\n\t}\n}\n\nvoid sipe_groupchat_rejoin(struct sipe_core_private *sipe_private,\n\t\t\t   struct sipe_chat_session *chat_session)\n{\n\tstruct sipe_groupchat *groupchat = sipe_private->groupchat;\n\n\tif (!groupchat) {\n\t\t/* First rejoined channel after reconnect will trigger this */\n\t\tsipe_groupchat_allocate(sipe_private);\n\t\tgroupchat = sipe_private->groupchat;\n\t}\n\n\t/* Remember \"old\" session, so that we don't recreate it at join */\n\tg_hash_table_insert(groupchat->uri_to_chat_session,\n\t\t\t    chat_session->id,\n\t\t\t    chat_session);\n\tsipe_core_groupchat_join(SIPE_CORE_PUBLIC, chat_session->id);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-groupchat.h",
    "content": " /**\n * @file sipe-groupchat.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2013 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipmsg;\nstruct sip_dialog;\nstruct sip_session;\nstruct sipe_chat_session;\nstruct sipe_core_private;\n\nvoid sipe_groupchat_free(struct sipe_core_private *sipe_private);\nvoid sipe_groupchat_init(struct sipe_core_private *sipe_private);\nvoid sipe_groupchat_invite_failed(struct sipe_core_private *sipe_private,\n\t\t\t\t  struct sip_session *session);\nvoid sipe_groupchat_invite_response(struct sipe_core_private *sipe_private,\n\t\t\t\t    struct sip_dialog *dialog,\n\t\t\t\t    struct sipmsg *response);\nvoid process_incoming_info_groupchat(struct sipe_core_private *sipe_private,\n\t\t\t\t     struct sipmsg *msg,\n\t\t\t\t     struct sip_session *session);\nvoid sipe_groupchat_send(struct sipe_core_private *sipe_private,\n\t\t\t struct sipe_chat_session *chat_session,\n\t\t\t const gchar *what);\nvoid sipe_groupchat_leave(struct sipe_core_private *sipe_private,\n\t\t\t  struct sipe_chat_session *chat_session);\nvoid sipe_groupchat_rejoin(struct sipe_core_private *sipe_private,\n\t\t\t   struct sipe_chat_session *chat_session);\n"
  },
  {
    "path": "src/core/sipe-http-request.c",
    "content": "/**\n * @file sipe-http-request.c\n*\n * pidgin-sipe\n *\n * Copyright (C) 2013-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * SIPE HTTP request layer implementation\n *\n *  - request handling: creation, parameters, deletion, cancelling\n *  - session handling: creation, closing\n *  - client authorization handling\n *  - connection request queue handling\n *  - compile HTTP header contents and hand-off to transport layer\n *  - process HTTP response and hand-off to user callback\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipmsg.h\"\n#include \"sip-sec.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-http.h\"\n\n#define _SIPE_HTTP_PRIVATE_IF_REQUEST\n#include \"sipe-http-request.h\"\n#define _SIPE_HTTP_PRIVATE_IF_TRANSPORT\n#include \"sipe-http-transport.h\"\n\nstruct sipe_http_session {\n\tGHashTable *cookie_jar;\n};\n\nstruct sipe_http_request {\n\tstruct sipe_http_connection_public *connection;\n\n\tstruct sipe_http_session *session;\n\n\tgchar *path;\n\tgchar *headers;\n\tgchar *body;           /* NULL for GET */\n\tgchar *content_type;   /* NULL if body == NULL */\n\tgchar *authorization;\n\n\tconst gchar *user;     /* not copied */\n\tconst gchar *password; /* not copied */\n\n\tsipe_http_response_callback *cb;\n\tgpointer cb_data;\n\n\tguint32 flags;\n};\n\n#define SIPE_HTTP_REQUEST_FLAG_FIRST     0x00000001\n#define SIPE_HTTP_REQUEST_FLAG_REDIRECT  0x00000002\n#define SIPE_HTTP_REQUEST_FLAG_AUTHDATA  0x00000004\n#define SIPE_HTTP_REQUEST_FLAG_HANDSHAKE 0x00000008\n\nstatic void sipe_http_request_free(struct sipe_core_private *sipe_private,\n\t\t\t\t   struct sipe_http_request *req,\n\t\t\t\t   guint status)\n{\n\tif (req->cb)\n\t\t/* Callback: aborted/failed/cancelled */\n\t\t(*req->cb)(sipe_private,\n\t\t\t   status,\n\t\t\t   NULL,\n\t\t\t   NULL,\n\t\t\t   req->cb_data);\n\tg_free(req->path);\n\tg_free(req->headers);\n\tg_free(req->body);\n\tg_free(req->content_type);\n\tg_free(req->authorization);\n\tg_free(req);\n}\n\nstatic void add_cookie_cb(SIPE_UNUSED_PARAMETER const gchar *key,\n\t\t\t  const gchar *cookie,\n\t\t\t  GString *string)\n{\n\tg_string_append_printf(string, \"Cookie: %s\\r\\n\", cookie);\n}\n\nstatic void sipe_http_request_send(struct sipe_http_connection_public *conn_public)\n{\n\tstruct sipe_http_request *req = conn_public->pending_requests->data;\n\tgchar *header;\n\tgchar *content = NULL;\n\tgchar *cookie  = NULL;\n\n\tif (req->body)\n\t\tcontent = g_strdup_printf(\"Content-Length: %\" G_GSIZE_FORMAT \"\\r\\n\"\n\t\t\t\t\t  \"Content-Type: %s\\r\\n\",\n\t\t\t\t\t  strlen(req->body),\n\t\t\t\t\t  req->content_type);\n\n\tif (req->session && g_hash_table_size(req->session->cookie_jar)) {\n\t\tGString *cookies = g_string_new(\"\");\n\t\tg_hash_table_foreach(req->session->cookie_jar,\n\t\t\t\t     (GHFunc) add_cookie_cb,\n\t\t\t\t     cookies);\n\t\tcookie = g_string_free(cookies, FALSE);\n\t}\n\n\theader = g_strdup_printf(\"%s /%s HTTP/1.1\\r\\n\"\n\t\t\t\t \"Host: %s\\r\\n\"\n\t\t\t\t \"User-Agent: %s\\r\\n\"\n\t\t\t\t \"%s%s%s%s\",\n\t\t\t\t content ? \"POST\" : \"GET\",\n\t\t\t\t req->path,\n\t\t\t\t conn_public->host,\n\t\t\t\t sipe_core_user_agent(conn_public->sipe_private),\n\t\t\t\t conn_public->cached_authorization ? conn_public->cached_authorization :\n\t\t\t\t req->authorization ? req->authorization : \"\",\n\t\t\t\t req->headers ? req->headers : \"\",\n\t\t\t\t cookie ? cookie : \"\",\n\t\t\t\t content ? content : \"\");\n\tg_free(cookie);\n\tg_free(content);\n\n\t/* only use authorization once */\n\tg_free(req->authorization);\n\treq->authorization = NULL;\n\n\tsipe_http_transport_send(conn_public,\n\t\t\t\t header,\n\t\t\t\t req->body);\n\tg_free(header);\n}\n\ngboolean sipe_http_request_pending(struct sipe_http_connection_public *conn_public)\n{\n\treturn(conn_public->pending_requests != NULL);\n}\n\nvoid sipe_http_request_next(struct sipe_http_connection_public *conn_public)\n{\n\tsipe_http_request_send(conn_public);\n}\n\nstatic void sipe_http_request_enqueue(struct sipe_core_private *sipe_private,\n\t\t\t\t      struct sipe_http_request *req,\n\t\t\t\t      const struct sipe_http_parsed_uri *parsed_uri)\n{\n\tstruct sipe_http_connection_public *conn_public;\n\n\treq->path       = g_strdup(parsed_uri->path);\n\treq->connection = conn_public = sipe_http_transport_new(sipe_private,\n\t\t\t\t\t\t\t\tparsed_uri->host,\n\t\t\t\t\t\t\t\tparsed_uri->port,\n\t\t\t\t\t\t\t\tparsed_uri->tls);\n\tif (!sipe_http_request_pending(conn_public))\n\t\treq->flags |= SIPE_HTTP_REQUEST_FLAG_FIRST;\n\n\tconn_public->pending_requests = g_slist_append(conn_public->pending_requests,\n\t\t\t\t\t\t       req);\n}\n\nstatic void sipe_http_request_drop_context(struct sipe_http_connection_public *conn_public)\n{\n\tg_free(conn_public->cached_authorization);\n\tconn_public->cached_authorization = NULL;\n\tsip_sec_destroy_context(conn_public->context);\n\tconn_public->context = NULL;\n}\n\nstatic void sipe_http_request_finalize_negotiate(struct sipe_http_request *req,\n\t\t\t\t\t\t struct sipmsg *msg)\n{\n#if defined(HAVE_GSSAPI_GSSAPI_H) || defined(HAVE_SSPI)\n\t/*\n\t * Negotiate can send a final package in the successful response.\n\t * We need to forward this to the context or otherwise it will\n\t * never reach the ready state.\n\t */\n\tstruct sipe_http_connection_public *conn_public = req->connection;\n\n\tif (sip_sec_context_type(conn_public->context) == SIPE_AUTHENTICATION_TYPE_NEGOTIATE) {\n\t\tconst gchar *header = sipmsg_find_auth_header(msg, \"Negotiate\");\n\n\t\tif (header) {\n\t\t\tgchar **parts = g_strsplit(header, \" \", 0);\n\t\t\tgchar *spn    = g_strdup_printf(\"HTTP/%s\", conn_public->host);\n\t\t\tgchar *token;\n\n\t\t\tSIPE_DEBUG_INFO(\"sipe_http_request_finalize_negotiate: init context target '%s' token '%s'\",\n\t\t\t\t\tspn, parts[1] ? parts[1] : \"<NULL>\");\n\n\t\t\tif (sip_sec_init_context_step(conn_public->context,\n\t\t\t\t\t\t      spn,\n\t\t\t\t\t\t      parts[1],\n\t\t\t\t\t\t      &token,\n\t\t\t\t\t\t      NULL)) {\n\t\t\t\tg_free(token);\n\t\t\t} else {\n\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_http_request_finalize_negotiate: security context init step failed, throwing away context\");\n\t\t\t\tsipe_http_request_drop_context(conn_public);\n\t\t\t}\n\n\t\t\tg_free(spn);\n\t\t\tg_strfreev(parts);\n\t\t}\n\t}\n#else\n\t(void) req; /* keep compiler happy */\n\t(void) msg; /* keep compiler happy */\n#endif\n}\n\n\n/* TRUE indicates failure */\nstatic gboolean sipe_http_request_response_redirection(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t       struct sipe_http_request *req,\n\t\t\t\t\t\t       struct sipmsg *msg)\n{\n\tconst gchar *location = sipmsg_find_header(msg, \"Location\");\n\tgboolean failed = TRUE;\n\n\tsipe_http_request_finalize_negotiate(req, msg);\n\n\tif (location) {\n\t\tstruct sipe_http_parsed_uri *parsed_uri = sipe_http_parse_uri(location);\n\n\t\tif (parsed_uri) {\n\t\t\t/* remove request from old connection */\n\t\t\tstruct sipe_http_connection_public *conn_public = req->connection;\n\t\t\tconn_public->pending_requests = g_slist_remove(conn_public->pending_requests,\n\t\t\t\t\t\t\t\t       req);\n\n\t\t\t/* free old request data */\n\t\t\tg_free(req->path);\n\t\t\treq->flags &= ~( SIPE_HTTP_REQUEST_FLAG_FIRST |\n\t\t\t\t\t SIPE_HTTP_REQUEST_FLAG_HANDSHAKE );\n\n\t\t\t/* resubmit request on other connection */\n\t\t\tsipe_http_request_enqueue(sipe_private, req, parsed_uri);\n\t\t\tfailed = FALSE;\n\n\t\t\tsipe_http_parsed_uri_free(parsed_uri);\n\t\t} else\n\t\t\tSIPE_DEBUG_INFO(\"sipe_http_request_response_redirection: invalid redirection to '%s'\",\n\t\t\t\t\tlocation);\n\t} else\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_http_request_response_redirection: no URL found?!?\");\n\n\treturn(failed);\n}\n\n/* TRUE indicates failure */\nstatic gboolean sipe_http_request_response_unauthorized(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t\tstruct sipe_http_request *req,\n\t\t\t\t\t\t\tstruct sipmsg *msg)\n{\n\tstruct sipe_http_connection_public *conn_public = req->connection;\n\tconst gchar *header = NULL;\n\tguint type;\n\tgboolean failed = TRUE;\n\n\t/*\n\t * There are some buggy HTTP servers out there that add superfluous\n\t * WWW-Authenticate: headers during the authentication handshake.\n\t * Look only for the header of the active security context.\n\t */\n\tif (conn_public->context) {\n\t\tconst gchar *name = sip_sec_context_name(conn_public->context);\n\n\t\theader = sipmsg_find_auth_header(msg, name);\n\t\ttype   = sip_sec_context_type(conn_public->context);\n\n\t\tif (!header) {\n\t\t\tSIPE_DEBUG_INFO(\"sipe_http_request_response_unauthorized: expected authentication scheme %s not found\",\n\t\t\t\t\tname);\n\t\t\treturn(failed);\n\t\t}\n\n\t\tif (conn_public->cached_authorization) {\n\t\t\t/*\n\t\t\t * The \"Basic\" scheme doesn't have any state.\n\t\t\t *\n\t\t\t * If we enter here then we have already tried \"Basic\"\n\t\t\t * authentication once for this request and it was\n\t\t\t * rejected by the server. As all future requests will\n\t\t\t * also be rejected, we need to abort here in order to\n\t\t\t * prevent an endless request/401/request/... loop.\n\t\t\t */\n\t\t\tSIPE_DEBUG_INFO(\"sipe_http_request_response_unauthorized: Basic authentication has failed for host '%s', please check user name and password!\",\n\t\t\t\t\tconn_public->host);\n\t\t\treturn(failed);\n\t\t}\n\n\t} else {\n#if defined(HAVE_GSSAPI_GSSAPI_H) || defined(HAVE_SSPI)\n#define DEBUG_STRING \", NTLM and Negotiate\"\n\t\t/* Use \"Negotiate\" unless the user requested \"NTLM\" */\n\t\tif (sipe_private->authentication_type != SIPE_AUTHENTICATION_TYPE_NTLM)\n\t\t\theader = sipmsg_find_auth_header(msg, \"Negotiate\");\n\t\tif (header) {\n\t\t\ttype   = SIPE_AUTHENTICATION_TYPE_NEGOTIATE;\n\t\t} else\n#else\n#define DEBUG_STRING \" and NTLM\"\n\t\t(void) sipe_private; /* keep compiler happy */\n#endif\n\t\t{\n\t\t\theader = sipmsg_find_auth_header(msg, \"NTLM\");\n\t\t\ttype   = SIPE_AUTHENTICATION_TYPE_NTLM;\n\t\t}\n\n\t\t/* only fall back to \"Basic\" after everything else fails */\n\t\tif (!header) {\n\t\t\theader = sipmsg_find_auth_header(msg, \"Basic\");\n\t\t\ttype   = SIPE_AUTHENTICATION_TYPE_BASIC;\n\t\t}\n\t}\n\n\tif (header) {\n\t\tif (!conn_public->context) {\n\t\t\tgboolean valid = req->flags & SIPE_HTTP_REQUEST_FLAG_AUTHDATA;\n\t\t\tconn_public->context = sip_sec_create_context(type,\n\t\t\t\t\t\t\t\t      !valid, /* Single Sign-On flag */\n\t\t\t\t\t\t\t\t      TRUE,   /* connection-based for HTTP */\n\t\t\t\t\t\t\t\t      valid ? req->user     : NULL,\n\t\t\t\t\t\t\t\t      valid ? req->password : NULL);\n\t\t}\n\n\t\tif (conn_public->context) {\n\t\t\tgchar **parts = g_strsplit(header, \" \", 0);\n\t\t\tgchar *spn    = g_strdup_printf(\"HTTP/%s\", conn_public->host);\n\t\t\tgchar *token_out;\n\t\t\tconst gchar *token_in = parts[1];\n\n\t\t\tSIPE_DEBUG_INFO(\"sipe_http_request_response_unauthorized: init context target '%s' token '%s'\",\n\t\t\t\t\tspn, token_in ? token_in : \"<NULL>\");\n\n\t\t\t/*\n\t\t\t * If we receive a NULL token during the handshake\n\t\t\t * then the authentication scheme has failed.\n\t\t\t */\n\t\t\tif ((req->flags & SIPE_HTTP_REQUEST_FLAG_HANDSHAKE) &&\n\t\t\t    !token_in) {\n\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_http_request_response_unauthorized: authentication failed, throwing away context\");\n\t\t\t\tsipe_http_request_drop_context(conn_public);\n\n\t\t\t} else if (sip_sec_init_context_step(conn_public->context,\n\t\t\t\t\t\t      spn,\n\t\t\t\t\t\t      token_in,\n\t\t\t\t\t\t      &token_out,\n\t\t\t\t\t\t      NULL)) {\n\n\t\t\t\t/* handshake has started */\n\t\t\t\treq->flags |= SIPE_HTTP_REQUEST_FLAG_HANDSHAKE;\n\n\t\t\t\t/* generate authorization header */\n\t\t\t\treq->authorization = g_strdup_printf(\"Authorization: %s %s\\r\\n\",\n\t\t\t\t\t\t\t\t     sip_sec_context_name(conn_public->context),\n\t\t\t\t\t\t\t\t     token_out ? token_out : \"\");\n\t\t\t\tg_free(token_out);\n\n\t\t\t\t/*\n\t\t\t\t * authorization never changes for Basic\n\t\t\t\t * authentication scheme, so we can keep it.\n\t\t\t\t */\n\t\t\t\tif (type == SIPE_AUTHENTICATION_TYPE_BASIC) {\n\t\t\t\t\tg_free(conn_public->cached_authorization);\n\t\t\t\t\tconn_public->cached_authorization = g_strdup(req->authorization);\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t * Keep the request in the queue. As it is at\n\t\t\t\t * the head it will be pulled automatically\n\t\t\t\t * by the transport layer after returning.\n\t\t\t\t */\n\t\t\t\tfailed = FALSE;\n\n\t\t\t} else {\n\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_http_request_response_unauthorized: security context init step failed, throwing away context\");\n\t\t\t\tsipe_http_request_drop_context(conn_public);\n\t\t\t}\n\n\t\t\tg_free(spn);\n\t\t\tg_strfreev(parts);\n\t\t} else\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_http_request_response_unauthorized: security context creation failed\");\n\t} else\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_http_request_response_unauthorized: only Basic\" DEBUG_STRING \" authentication schemes are supported\");\n\n\treturn(failed);\n}\n\nstatic void sipe_http_request_response_callback(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\tstruct sipe_http_request *req,\n\t\t\t\t\t\tstruct sipmsg *msg)\n{\n\tsipe_http_request_finalize_negotiate(req, msg);\n\n\t/* Set-Cookie: RMID=732423sdfs73242; expires=Fri, 31-Dec-2010 23:59:59 GMT; path=/; domain=.example.net */\n\tif (req->session) {\n\t\tguint instance = 0;\n\t\tconst gchar *hdr;\n\n\t\t/* extract all cookies from header */\n\t\twhile ((hdr = sipmsg_find_header_instance(msg,\n\t\t\t\t\t\t\t  \"Set-Cookie\",\n\t\t\t\t\t\t\t  instance++)) != NULL) {\n\t\t\tgchar **parts, **current;\n\t\t\tconst gchar *part;\n\t\t\tgchar *new = NULL;\n\n\t\t\tcurrent = parts = g_strsplit(hdr, \";\", 0);\n\t\t\twhile ((part = *current++) != NULL) {\n\t\t\t\t/* strip these parts from cookie */\n\t\t\t\tif (!(strstr(part, \"path=\")    ||\n\t\t\t\t      strstr(part, \"domain=\")  ||\n\t\t\t\t      strstr(part, \"expires=\") ||\n\t\t\t\t      strstr(part, \"secure\"))) {\n\t\t\t\t\tgchar *tmp = new;\n\t\t\t\t\tnew = new ?\n\t\t\t\t\t\tg_strconcat(new, \";\", part, NULL) :\n\t\t\t\t\t\tg_strdup(part);\n\t\t\t\t\tg_free(tmp);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (new) {\n\t\t\t\tg_hash_table_insert(req->session->cookie_jar,\n\t\t\t\t\t\t    g_strdup(*parts),\n\t\t\t\t\t\t    new);\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_http_request_response_callback: cookie: %s\", new);\n\t\t\t}\n\t\t\tg_strfreev(parts);\n\t\t}\n\t}\n\n\t/* Callback: success */\n\t(*req->cb)(sipe_private,\n\t\t   msg->response,\n\t\t   msg->headers,\n\t\t   msg->body,\n\t\t   req->cb_data);\n\n\t/* remove completed request */\n\tsipe_http_request_cancel(req);\n}\n\nvoid sipe_http_request_response(struct sipe_http_connection_public *conn_public,\n\t\t\t\tstruct sipmsg *msg)\n{\n\tstruct sipe_core_private *sipe_private = conn_public->sipe_private;\n\tstruct sipe_http_request *req = conn_public->pending_requests->data;\n\tgboolean failed;\n\n\tif ((req->flags & SIPE_HTTP_REQUEST_FLAG_REDIRECT)   &&\n\t    (msg->response >= SIPE_HTTP_STATUS_REDIRECTION)  &&\n\t    (msg->response <  SIPE_HTTP_STATUS_CLIENT_ERROR)) {\n\t\tfailed = sipe_http_request_response_redirection(sipe_private,\n\t\t\t\t\t\t\t\treq,\n\t\t\t\t\t\t\t\tmsg);\n\n\t} else if (msg->response == SIPE_HTTP_STATUS_CLIENT_UNAUTHORIZED) {\n\t\tfailed = sipe_http_request_response_unauthorized(sipe_private,\n\t\t\t\t\t\t\t\t req,\n\t\t\t\t\t\t\t\t msg);\n\n\t} else {\n\t\t/* On some errors throw away the security context */\n\t\tif (((msg->response == SIPE_HTTP_STATUS_CLIENT_FORBIDDEN)  ||\n\t\t     (msg->response == SIPE_HTTP_STATUS_CLIENT_PROXY_AUTH) ||\n\t\t     (msg->response >= SIPE_HTTP_STATUS_SERVER_ERROR))     &&\n\t\t    conn_public->context) {\n\t\t\tSIPE_DEBUG_INFO(\"sipe_http_request_response: response was %d, throwing away security context\",\n\t\t\t\t\tmsg->response);\n\t\t\tsipe_http_request_drop_context(conn_public);\n\t\t}\n\n\t\t/* All other cases are passed on to the user */\n\t\tsipe_http_request_response_callback(sipe_private, req, msg);\n\n\t\t/* req is no longer valid */\n\t\tfailed = FALSE;\n\t}\n\n\tif (failed) {\n\t\t/* Callback: request failed */\n\t\t(*req->cb)(sipe_private,\n\t\t\t   SIPE_HTTP_STATUS_FAILED,\n\t\t\t   msg->headers,\n\t\t\t   NULL,\n\t\t\t   req->cb_data);\n\n\t\t/* remove failed request */\n\t\tsipe_http_request_cancel(req);\n\t}\n}\n\nvoid sipe_http_request_shutdown(struct sipe_http_connection_public *conn_public,\n\t\t\t\tgboolean abort)\n{\n\tif (conn_public->pending_requests) {\n\t\tGSList *entry = conn_public->pending_requests;\n\t\tguint status = abort ?\n\t\t\tSIPE_HTTP_STATUS_ABORTED :\n\t\t\tSIPE_HTTP_STATUS_FAILED;\n\t\tgboolean warn = conn_public->connected && !abort;\n\t\twhile (entry) {\n\t\t\tstruct sipe_http_request *req = entry->data;\n\n\t\t\tif (warn) {\n\t\t\t\tSIPE_DEBUG_ERROR(\"sipe_http_request_shutdown: pending request at shutdown: could indicate missing _ready() call on request. Debugging information:\\n\"\n\t\t\t\t\t\t \"Host:   %s\\n\"\n\t\t\t\t\t\t \"Port:   %d\\n\"\n\t\t\t\t\t\t \"Path:   %s\\n\"\n\t\t\t\t\t\t \"Method: %s\\n\",\n\t\t\t\t\t\t conn_public->host,\n\t\t\t\t\t\t conn_public->port,\n\t\t\t\t\t\t req->path,\n\t\t\t\t\t\t req->body ? \"POST\" : \"GET\");\n\t\t\t}\n\n\t\t\tsipe_http_request_free(conn_public->sipe_private,\n\t\t\t\t\t       req,\n\t\t\t\t\t       status);\n\t\t\tentry = entry->next;\n\t\t}\n\t\tg_slist_free(conn_public->pending_requests);\n\t\tconn_public->pending_requests = NULL;\n\t}\n\n\tif (conn_public->context) {\n\t\tg_free(conn_public->cached_authorization);\n\t\tconn_public->cached_authorization = NULL;\n\t\tsip_sec_destroy_context(conn_public->context);\n\t\tconn_public->context = NULL;\n\t}\n}\n\nstruct sipe_http_request *sipe_http_request_new(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\tconst struct sipe_http_parsed_uri *parsed_uri,\n\t\t\t\t\t\tconst gchar *headers,\n\t\t\t\t\t\tconst gchar *body,\n\t\t\t\t\t\tconst gchar *content_type,\n\t\t\t\t\t\tsipe_http_response_callback *callback,\n\t\t\t\t\t\tgpointer callback_data)\n{\n\tstruct sipe_http_request *req;\n\tif (!parsed_uri)\n\t\treturn(NULL);\n\tif (sipe_http_shutting_down(sipe_private)) {\n\t\tSIPE_DEBUG_ERROR(\"sipe_http_request_new: new HTTP request during shutdown: THIS SHOULD NOT HAPPEN! Debugging information:\\n\"\n\t\t\t\t \"Host:    %s\\n\"\n\t\t\t\t \"Port:    %d\\n\"\n\t\t\t\t \"Path:    %s\\n\"\n\t\t\t\t \"Headers: %s\\n\"\n\t\t\t\t \"Body:    %s\\n\",\n\t\t\t\t parsed_uri->host,\n\t\t\t\t parsed_uri->port,\n\t\t\t\t parsed_uri->path,\n\t\t\t\t headers ? headers : \"<NONE>\",\n\t\t\t\t body ? body : \"<EMPTY>\");\n\t\treturn(NULL);\n\t}\n\n\treq          = g_new0(struct sipe_http_request, 1);\n\treq->flags   = 0;\n\treq->cb      = callback;\n\treq->cb_data = callback_data;\n\tif (headers)\n\t\treq->headers      = g_strdup(headers);\n\tif (body) {\n\t\treq->body         = g_strdup(body);\n\t\treq->content_type = g_strdup(content_type);\n\t}\n\n\t/* default authentication */\n\tif (!SIPE_CORE_PRIVATE_FLAG_IS(SSO))\n\t\tsipe_http_request_authentication(req,\n\t\t\t\t\t\t sipe_private->authuser,\n\t\t\t\t\t\t sipe_private->password);\n\n\tsipe_http_request_enqueue(sipe_private, req, parsed_uri);\n\n\treturn(req);\n}\n\nvoid sipe_http_request_ready(struct sipe_http_request *request)\n{\n\tstruct sipe_http_connection_public *conn_public = request->connection;\n\n\t/* pass first request on already opened connection through directly */\n\tif ((request->flags & SIPE_HTTP_REQUEST_FLAG_FIRST) &&\n\t    conn_public->connected)\n\t\tsipe_http_request_send(conn_public);\n}\n\nstruct sipe_http_session *sipe_http_session_start(void)\n{\n\tstruct sipe_http_session *session = g_new0(struct sipe_http_session, 1);\n\tsession->cookie_jar = g_hash_table_new_full(g_str_hash,\n\t\t\t\t\t\t    g_str_equal,\n\t\t\t\t\t\t    g_free,\n\t\t\t\t\t\t    g_free);\n\treturn(session);\n}\n\nvoid sipe_http_session_close(struct sipe_http_session *session)\n{\n\tif (session) {\n\t\tg_hash_table_destroy(session->cookie_jar);\n\t\tg_free(session);\n\t}\n}\n\nvoid sipe_http_request_cancel(struct sipe_http_request *request)\n{\n\tstruct sipe_http_connection_public *conn_public = request->connection;\n\tconn_public->pending_requests = g_slist_remove(conn_public->pending_requests,\n\t\t\t\t\t\t       request);\n\n\t/* cancelled by requester, don't use callback */\n\trequest->cb = NULL;\n\n\tsipe_http_request_free(conn_public->sipe_private,\n\t\t\t       request,\n\t\t\t       SIPE_HTTP_STATUS_CANCELLED);\n}\n\nvoid sipe_http_request_session(struct sipe_http_request *request,\n\t\t\t       struct sipe_http_session *session)\n{\n\trequest->session = session;\n}\n\nvoid sipe_http_request_allow_redirect(struct sipe_http_request *request)\n{\n\trequest->flags |= SIPE_HTTP_REQUEST_FLAG_REDIRECT;\n}\n\nvoid sipe_http_request_authentication(struct sipe_http_request *request,\n\t\t\t\t      const gchar *user,\n\t\t\t\t      const gchar *password)\n{\n\trequest->flags   |= SIPE_HTTP_REQUEST_FLAG_AUTHDATA;\n\trequest->user     = user;\n\trequest->password = password;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-http-request.h",
    "content": "/**\n * @file sipe-http-request.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Private interface between HTTP Public <-> Request <-> Transport layers */\n#ifndef _SIPE_HTTP_PRIVATE_IF_REQUEST\n#error \"you are not allowed to include sipe-http-request.h!\"\n#endif\n\n/*\n * Interface dependencies:\n *\n * <glib.h>\n */\n\n/* Forward declarations */\nstruct sipmsg;\nstruct sipe_core_private;\nstruct sipe_http_connection_public;\nstruct sipe_http_request;\n\nstruct sipe_http_parsed_uri {\n\tgchar *host;\n\tgchar *path;\n\tguint port;\n        gboolean tls;\n};\n\n/**\n * Parse URI\n *\n * @param uri text to parse\n *\n * @return pointer to parsed URI. Must be freed with @c sipe_http_parsed_uri_free()\n */\nstruct sipe_http_parsed_uri *sipe_http_parse_uri(const gchar *uri);\n\n/**\n * Free parsed URI data structure\n *\n * @param pointer to parsed URI (may be @c NULL)\n */\nvoid sipe_http_parsed_uri_free(struct sipe_http_parsed_uri *parsed_uri);\n\n\n/**\n * Is there pending request for HTTP connection?\n *\n * @param conn_public HTTP connection public data\n */\ngboolean sipe_http_request_pending(struct sipe_http_connection_public *conn_public);\n\n/**\n * HTTP connection is ready for next request\n *\n * @param conn_public HTTP connection public data\n */\nvoid sipe_http_request_next(struct sipe_http_connection_public *conn_public);\n\n/**\n * HTTP response received\n *\n * @param conn_public HTTP connection public data\n * @param msg         parsed message\n */\nvoid sipe_http_request_response(struct sipe_http_connection_public *conn_public,\n\t\t\t\tstruct sipmsg *msg);\n\n/**\n * HTTP connection shutdown\n *\n * @param conn_public HTTP connection public data\n * @param abort       @c TRUE if HTTP stack is shutting down\n */\nvoid sipe_http_request_shutdown(struct sipe_http_connection_public *conn_public,\n\t\t\t\tgboolean abort);\n\n/**\n * Create new HTTP request (internal raw version)\n *\n * @param sipe_private  SIPE core private data\n * @param parsed_uri    pointer to parsed URI\n * @param headers       additional headers to add (may be @c NULL)\n * @param body          body                      (may be @c NULL)\n * @param content_type  MIME type for body (may be @c NULL if body is @c NULL)\n * @param callback      callback function\n * @param callback_data callback data\n *\n * @return pointer to opaque HTTP request data structure\n */\nstruct sipe_http_request *sipe_http_request_new(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\tconst struct sipe_http_parsed_uri *parsed_uri,\n\t\t\t\t\t\tconst gchar *headers,\n\t\t\t\t\t\tconst gchar *body,\n\t\t\t\t\t\tconst gchar *content_type,\n\t\t\t\t\t\tsipe_http_response_callback *callback,\n\t\t\t\t\t\tgpointer callback_data);\n"
  },
  {
    "path": "src/core/sipe-http-transport.c",
    "content": "/**\n * @file sipe-http-transport.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * SIPE HTTP transport layer implementation\n *\n *  - connection handling: opening, closing, timeout\n *  - interface to backend: sending & receiving of raw messages\n *  - request queue pulling\n */\n\n#include <string.h>\n#include <time.h>\n\n#include <glib.h>\n\n#include \"sipmsg.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-http.h\"\n#include \"sipe-schedule.h\"\n#include \"sipe-utils.h\"\n\n#define _SIPE_HTTP_PRIVATE_IF_REQUEST\n#include \"sipe-http-request.h\"\n#define _SIPE_HTTP_PRIVATE_IF_TRANSPORT\n#include \"sipe-http-transport.h\"\n\n#define SIPE_HTTP_CONNECTION         ((struct sipe_http_connection *) connection->user_data)\n#define SIPE_HTTP_CONNECTION_PRIVATE ((struct sipe_http_connection *) conn_public)\n#define SIPE_HTTP_CONNECTION_PUBLIC  ((struct sipe_http_connection_public *) conn)\n\n#define SIPE_HTTP_TIMEOUT_ACTION  \"<+http-timeout>\"\n#define SIPE_HTTP_DEFAULT_TIMEOUT 60 /* in seconds */\n\nstruct sipe_http_connection {\n\tstruct sipe_http_connection_public public;\n\n\tstruct sipe_transport_connection *connection;\n\n\tgchar *host_port;\n\ttime_t timeout;  /* in seconds from epoch */\n\tgboolean use_tls;\n};\n\nstruct sipe_http {\n\tGHashTable *connections;\n\tGQueue *timeouts;\n\ttime_t next_timeout; /* in seconds from epoch, 0 if timer isn't running */\n\tgboolean shutting_down;\n};\n\nstatic gint timeout_compare(gconstpointer a,\n\t\t\t    gconstpointer b,\n                            SIPE_UNUSED_PARAMETER gpointer user_data)\n{\n\treturn(((struct sipe_http_connection *) a)->timeout -\n\t       ((struct sipe_http_connection *) b)->timeout);\n}\n\nstatic void sipe_http_transport_update_timeout_queue(struct sipe_http_connection *conn,\n\t\t\t\t\t\t     gboolean remove);\nstatic void sipe_http_transport_free(gpointer data)\n{\n\tstruct sipe_http_connection *conn = data;\n\n\tSIPE_DEBUG_INFO(\"sipe_http_transport_free: destroying connection '%s'(%p)\",\n\t\t\tconn->host_port, conn->connection);\n\n\tif (conn->connection)\n\t\tsipe_backend_transport_disconnect(conn->connection);\n\tconn->connection = NULL;\n\n\tsipe_http_transport_update_timeout_queue(conn, TRUE);\n\n\tsipe_http_request_shutdown(SIPE_HTTP_CONNECTION_PUBLIC,\n\t\t\t\t   conn->public.sipe_private->http->shutting_down);\n\n\tg_free(conn->public.host);\n\n\tg_free(conn->host_port);\n\tg_free(conn);\n}\n\nstatic void sipe_http_transport_drop(struct sipe_http *http,\n\t\t\t\t     struct sipe_http_connection *conn,\n\t\t\t\t     const gchar *message)\n{\n\tSIPE_LOG_INFO(\"sipe_http_transport_drop: '%s'(%p): %s\",\n\t\t      conn->host_port,\n\t\t      conn->connection,\n\t\t      message ? message : \"REASON UNKNOWN\");\n\n#if GLIB_CHECK_VERSION(2,30,0)\n\t/* this triggers sipe_http_transport_free() */\n\tg_hash_table_remove(http->connections, conn->host_port);\n#else\n\t/* GLIB < 2.30 calls destroy notifiers *before* removing the entry */\n\t/* which can cause a race condition with sipe_http_transport_new() */\n\tg_hash_table_steal(http->connections, conn->host_port);\n\tsipe_http_transport_free(conn);\n#endif\n\t/* conn is no longer valid */\n}\n\nstatic void start_timer(struct sipe_core_private *sipe_private,\n\t\t\ttime_t current_time);\nstatic void sipe_http_transport_timeout(struct sipe_core_private *sipe_private,\n\t\t\t\t\tgpointer data)\n{\n\tstruct sipe_http *http = sipe_private->http;\n\tstruct sipe_http_connection *conn = data;\n\ttime_t current_time = time(NULL);\n\n\t/* timer has expired */\n\thttp->next_timeout = 0;\n\n\twhile (1) {\n\t\tsipe_http_transport_drop(http, conn, \"timeout\");\n\t\t/* conn is no longer valid */\n\n\t\t/* is there another active connection? */\n\t\tconn = g_queue_peek_head(http->timeouts);\n\t\tif (!conn)\n\t\t\tbreak;\n\n\t\t/* restart timer for next connection */\n\t\tif (conn->timeout > current_time) {\n\t\t\tstart_timer(sipe_private, current_time);\n\t\t\tbreak;\n\t\t}\n\n\t\t/* next connection timed-out too, loop around */\n\t}\n}\n\nstatic void start_timer(struct sipe_core_private *sipe_private,\n\t\t\ttime_t current_time)\n{\n\tstruct sipe_http *http = sipe_private->http;\n\tstruct sipe_http_connection *conn = g_queue_peek_head(http->timeouts);\n\n\thttp->next_timeout = conn->timeout;\n\tsipe_schedule_seconds(sipe_private,\n\t\t\t      SIPE_HTTP_TIMEOUT_ACTION,\n\t\t\t      conn,\n\t\t\t      http->next_timeout - current_time,\n\t\t\t      sipe_http_transport_timeout,\n\t\t\t      NULL);\n}\n\nstatic void sipe_http_transport_update_timeout_queue(struct sipe_http_connection *conn,\n\t\t\t\t\t\t     gboolean remove)\n{\n\tstruct sipe_core_private *sipe_private = conn->public.sipe_private;\n\tstruct sipe_http *http = sipe_private->http;\n\tGQueue *timeouts = http->timeouts;\n\ttime_t current_time = time(NULL);\n\n\t/* is this connection at head of queue? */\n\tgboolean update = (conn == g_queue_peek_head(timeouts));\n\n\t/* update timeout queue */\n\tif (remove) {\n\t\tg_queue_remove(timeouts, conn);\n\t} else {\n\t\tconn->timeout = current_time + SIPE_HTTP_DEFAULT_TIMEOUT;\n\t\tg_queue_sort(timeouts,\n\t\t\t     timeout_compare,\n\t\t\t     NULL);\n\t}\n\n\t/* update timer if necessary */\n\tif (update) {\n\t\tsipe_schedule_cancel(sipe_private, SIPE_HTTP_TIMEOUT_ACTION);\n\t\tif (g_queue_is_empty(timeouts)) {\n\t\t\thttp->next_timeout = 0;\n\t\t} else {\n\t\t\tstart_timer(sipe_private, current_time);\n\t\t}\n\t}\n}\n\ngboolean sipe_http_shutting_down(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_http *http = sipe_private->http;\n\t/* We need to return FALSE in case HTTP stack isn't initialized yet */\n\tif (!http)\n\t\treturn(FALSE);\n\treturn(http->shutting_down);\n}\n\nvoid sipe_http_free(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_http *http = sipe_private->http;\n\tif (!http)\n\t\treturn;\n\n\t/* HTTP stack is shutting down: reject all new requests */\n\thttp->shutting_down = TRUE;\n\n\tsipe_schedule_cancel(sipe_private, SIPE_HTTP_TIMEOUT_ACTION);\n\tg_hash_table_destroy(http->connections);\n\tg_queue_free(http->timeouts);\n\tg_free(http);\n\tsipe_private->http = NULL;\n}\n\nstatic void sipe_http_init(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_http *http;\n\tif (sipe_private->http)\n\t\treturn;\n\n\tsipe_private->http = http = g_new0(struct sipe_http, 1);\n\thttp->connections = g_hash_table_new_full(g_str_hash, g_str_equal,\n\t\t\t\t\t\t  NULL,\n\t\t\t\t\t\t  sipe_http_transport_free);\n\thttp->timeouts = g_queue_new();\n}\n\nstatic void sipe_http_transport_connected(struct sipe_transport_connection *connection)\n{\n\tstruct sipe_http_connection *conn = SIPE_HTTP_CONNECTION;\n\tstruct sipe_core_private *sipe_private = conn->public.sipe_private;\n\tstruct sipe_http *http = sipe_private->http;\n\ttime_t current_time = time(NULL);\n\n\tSIPE_LOG_INFO(\"sipe_http_transport_connected: '%s'(%p)\",\n\t\t      conn->host_port, connection);\n\tconn->public.connected = TRUE;\n\n\t/* add active connection to timeout queue */\n\tconn->timeout = current_time + SIPE_HTTP_DEFAULT_TIMEOUT;\n\tg_queue_insert_sorted(http->timeouts,\n\t\t\t      conn,\n\t\t\t      timeout_compare,\n\t\t\t      NULL);\n\n\t/* start timeout timer if necessary */\n\tif (http->next_timeout == 0)\n\t\tstart_timer(sipe_private, current_time);\n\n\tsipe_http_request_next(SIPE_HTTP_CONNECTION_PUBLIC);\n}\n\nstatic void sipe_http_transport_input(struct sipe_transport_connection *connection)\n{\n\tstruct sipe_http_connection *conn = SIPE_HTTP_CONNECTION;\n\tchar *current = connection->buffer;\n\n\t/* according to the RFC remove CRLF at the beginning */\n\twhile (*current == '\\r' || *current == '\\n') {\n\t\tcurrent++;\n\t}\n\tif (current != connection->buffer)\n\t\tsipe_utils_shrink_buffer(connection, current);\n\n\tif (conn->connection &&\n\t    (current = strstr(connection->buffer, \"\\r\\n\\r\\n\")) != NULL) {\n\t\tstruct sipmsg *msg;\n\t\tgboolean drop = FALSE;\n\t\tgboolean next;\n\n\t\tcurrent += 2;\n\t\tcurrent[0] = '\\0';\n\t\tmsg = sipmsg_parse_header(connection->buffer);\n\t\tif (!msg) {\n\t\t\t/* restore header for next try */\n\t\t\tcurrent[0] = '\\r';\n\t\t\treturn;\n\t\t}\n\n\t\t/* HTTP/1.1 Transfer-Encoding: chunked */\n\t\tif (msg->bodylen == SIPMSG_BODYLEN_CHUNKED) {\n\t\t\tgchar *start        = current + 2;\n\t\t\tGSList *chunks      = NULL;\n\t\t\tgboolean incomplete = TRUE;\n\n\t\t\tmsg->bodylen = 0;\n\t\t\twhile (strlen(start) > 0) {\n\t\t\t\tgchar *tmp;\n\t\t\t\tguint length = g_ascii_strtoll(start, &tmp, 16);\n\t\t\t\tguint remainder;\n\t\t\t\tstruct _chunk {\n\t\t\t\t\tguint length;\n\t\t\t\t\tconst gchar *start;\n\t\t\t\t} *chunk;\n\n\t\t\t\t/* Illegal number */\n\t\t\t\tif ((length == 0) && (start == tmp))\n\t\t\t\t\tbreak;\n\t\t\t\tmsg->bodylen += length;\n\n\t\t\t\t/* Chunk header not finished yet */\n\t\t\t\ttmp = strstr(tmp, \"\\r\\n\");\n\t\t\t\tif (tmp == NULL)\n\t\t\t\t\tbreak;\n\n\t\t\t\t/* Chunk not finished yet */\n\t\t\t\ttmp += 2;\n\t\t\t\tremainder = connection->buffer_used - (tmp - connection->buffer);\n\t\t\t\tif (remainder < length + 2)\n\t\t\t\t\tbreak;\n\n\t\t\t\t/* Next chunk */\n\t\t\t\tstart = tmp + length + 2;\n\n\t\t\t\t/* Body completed */\n\t\t\t\tif (length == 0) {\n\t\t\t\t\tgchar *dummy  = g_malloc(msg->bodylen + 1);\n\t\t\t\t\tgchar *p      = dummy;\n\t\t\t\t\tGSList *entry = chunks;\n\n\t\t\t\t\twhile (entry) {\n\t\t\t\t\t\tchunk = entry->data;\n\t\t\t\t\t\tmemcpy(p, chunk->start, chunk->length);\n\t\t\t\t\t\tp += chunk->length;\n\t\t\t\t\t\tentry = entry->next;\n\t\t\t\t\t}\n\t\t\t\t\tp[0] = '\\0';\n\n\t\t\t\t\tmsg->body = dummy;\n\t\t\t\t\tsipe_utils_message_debug(connection,\n\t\t\t\t\t\t\t\t \"HTTP\",\n\t\t\t\t\t\t\t\t connection->buffer,\n\t\t\t\t\t\t\t\t msg->body,\n\t\t\t\t\t\t\t\t FALSE);\n\n\t\t\t\t\tcurrent = start;\n\t\t\t\t\tsipe_utils_shrink_buffer(connection,\n\t\t\t\t\t\t\t\t current);\n\n\t\t\t\t\tincomplete = FALSE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/* Append completed chunk */\n\t\t\t\tchunk = g_new0(struct _chunk, 1);\n\t\t\t\tchunk->length = length;\n\t\t\t\tchunk->start  = tmp;\n\t\t\t\tchunks = g_slist_append(chunks, chunk);\n\t\t\t}\n\n\t\t\tif (chunks)\n\t\t\t\tsipe_utils_slist_free_full(chunks, g_free);\n\n\t\t\tif (incomplete) {\n\t\t\t\t/* restore header for next try */\n\t\t\t\tsipmsg_free(msg);\n\t\t\t\tcurrent[0] = '\\r';\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t} else {\n\t\t\tguint remainder = connection->buffer_used - (current + 2 - connection->buffer);\n\n\t\t\tif (remainder >= (guint) msg->bodylen) {\n\t\t\t\tchar *dummy = g_malloc(msg->bodylen + 1);\n\t\t\t\tcurrent += 2;\n\t\t\t\tmemcpy(dummy, current, msg->bodylen);\n\t\t\t\tdummy[msg->bodylen] = '\\0';\n\t\t\t\tmsg->body = dummy;\n\t\t\t\tcurrent += msg->bodylen;\n\t\t\t\tsipe_utils_message_debug(connection,\n\t\t\t\t\t\t\t \"HTTP\",\n\t\t\t\t\t\t\t connection->buffer,\n\t\t\t\t\t\t\t msg->body,\n\t\t\t\t\t\t\t FALSE);\n\t\t\t\tsipe_utils_shrink_buffer(connection, current);\n\t\t\t} else {\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_http_transport_input: body too short (%d < %d, strlen %\" G_GSIZE_FORMAT \") - ignoring message\",\n\t\t\t\t\t\tremainder, msg->bodylen, strlen(connection->buffer));\n\n\t\t\t\t/* restore header for next try */\n\t\t\t\tsipmsg_free(msg);\n\t\t\t\tcurrent[0] = '\\r';\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (msg->response == SIPMSG_RESPONSE_FATAL_ERROR) {\n\t\t\t/* fatal header parse error */\n\t\t\tmsg->response = SIPE_HTTP_STATUS_SERVER_ERROR;\n\t\t\tdrop          = TRUE;\n\t\t} else if (sipe_strcase_equal(sipmsg_find_header(msg, \"Connection\"), \"close\")) {\n\t\t\tSIPE_DEBUG_INFO(\"sipe_http_transport_input: server requested close '%s'\",\n\t\t\t\t\tconn->host_port);\n\t\t\tdrop          = TRUE;\n\t\t}\n\n\t\tsipe_http_request_response(SIPE_HTTP_CONNECTION_PUBLIC, msg);\n\t\tnext = sipe_http_request_pending(SIPE_HTTP_CONNECTION_PUBLIC);\n\n\t\tif (drop) {\n\t\t\t/* drop backend connection */\n\t\t\tsipe_backend_transport_disconnect(conn->connection);\n\t\t\tconn->connection       = NULL;\n\t\t\tconn->public.connected = FALSE;\n\n\t\t\t/* if we have pending requests we need to trigger re-connect */\n\t\t\tif (next)\n\t\t\t\tsipe_http_transport_new(conn->public.sipe_private,\n\t\t\t\t\t\t\tconn->public.host,\n\t\t\t\t\t\t\tconn->public.port,\n\t\t\t\t\t\t\tconn->use_tls);\n\n\t\t} else if (next) {\n\t\t\t/* trigger sending of next pending request */\n\t\t\tsipe_http_request_next(SIPE_HTTP_CONNECTION_PUBLIC);\n\t\t}\n\n\t\tsipmsg_free(msg);\n\t}\n}\n\nstatic void sipe_http_transport_error(struct sipe_transport_connection *connection,\n\t\t\t\t      const gchar *msg)\n{\n\tstruct sipe_http_connection *conn = SIPE_HTTP_CONNECTION;\n\tsipe_http_transport_drop(conn->public.sipe_private->http,\n\t\t\t\t conn,\n\t\t\t\t msg);\n\t/* conn is no longer valid */\n}\n\nstruct sipe_http_connection_public *sipe_http_transport_new(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t\t    const gchar *host_in,\n\t\t\t\t\t\t\t    const guint32 port,\n\t\t\t\t\t\t\t    gboolean use_tls)\n{\n\tstruct sipe_http *http;\n\tstruct sipe_http_connection *conn = NULL;\n\t/* host name matching should be case insensitive */\n\tgchar *host = g_ascii_strdown(host_in, -1);\n\tgchar *host_port = g_strdup_printf(\"%s:%\" G_GUINT32_FORMAT, host, port);\n\n\tsipe_http_init(sipe_private);\n\n\thttp = sipe_private->http;\n\tif (http->shutting_down) {\n\t\tSIPE_DEBUG_ERROR(\"sipe_http_transport_new: new connection requested during shutdown: THIS SHOULD NOT HAPPEN! Debugging information:\\n\"\n\t\t\t\t \"Host/Port: %s\", host_port);\n\t} else {\n\t\tconn = g_hash_table_lookup(http->connections, host_port);\n\n\t\tif (conn) {\n\t\t\t/* re-establishing connection */\n\t\t\tif (!conn->connection) {\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_http_transport_new: re-establishing %s\", host_port);\n\n\t\t\t\t/* will be re-inserted after connect */\n\t\t\t\tsipe_http_transport_update_timeout_queue(conn, TRUE);\n\t\t\t}\n\n\t\t} else {\n\t\t\t/* new connection */\n\t\t\tSIPE_DEBUG_INFO(\"sipe_http_transport_new: new %s\", host_port);\n\n\t\t\tconn = g_new0(struct sipe_http_connection, 1);\n\n\t\t\tconn->public.sipe_private = sipe_private;\n\t\t\tconn->public.host         = g_strdup(host);\n\t\t\tconn->public.port         = port;\n\n\t\t\tconn->host_port           = host_port;\n\t\t\tconn->use_tls             = use_tls;\n\n\t\t\tg_hash_table_insert(http->connections,\n\t\t\t\t\t    host_port,\n\t\t\t\t\t    conn);\n\t\t\thost_port = NULL; /* conn_private takes ownership of the key */\n\t\t}\n\n\t\tif (!conn->connection) {\n\t\t\tsipe_connect_setup setup = {\n\t\t\t\tuse_tls ? SIPE_TRANSPORT_TLS : SIPE_TRANSPORT_TCP,\n\t\t\t\thost,\n\t\t\t\tport,\n\t\t\t\tconn,\n\t\t\t\tsipe_http_transport_connected,\n\t\t\t\tsipe_http_transport_input,\n\t\t\t\tsipe_http_transport_error\n\t\t\t};\n\n\t\t\tconn->public.connected = FALSE;\n\t\t\tconn->connection = sipe_backend_transport_connect(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\t  &setup);\n\t\t}\n\t}\n\n\tg_free(host_port);\n\tg_free(host);\n\treturn(SIPE_HTTP_CONNECTION_PUBLIC);\n}\n\nvoid sipe_http_transport_send(struct sipe_http_connection_public *conn_public,\n\t\t\t      const gchar *header,\n\t\t\t      const gchar *body)\n{\n\tstruct sipe_http_connection *conn = SIPE_HTTP_CONNECTION_PRIVATE;\n\tGString *message = g_string_new(header);\n\n\tg_string_append_printf(message, \"\\r\\n%s\", body ? body : \"\");\n\n\tsipe_utils_message_debug(conn->connection, \"HTTP\", message->str, NULL, TRUE);\n\tsipe_backend_transport_message(conn->connection, message->str);\n\tg_string_free(message, TRUE);\n\n\tsipe_http_transport_update_timeout_queue(conn, FALSE);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-http-transport.h",
    "content": "/**\n * @file sipe-http-transport.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Private interface between HTTP Request <-> Transport layers */\n#ifndef _SIPE_HTTP_PRIVATE_IF_TRANSPORT\n#error \"you are not allowed to include sipe-http-transport.h!\"\n#endif\n\n/*\n * Interface dependencies:\n *\n * <glib.h>\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\nstruct sip_sec_context;\n\nstruct sipe_http_connection_public {\n\tstruct sipe_core_private *sipe_private;\n\n\tGSList *pending_requests;        /* handled by sipe-http-request.c */\n\tstruct sip_sec_context *context; /* handled by sipe-http-request.c */\n\tgchar *cached_authorization;     /* handled by sipe-http-request.c */\n\n\tgchar *host;\n\tguint32 port;\n\tgboolean connected;\n};\n\n/**\n * Check if we're shutting down the HTTP stack\n *\n * @param sipe_private SIPE core private data\n *\n * @return return @c TRUE if HTTP stack is shutting down\n */\ngboolean sipe_http_shutting_down(struct sipe_core_private *sipe_private);\n\n/**\n * Initiate HTTP connection\n *\n * If a connection to this host/port already exists it will be reused.\n *\n * @param sipe_private SIPE core private data\n * @param host         name of the host to connect to\n * @param port         port number to connect to\n * @param use_tls      use TLS if @c TRUE, otherwise TCP\n *\n * @return HTTP connection public data\n */\nstruct sipe_http_connection_public *sipe_http_transport_new(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t\t    const gchar *host,\n\t\t\t\t\t\t\t    guint32 port,\n\t\t\t\t\t\t\t    gboolean use_tls);\n\n/**\n * Send HTTP request\n *\n * @param conn_public HTTP connection public data\n * @param header      HTTP header\n * @param body        HTTP body (may be @c NULL)\n */\nvoid sipe_http_transport_send(struct sipe_http_connection_public *conn_public,\n\t\t\t      const gchar *header,\n\t\t\t      const gchar *body);\n"
  },
  {
    "path": "src/core/sipe-http.c",
    "content": "/**\n * @file sipe-http.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * SIPE HTTP API implementation\n *\n *  - convenience functions for public API: GET & POST requests\n *  - URL parsing\n *  - all other public API functions are implemented by lower layers\n */\n\n#include <glib.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-http.h\"\n\n#define _SIPE_HTTP_PRIVATE_IF_REQUEST\n#include \"sipe-http-request.h\"\n\nvoid sipe_http_parsed_uri_free(struct sipe_http_parsed_uri *parsed_uri)\n{\n\tif (parsed_uri) {\n\t\tg_free(parsed_uri->host);\n\t\tg_free(parsed_uri->path);\n\t\tg_free(parsed_uri);\n\t}\n}\n\nstruct sipe_http_parsed_uri *sipe_http_parse_uri(const gchar *uri)\n{\n\tstruct sipe_http_parsed_uri *parsed_uri = NULL;\n\tguint offset = 0;\n\tgboolean tls = FALSE;\n\n//\tSIPE_DEBUG_INFO(\"sipe_http_parse_uri: '%s'\", uri);\n\n\tif (g_str_has_prefix(uri, \"https://\")) {\n\t\toffset = 8;\n\t\ttls    = TRUE;\n\t} else if (g_str_has_prefix(uri, \"http://\")) {\n\t\toffset = 7;\n\t}\n\n\tif (offset) {\n\t\tgchar **hostport_path = g_strsplit(uri + offset, \"/\", 2);\n\n\t\tif (hostport_path && hostport_path[0] && hostport_path[1]) {\n\t\t\tgchar **host_port = g_strsplit(hostport_path[0], \":\", 2);\n\n//\t\t\tSIPE_DEBUG_INFO(\"sipe_http_parse_uri: hostport '%s' path '%s'\", hostport_path[0], hostport_path[1]);\n\n\t\t\t/* \":port\" is optional */\n\t\t\tif (host_port && host_port[0]) {\n\n\t\t\t\tparsed_uri = g_new0(struct sipe_http_parsed_uri, 1);\n\t\t\t\tparsed_uri->host = g_strdup(host_port[0]);\n\t\t\t\tparsed_uri->path = g_strdup(hostport_path[1]);\n\t\t\t\tparsed_uri->tls  = tls;\n\n\t\t\t\tif (host_port[1])\n\t\t\t\t\tparsed_uri->port = g_ascii_strtoull(host_port[1],\n\t\t\t\t\t\t\t\t\t    NULL,\n\t\t\t\t\t\t\t\t\t    10);\n\t\t\t\tif (parsed_uri->port == 0) {\n\t\t\t\t\tif (tls)\n\t\t\t\t\t\t/* default port for https */\n\t\t\t\t\t\tparsed_uri->port = 443;\n\t\t\t\t\telse\n\t\t\t\t\t\t/* default port for http */\n\t\t\t\t\t\tparsed_uri->port = 80;\n\t\t\t\t}\n\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_http_parse_uri: host '%s' port %d path '%s'\",\n\t\t\t\t\t\tparsed_uri->host, parsed_uri->port, parsed_uri->path);\n\n\t\t\t}\n\t\t\tg_strfreev(host_port);\n\t\t}\n\t\tg_strfreev(hostport_path);\n\t}\n\n\tif (!parsed_uri)\n\t\tSIPE_DEBUG_ERROR(\"sipe_http_parse_uri: FAILED '%s'\", uri);\n\n\treturn(parsed_uri);\n}\n\nstruct sipe_http_request *sipe_http_request_get(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\tconst gchar *uri,\n\t\t\t\t\t\tconst gchar *headers,\n\t\t\t\t\t\tsipe_http_response_callback *callback,\n\t\t\t\t\t\tgpointer callback_data)\n{\n\tstruct sipe_http_request *req;\n\tstruct sipe_http_parsed_uri *parsed_uri = sipe_http_parse_uri(uri);\n\n\treq = sipe_http_request_new(sipe_private,\n\t\t\t\t    parsed_uri,\n\t\t\t\t    headers,\n\t\t\t\t    NULL,\n\t\t\t\t    NULL,\n\t\t\t\t    callback,\n\t\t\t\t    callback_data);\n\tsipe_http_parsed_uri_free(parsed_uri);\n\n\treturn(req);\n}\n\nstruct sipe_http_request *sipe_http_request_post(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t const gchar *uri,\n\t\t\t\t\t\t const gchar *headers,\n\t\t\t\t\t\t const gchar *body,\n\t\t\t\t\t\t const gchar *content_type,\n\t\t\t\t\t\t sipe_http_response_callback *callback,\n\t\t\t\t\t\t gpointer callback_data)\n{\n\tstruct sipe_http_request *req;\n\tstruct sipe_http_parsed_uri *parsed_uri = sipe_http_parse_uri(uri);\n\n\treq = sipe_http_request_new(sipe_private,\n\t\t\t\t    parsed_uri,\n\t\t\t\t    headers,\n\t\t\t\t    body,\n\t\t\t\t    content_type,\n\t\t\t\t    callback,\n\t\t\t\t    callback_data);\n\tsipe_http_parsed_uri_free(parsed_uri);\n\n\treturn(req);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-http.h",
    "content": "/**\n * @file sipe-http.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013-2015 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * Public interface to HTTP request service\n */\n\n/*\n * Interface dependencies:\n *\n * <glib.h>\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\nstruct sipe_http_request;\nstruct sipe_http_session;\n\n/**\n * HTTP response callback\n *\n * @param sipe_private  SIPE core private data\n * @param status        status code\n * @param headers       response headers (@c NULL if request aborted)\n * @param body          response body    (@c NULL if request aborted)\n * @param callback_data callback data\n */\ntypedef void (sipe_http_response_callback)(struct sipe_core_private *sipe_private,\n\t\t\t\t\t   guint status,\n\t\t\t\t\t   GSList *headers,\n\t\t\t\t\t   const gchar *body,\n\t\t\t\t\t   gpointer callback_data);\n\n/* HTTP response status codes */\n#define SIPE_HTTP_STATUS_FAILED                0 /* internal use */\n#define SIPE_HTTP_STATUS_OK                  200\n#define SIPE_HTTP_STATUS_REDIRECTION         300 /* - 399 */\n#define SIPE_HTTP_STATUS_CLIENT_ERROR        400 /* - 499 */\n#define SIPE_HTTP_STATUS_CLIENT_UNAUTHORIZED 401\n#define SIPE_HTTP_STATUS_CLIENT_FORBIDDEN    403\n#define SIPE_HTTP_STATUS_CLIENT_PROXY_AUTH   407\n#define SIPE_HTTP_STATUS_SERVER_ERROR        500 /* - 599 */\n#define SIPE_HTTP_STATUS_CANCELLED            -2 /* internal use */\n#define SIPE_HTTP_STATUS_ABORTED              -1 /* internal use */\n\n/**\n * Free HTTP data\n *\n * @param sipe_private SIPE core private data\n */\nvoid sipe_http_free(struct sipe_core_private *sipe_private);\n\n/**\n * Start HTTP session\n *\n * @return pointer to opaque HTTP session data structure\n */\nstruct sipe_http_session *sipe_http_session_start(void);\n\n/**\n * Close HTTP session\n *\n * @param session pointer to opaque HTTP session data structure\n */\nvoid sipe_http_session_close(struct sipe_http_session *session);\n\n/**\n * Create HTTP GET request\n *\n * @param sipe_private  SIPE core private data\n * @param uri           URI\n * @param headers       additional headers (may be @c NULL)\n * @param callback      callback function\n * @param callback_data callback data\n *\n * @return pointer to opaque HTTP request data structure (@c NULL if failed)\n */\nstruct sipe_http_request *sipe_http_request_get(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\tconst gchar *uri,\n\t\t\t\t\t\tconst gchar *headers,\n\t\t\t\t\t\tsipe_http_response_callback *callback,\n\t\t\t\t\t\tgpointer callback_data);\n\n/**\n * Create HTTP POST request\n *\n * @param sipe_private  SIPE core private data\n * @param uri           URI\n * @param headers       additional headers (may be @c NULL)\n * @param body          body contents\n * @param content_type  body content type\n * @param callback      callback function\n * @param callback_data callback data\n *\n * @return pointer to opaque HTTP request data structure (@c NULL if failed)\n */\nstruct sipe_http_request *sipe_http_request_post(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t const gchar *uri,\n\t\t\t\t\t\t const gchar *headers,\n\t\t\t\t\t\t const gchar *body,\n\t\t\t\t\t\t const gchar *content_type,\n\t\t\t\t\t\t sipe_http_response_callback *callback,\n\t\t\t\t\t\t gpointer callback_data);\n\n/**\n * HTTP request is ready to be sent\n *\n * @param request pointer to opaque HTTP request data structure\n */\nvoid sipe_http_request_ready(struct sipe_http_request *request);\n\n/**\n * Cancel pending HTTP request\n *\n * @param request pointer to opaque HTTP request data structure\n */\nvoid sipe_http_request_cancel(struct sipe_http_request *request);\n\n/**\n * Assign request to HTTP session\n *\n * @param request pointer to opaque HTTP request data structure\n * @param session pointer to opaque HTTP session data structure\n */\nvoid sipe_http_request_session(struct sipe_http_request *request,\n\t\t\t       struct sipe_http_session *session);\n\n/**\n * Allow redirection of HTTP request\n *\n * @param request pointer to opaque HTTP request data structure\n */\nvoid sipe_http_request_allow_redirect(struct sipe_http_request *request);\n\n/**\n * Provide authentication information for HTTP request\n *\n * @param request  pointer to opaque HTTP request data structure\n * @param user     user name   (MUST stay valid for duration of request!)\n * @param password Password    (MUST stay valid for duration of request!)\n */\nvoid sipe_http_request_authentication(struct sipe_http_request *request,\n\t\t\t\t      const gchar *user,\n\t\t\t\t      const gchar *password);\n"
  },
  {
    "path": "src/core/sipe-im.c",
    "content": "/**\n * @file sipe-im.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipmsg.h\"\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-buddy.h\"\n#include \"sipe-chat.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-dialog.h\"\n#include \"sipe-ft.h\"\n#include \"sipe-groupchat.h\"\n#include \"sipe-im.h\"\n#include \"sipe-incoming.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-session.h\"\n#include \"sipe-user.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n\n/*\n * Hash key template for unconfirmed messages\n *\n *                                             Call-ID      Recipient URI (or empty)\n *                                               |               |\n *                                               |  SIP method   |    CSeq\n *                                               |     |         |     |             */\n#define UNCONFIRMED_KEY_TEMPLATE(method, cseq) \"<%s><\" method \"><%s><\" cseq\n\n/* key must be g_free()'d */\nstatic gchar *get_unconfirmed_message_key(const gchar *callid,\n\t\t\t\t\t  unsigned int cseq,\n\t\t\t\t\t  const gchar *with)\n{\n\treturn(g_strdup_printf(UNCONFIRMED_KEY_TEMPLATE(\"%s\", \"%d>\"),\n\t\t\t       callid,\n\t\t\t       with ? \"MESSAGE\" : \"INVITE\",\n\t\t\t       with ? with : \"\",\n\t\t\t       cseq));\n}\n\nstatic void insert_unconfirmed_message(struct sip_session *session,\n\t\t\t\t       struct sip_dialog *dialog,\n\t\t\t\t       const gchar *with,\n\t\t\t\t       const gchar *body,\n\t\t\t\t       const gchar *content_type)\n{\n\tgchar *key = get_unconfirmed_message_key(dialog->callid, dialog->cseq + 1, with);\n\tstruct queued_message *message = g_new0(struct queued_message, 1);\n\n\tmessage->body = g_strdup(body);\n\tif (content_type != NULL)\n\t\tmessage->content_type = g_strdup(content_type);\n\tmessage->cseq = dialog->cseq + 1;\n\n\tg_hash_table_insert(session->unconfirmed_messages, key, message);\n\tSIPE_DEBUG_INFO(\"insert_unconfirmed_message: added %s to list (count=%d)\",\n\t\t\tkey, g_hash_table_size(session->unconfirmed_messages));\n}\n\nstatic gboolean remove_unconfirmed_message(struct sip_session *session,\n\t\t\t\t\t   const gchar *key)\n{\n\tgboolean found = g_hash_table_remove(session->unconfirmed_messages, key);\n\tif (found) {\n\t\tSIPE_DEBUG_INFO(\"remove_unconfirmed_message: removed %s from list (count=%d)\",\n\t\t\t\tkey, g_hash_table_size(session->unconfirmed_messages));\n\t} else {\n\t\tSIPE_DEBUG_INFO(\"remove_unconfirmed_message: key %s not found\",\n\t\t\t\tkey);\n\t}\n\treturn(found);\n}\n\nstatic void sipe_refer_notify(struct sipe_core_private *sipe_private,\n\t\t\t      struct sip_session *session,\n\t\t\t      const gchar *who,\n\t\t\t      int status,\n\t\t\t      const gchar *desc)\n{\n\tgchar *hdr;\n\tgchar *body;\n\tstruct sip_dialog *dialog = sipe_dialog_find(session, who);\n\n\thdr = g_strdup_printf(\n\t\t\"Event: refer\\r\\n\"\n\t\t\"Subscription-State: %s\\r\\n\"\n\t\t\"Content-Type: message/sipfrag\\r\\n\",\n\t\tstatus >= 200 ? \"terminated\" : \"active\");\n\n\tbody = g_strdup_printf(\n\t\t\"SIP/2.0 %d %s\\r\\n\",\n\t\tstatus, desc);\n\n\tsip_transport_request(sipe_private,\n\t\t\t      \"NOTIFY\",\n\t\t\t      who,\n\t\t\t      who,\n\t\t\t      hdr,\n\t\t\t      body,\n\t\t\t      dialog,\n\t\t\t      NULL);\n\n\tg_free(hdr);\n\tg_free(body);\n}\n\nstatic gboolean process_invite_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\tstruct sipmsg *msg,\n\t\t\t\t\tstruct transaction *trans)\n{\n\tgchar *with = sipmsg_parse_to_address(msg);\n\tstruct sip_session *session;\n\tstruct sip_dialog *dialog;\n\tgchar *key;\n\tstruct queued_message *message;\n\tstruct sipmsg *request_msg = trans->msg;\n\n\tconst gchar *callid = sipmsg_find_call_id_header(msg);\n\tgchar *referred_by;\n\n\tsession = sipe_session_find_chat_or_im(sipe_private, callid, with);\n\tif (!session) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_invite_response: unable to find IM session\");\n\t\tg_free(with);\n\t\treturn FALSE;\n\t}\n\n\tdialog = sipe_dialog_find(session, with);\n\tif (!dialog) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_invite_response: session outgoing dialog is NULL\");\n\t\tg_free(with);\n\t\treturn FALSE;\n\t}\n\n\tsipe_dialog_parse(dialog, msg, TRUE);\n\n\tkey = get_unconfirmed_message_key(dialog->callid, sipmsg_parse_cseq(msg), NULL);\n\tmessage = g_hash_table_lookup(session->unconfirmed_messages, key);\n\n\tif (msg->response != 200) {\n\t\tgchar *alias = sipe_buddy_get_alias(sipe_private, with);\n\t\tint warning = sipmsg_parse_warning(msg, NULL);\n\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_invite_response: INVITE response not 200\");\n\n\t\t/* cancel file transfer as rejected by server */\n\t\tif (msg->response == 606 &&\t/* Not acceptable all. */\n\t\t    warning == 309 &&\t\t/* Message contents not allowed by policy */\n\t\t    message && g_str_has_prefix(message->content_type, \"text/x-msmsgsinvite\"))\n\t\t{\n\t\t\tGSList *parsed_body = sipe_ft_parse_msg_body(message->body);\n\t\t\tsipe_ft_incoming_cancel(dialog, parsed_body);\n\t\t\tsipe_utils_nameval_free(parsed_body);\n\t\t}\n\n\t\tif (message) {\n\t\t\t/* generate error for each unprocessed message */\n\t\t\tGSList *entry = session->outgoing_message_queue;\n\t\t\twhile (entry) {\n\t\t\t\tstruct queued_message *queued = entry->data;\n\t\t\t\tsipe_user_present_message_undelivered(sipe_private, session, msg->response, warning, alias ? alias : with, queued->body);\n\t\t\t\tentry = sipe_session_dequeue_message(session);\n\t\t\t}\n\t\t} else {\n\t\t\t/* generate one error and remove all unprocessed messages */\n\t\t\tgchar *tmp_msg = g_strdup_printf(_(\"Failed to invite %s\"), alias ? alias : with);\n\t\t\tsipe_user_present_error(sipe_private, session, tmp_msg);\n\t\t\tg_free(tmp_msg);\n\t\t\twhile (sipe_session_dequeue_message(session));\n\t\t}\n\t\tg_free(alias);\n\n\t\tremove_unconfirmed_message(session, key);\n\t\t/* message is no longer valid */\n\t\tg_free(key);\n\n\t\tsipe_dialog_remove(session, with);\n\t\tg_free(with);\n\n\t\tif (session->is_groupchat) {\n\t\t\tsipe_groupchat_invite_failed(sipe_private, session);\n\t\t\t/* session is no longer valid */\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\tdialog->cseq = 0;\n\tsip_transport_ack(sipe_private, dialog);\n\tdialog->outgoing_invite = NULL;\n\tdialog->is_established = TRUE;\n\n\treferred_by = sipmsg_parse_address_from_header(request_msg, \"Referred-By\");\n\tif (referred_by) {\n\t\tsipe_refer_notify(sipe_private, session, referred_by, 200, \"OK\");\n\t\tg_free(referred_by);\n\t}\n\n\t/* add user to chat if it is a multiparty session */\n\tif (session->chat_session &&\n\t    (session->chat_session->type == SIPE_CHAT_TYPE_MULTIPARTY)) {\n\t\tsipe_backend_chat_add(session->chat_session->backend,\n\t\t\t\t      with,\n\t\t\t\t      TRUE);\n\t}\n\n\tif (session->is_groupchat) {\n\t\tsipe_groupchat_invite_response(sipe_private, dialog, msg);\n\t}\n\n\tif(g_slist_find_custom(dialog->supported, \"ms-text-format\", (GCompareFunc)g_ascii_strcasecmp)) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_invite_response: remote system accepted message in INVITE\");\n\t\tsipe_session_dequeue_message(session);\n\t}\n\n\tsipe_im_process_queue(sipe_private, session);\n\n\tremove_unconfirmed_message(session, key);\n\n\tg_free(key);\n\tg_free(with);\n\treturn TRUE;\n}\n\n/* EndPoints: \"alice alisson\" <sip:alice@atlanta.local>, <sip:bob@atlanta.local>;epid=ebca82d94d, <sip:carol@atlanta.local> */\nstatic gchar *get_end_points(struct sipe_core_private *sipe_private,\n\t\t\t     struct sip_session *session)\n{\n\tgchar *res;\n\n\tif (session == NULL) {\n\t\treturn NULL;\n\t}\n\n\tres = g_strdup_printf(\"<sip:%s>\", sipe_private->username);\n\n\tSIPE_DIALOG_FOREACH {\n\t\tgchar *tmp = res;\n\t\tres = g_strdup_printf(\"%s, <%s>\", res, dialog->with);\n\t\tg_free(tmp);\n\n\t\tif (dialog->theirepid) {\n\t\t\ttmp = res;\n\t\t\tres = g_strdup_printf(\"%s;epid=%s\", res, dialog->theirepid);\n\t\t\tg_free(tmp);\n\t\t}\n\t} SIPE_DIALOG_FOREACH_END;\n\n\treturn res;\n}\n\nvoid\nsipe_im_invite(struct sipe_core_private *sipe_private,\n\t       struct sip_session *session,\n\t       const gchar *who,\n\t       const gchar *msg_body,\n\t       const gchar *content_type,\n\t       const gchar *referred_by,\n\t       const gboolean is_triggered)\n{\n\tgchar *hdr;\n\tgchar *to;\n\tgchar *contact;\n\tgchar *body;\n\tgchar *self;\n\tchar  *ms_text_format = NULL;\n\tchar  *ms_conversation_id = NULL;\n\tgchar *roster_manager;\n\tgchar *end_points;\n\tgchar *referred_by_str;\n\tgboolean is_multiparty =\n\t\tsession->chat_session &&\n\t\t(session->chat_session->type == SIPE_CHAT_TYPE_MULTIPARTY);\n\tstruct sip_dialog *dialog = sipe_dialog_find(session, who);\n\n\tif (dialog && dialog->is_established) {\n\t\tSIPE_DEBUG_INFO(\"session with %s already has a dialog open\", who);\n\t\treturn;\n\t}\n\n\tif (!dialog) {\n\t\tdialog = sipe_dialog_add(session);\n\t\tdialog->callid = session->callid ? g_strdup(session->callid) : gencallid();\n\t\tdialog->with = g_strdup(who);\n\t}\n\n\tif (!(dialog->ourtag)) {\n\t\tdialog->ourtag = gentag();\n\t}\n\n\tto = sip_uri(who);\n\n\tif (msg_body) {\n\t\tchar *msgtext = NULL;\n\t\tchar *base64_msg;\n\t\tconst gchar *msgr = \"\";\n\t\tgchar *tmp = NULL;\n\n\t\tif (!g_str_has_prefix(content_type, \"text/x-msmsgsinvite\")) {\n\t\t\tchar *msgformat = NULL;\n\t\t\tgchar *msgr_value;\n\n\t\t\tsipe_parse_html(msg_body, &msgformat, &msgtext);\n\t\t\tSIPE_DEBUG_INFO(\"sipe_invite: msgformat=%s\", msgformat);\n\n\t\t\tmsgr_value = sipmsg_get_msgr_string(msgformat);\n\t\t\tg_free(msgformat);\n\t\t\tif (msgr_value) {\n\t\t\t\tmsgr = tmp = g_strdup_printf(\";msgr=%s\", msgr_value);\n\t\t\t\tg_free(msgr_value);\n\t\t\t}\n\n\t\t\t/* When Sipe reconnects after a crash, we are not able\n\t\t\t * to send messages to contacts with which we had open\n\t\t\t * conversations when the crash occured. Server sends\n\t\t\t * error response with reason=\"This client has an IM\n\t\t\t * session with the same conversation ID\"\n\t\t\t *\n\t\t\t * Setting random Ms-Conversation-ID prevents this problem\n\t\t\t * so we can continue the conversation. */\n\t\t\tms_conversation_id = g_strdup_printf(\"Ms-Conversation-ID: %u\\r\\n\",\n\t\t\t\t\t\t\t     rand() % 1000000000);\n\t\t} else {\n\t\t\tmsgtext = g_strdup(msg_body);\n\t\t}\n\n\t\tbase64_msg = g_base64_encode((guchar*) msgtext, strlen(msgtext));\n\t\tms_text_format = g_strdup_printf(\"ms-text-format: %s; charset=UTF-8%s;ms-body=%s\\r\\n\",\n\t\t\t\t\t\t content_type ? content_type : \"text/plain\",\n\t\t\t\t\t\t msgr,\n\t\t\t\t\t\t base64_msg);\n\t\tg_free(msgtext);\n\t\tg_free(tmp);\n\t\tg_free(base64_msg);\n\n\t\tinsert_unconfirmed_message(session, dialog, NULL,\n\t\t\t\t\t   msg_body, content_type);\n\t}\n\n\tcontact = get_contact(sipe_private);\n\tend_points = get_end_points(sipe_private, session);\n\tself = sip_uri_self(sipe_private);\n\troster_manager = g_strdup_printf(\n\t\t\"Roster-Manager: %s\\r\\n\"\n\t\t\"EndPoints: %s\\r\\n\",\n\t\tself,\n\t\tend_points);\n\treferred_by_str = referred_by ?\n\t\tg_strdup_printf(\n\t\t\t\"Referred-By: %s\\r\\n\",\n\t\t\treferred_by)\n\t\t: g_strdup(\"\");\n\thdr = g_strdup_printf(\n\t\t\"Supported: ms-sender\\r\\n\"\n\t\t\"%s\"\n\t\t\"%s\"\n\t\t\"%s\"\n\t\t\"%s\"\n\t\t\"Contact: %s\\r\\n%s\"\n\t\t\"%s\"\n\t\t\"Content-Type: application/sdp\\r\\n\",\n\t\tis_multiparty && sipe_strcase_equal(session->chat_session->id, self) ? roster_manager : \"\",\n\t\treferred_by_str,\n\t\tis_triggered ? \"TriggeredInvite: TRUE\\r\\n\" : \"\",\n\t\tis_triggered || is_multiparty ? \"Require: com.microsoft.rtc-multiparty\\r\\n\" : \"\",\n\t\tcontact,\n\t\tms_text_format ? ms_text_format : \"\",\n\t\tms_conversation_id ? ms_conversation_id : \"\");\n\tg_free(ms_text_format);\n\tg_free(ms_conversation_id);\n\tg_free(self);\n\n\tbody = g_strdup_printf(\n\t\t\"v=0\\r\\n\"\n\t\t\"o=- 0 0 IN %s %s\\r\\n\"\n\t\t\"s=session\\r\\n\"\n\t\t\"c=IN %s %s\\r\\n\"\n\t\t\"t=0 0\\r\\n\"\n\t\t\"m=%s %d sip null\\r\\n\"\n\t\t\"a=accept-types:\" SDP_ACCEPT_TYPES \"\\r\\n\",\n\t\tsip_transport_sdp_address_marker(sipe_private),\n\t\tsip_transport_ip_address(sipe_private),\n\t\tsip_transport_sdp_address_marker(sipe_private),\n\t\tsip_transport_ip_address(sipe_private),\n\t\tSIPE_CORE_PRIVATE_FLAG_IS(OCS2007) ? \"message\" : \"x-ms-message\",\n\t\tsip_transport_port(sipe_private));\n\n\tdialog->outgoing_invite = sip_transport_request(sipe_private,\n\t\t\t\t\t\t\t\"INVITE\",\n\t\t\t\t\t\t\tto,\n\t\t\t\t\t\t\tto,\n\t\t\t\t\t\t\thdr,\n\t\t\t\t\t\t\tbody,\n\t\t\t\t\t\t\tdialog,\n\t\t\t\t\t\t\tprocess_invite_response);\n\n\tg_free(to);\n\tg_free(roster_manager);\n\tg_free(end_points);\n\tg_free(referred_by_str);\n\tg_free(body);\n\tg_free(hdr);\n\tg_free(contact);\n}\n\nstatic gboolean\nprocess_message_response(struct sipe_core_private *sipe_private,\n\t\t\t struct sipmsg *msg,\n\t\t\t SIPE_UNUSED_PARAMETER struct transaction *trans)\n{\n\tgboolean ret = TRUE;\n\tgchar *with = sipmsg_parse_to_address(msg);\n\tconst gchar *callid = sipmsg_find_call_id_header(msg);\n\tstruct sip_session *session = sipe_session_find_chat_or_im(sipe_private, callid, with);\n\tstruct sip_dialog *dialog;\n\tgchar *key;\n\tstruct queued_message *message;\n\n\tif (!session) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_message_response: unable to find IM session\");\n\t\tg_free(with);\n\t\treturn FALSE;\n\t}\n\n\tdialog = sipe_dialog_find(session, with);\n\tif (!dialog) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_message_response: session outgoing dialog is NULL\");\n\t\tg_free(with);\n\t\treturn FALSE;\n\t}\n\n\tkey = get_unconfirmed_message_key(sipmsg_find_call_id_header(msg), sipmsg_parse_cseq(msg), with);\n\tmessage = g_hash_table_lookup(session->unconfirmed_messages, key);\n\n\tif (msg->response >= 400) {\n\t\tint warning = sipmsg_parse_warning(msg, NULL);\n\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_message_response: MESSAGE response >= 400\");\n\n\t\t/* cancel file transfer as rejected by server */\n\t\tif (msg->response == 606 &&\t/* Not acceptable all. */\n\t\t    warning == 309 &&\t\t/* Message contents not allowed by policy */\n\t\t    message && g_str_has_prefix(message->content_type, \"text/x-msmsgsinvite\"))\n\t\t{\n\t\t\tGSList *parsed_body = sipe_ft_parse_msg_body(msg->body);\n\t\t\tsipe_ft_incoming_cancel(dialog, parsed_body);\n\t\t\tsipe_utils_nameval_free(parsed_body);\n\t\t}\n\n\t\t/* drop dangling IM sessions: assume that BYE from remote never reached us */\n\t\tif (msg->response == 408 || /* Request timeout */\n\t\t    msg->response == 480 || /* Temporarily Unavailable */\n\t\t    msg->response == 481) { /* Call/Transaction Does Not Exist */\n\t\t\tsipe_im_cancel_dangling(sipe_private, session, dialog, with,\n\t\t\t\t\t\tsipe_im_cancel_unconfirmed);\n\t\t\t/* dialog is no longer valid */\n\t\t} else {\n\t\t\tgchar *alias = sipe_buddy_get_alias(sipe_private, with);\n\t\t\tsipe_user_present_message_undelivered(sipe_private, session,\n\t\t\t\t\t\t\t      msg->response, warning,\n\t\t\t\t\t\t\t      alias ? alias : with,\n\t\t\t\t\t\t\t      message ? message->body : NULL);\n\t\t\tremove_unconfirmed_message(session, key);\n\t\t\t/* message is no longer valid */\n\t\t\tg_free(alias);\n\t\t}\n\n\t\tret = FALSE;\n\t} else {\n\t\tconst gchar *message_id = sipmsg_find_header(msg, \"Message-Id\");\n\t\tif (message_id) {\n\t\t\tg_hash_table_insert(session->conf_unconfirmed_messages, g_strdup(message_id), g_strdup(message->body));\n\t\t\tSIPE_DEBUG_INFO(\"process_message_response: added message with id %s to conf_unconfirmed_messages(count=%d)\",\n\t\t\t\t\tmessage_id, g_hash_table_size(session->conf_unconfirmed_messages));\n\t\t}\n\t\tremove_unconfirmed_message(session, key);\n\t}\n\n\tg_free(key);\n\tg_free(with);\n\n\tif (ret) sipe_im_process_queue(sipe_private, session);\n\treturn ret;\n}\n\n#ifndef ENABLE_OCS2005_MESSAGE_HACK\n/*\n * Hack to circumvent problems reported in the bug report\n *\n *        #3267073 - False \"could not be delivered\" errors\n *\n * The logs provided by the reporters indicate that OCS2005 clients DO NOT\n * acknowledge our SIP MESSAGEs. Therefore the message timeout is triggered\n * and messages are reported to the user as not delivered.\n *\n * Either this is a bug in the OCS2005 client or we do something wrong in our\n * SIP MESSAGEs. This hack removes the message timeout and is provided for\n * users who need to communicate with a still existing OCS2005 user base.\n *\n * Do not enable it by default!\n */\nstatic gboolean\nprocess_message_timeout(struct sipe_core_private *sipe_private,\n\t\t\tstruct sipmsg *msg,\n\t\t\tSIPE_UNUSED_PARAMETER struct transaction *trans)\n{\n\tgchar *with = sipmsg_parse_to_address(msg);\n\tconst gchar *callid = sipmsg_find_call_id_header(msg);\n\tstruct sip_session *session = sipe_session_find_chat_or_im(sipe_private, callid, with);\n\tgchar *key;\n\tgboolean found;\n\n\tif (!session) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_message_timeout: unable to find IM session\");\n\t\tg_free(with);\n\t\treturn TRUE;\n\t}\n\n\t/* Remove timed-out message from unconfirmed list */\n\tkey = get_unconfirmed_message_key(sipmsg_find_call_id_header(msg), sipmsg_parse_cseq(msg), with);\n\tfound = remove_unconfirmed_message(session, key);\n\tg_free(key);\n\n\tif (found) {\n\t\tgchar *alias = sipe_buddy_get_alias(sipe_private, with);\n\t\tsipe_user_present_message_undelivered(sipe_private, session, -1, -1,\n\t\t\t\t\t\t      alias ? alias : with,\n\t\t\t\t\t\t      msg->body);\n\t\tg_free(alias);\n\t}\n\n\tg_free(with);\n\treturn TRUE;\n}\n#endif\n\nstatic void sipe_im_send_message(struct sipe_core_private *sipe_private,\n\t\t\t\t struct sip_dialog *dialog,\n\t\t\t\t const gchar *msg_body,\n\t\t\t\t const gchar *content_type)\n{\n\tgchar *hdr;\n\tgchar *tmp;\n\tchar *msgtext = NULL;\n\tconst gchar *msgr = \"\";\n\tgchar *tmp2 = NULL;\n\n\tif (content_type == NULL)\n\t\tcontent_type = \"text/plain\";\n\n\tif (!g_str_has_prefix(content_type, \"text/x-msmsgsinvite\")) {\n\t\tchar *msgformat = NULL;\n\t\tgchar *msgr_value;\n\n\t\tsipe_parse_html(msg_body, &msgformat, &msgtext);\n\t\tSIPE_DEBUG_INFO(\"sipe_send_message: msgformat=%s\", msgformat);\n\n\t\tmsgr_value = sipmsg_get_msgr_string(msgformat);\n\t\tg_free(msgformat);\n\t\tif (msgr_value) {\n\t\t\tmsgr = tmp2 = g_strdup_printf(\";msgr=%s\", msgr_value);\n\t\t\tg_free(msgr_value);\n\t\t}\n\t} else {\n\t\tmsgtext = g_strdup(msg_body);\n\t}\n\n\ttmp = get_contact(sipe_private);\n\t//hdr = g_strdup(\"Content-Type: text/plain; charset=UTF-8\\r\\n\");\n\t//hdr = g_strdup(\"Content-Type: text/rtf\\r\\n\");\n\t//hdr = g_strdup(\"Content-Type: text/plain; charset=UTF-8;msgr=WAAtAE0ATQBTAC....AoADQA\\r\\nSupported: timer\\r\\n\");\n\n\thdr = g_strdup_printf(\"Contact: %s\\r\\nContent-Type: %s; charset=UTF-8%s\\r\\n\", tmp, content_type, msgr);\n\tg_free(tmp);\n\tg_free(tmp2);\n\n#ifdef ENABLE_OCS2005_MESSAGE_HACK\n\tsip_transport_request(\n#else\n\tsip_transport_request_timeout(\n#endif\n\t\t\t\t      sipe_private,\n\t\t\t\t      \"MESSAGE\",\n\t\t\t\t      dialog->with,\n\t\t\t\t      dialog->with,\n\t\t\t\t      hdr,\n\t\t\t\t      msgtext,\n\t\t\t\t      dialog,\n\t\t\t\t      process_message_response\n#ifndef ENABLE_OCS2005_MESSAGE_HACK\n\t\t\t\t      ,\n\t\t\t\t      60,\n\t\t\t\t      process_message_timeout\n#endif\n\t\t\t\t     );\n\tg_free(msgtext);\n\tg_free(hdr);\n}\n\nvoid sipe_im_process_queue(struct sipe_core_private *sipe_private,\n\t\t\t   struct sip_session *session)\n{\n\tGSList *entry2 = session->outgoing_message_queue;\n\twhile (entry2) {\n\t\tstruct queued_message *msg = entry2->data;\n\n\t\t/* for multiparty chat or conference */\n\t\tif (session->chat_session) {\n\t\t\tgchar *who = sip_uri_self(sipe_private);\n\t\t\tsipe_backend_chat_message(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t  session->chat_session->backend,\n\t\t\t\t\t\t  who,\n\t\t\t\t\t\t  0,\n\t\t\t\t\t\t  msg->body);\n\t\t\tg_free(who);\n\t\t}\n\n\t\tSIPE_DIALOG_FOREACH {\n\t\t\tif (dialog->outgoing_invite) continue; /* do not send messages as INVITE is not responded. */\n\n\t\t\tinsert_unconfirmed_message(session, dialog, dialog->with,\n\t\t\t\t\t\t   msg->body, msg->content_type);\n\n\t\t\tsipe_im_send_message(sipe_private, dialog, msg->body, msg->content_type);\n\t\t} SIPE_DIALOG_FOREACH_END;\n\n\t\tentry2 = sipe_session_dequeue_message(session);\n\t}\n}\n\nstruct unconfirmed_callback_data {\n\tconst gchar *prefix;\n\tGSList *list;\n};\n\nstruct unconfirmed_message {\n\tconst gchar *key;\n\tconst struct queued_message *msg;\n};\n\nstatic gint compare_cseq(gconstpointer a,\n\t\t\t gconstpointer b)\n{\n\treturn(((struct unconfirmed_message *) a)->msg->cseq -\n\t       ((struct unconfirmed_message *) b)->msg->cseq);\n}\n\nstatic void unconfirmed_message_callback(gpointer key,\n\t\t\t\t\t gpointer value,\n\t\t\t\t\t gpointer user_data)\n{\n\tconst gchar *message_key = key;\n\tstruct unconfirmed_callback_data *data = user_data;\n\n\tSIPE_DEBUG_INFO(\"unconfirmed_message_callback: key %s\", message_key);\n\n\t/* Put messages with the same prefix on a list sorted by CSeq */\n\tif (g_str_has_prefix(message_key, data->prefix)) {\n\t\tstruct unconfirmed_message *msg = g_malloc(sizeof(struct unconfirmed_message));\n\t\tmsg->key = message_key;\n\t\tmsg->msg = value;\n\t\tdata->list = g_slist_insert_sorted(data->list, msg,\n\t\t\t\t\t\t   compare_cseq);\n\t}\n}\n\nstatic void foreach_unconfirmed_message(struct sipe_core_private *sipe_private,\n\t\t\t\t\tstruct sip_session *session,\n\t\t\t\t\tconst gchar *callid,\n\t\t\t\t\tconst gchar *with,\n\t\t\t\t\tunconfirmed_callback callback,\n\t\t\t\t\tconst gchar *callback_data)\n{\n\tgchar *prefix = g_strdup_printf(UNCONFIRMED_KEY_TEMPLATE(\"MESSAGE\", \"\"),\n\t\t\t\t\tcallid, with);\n\tstruct unconfirmed_callback_data data = { prefix, NULL };\n\n\tSIPE_DEBUG_INFO(\"foreach_unconfirmed_message: prefix %s\", prefix);\n\n\t/* Generate list of matching unconfirmed messages */\n\tg_hash_table_foreach(session->unconfirmed_messages,\n\t\t\t     unconfirmed_message_callback,\n\t\t\t     &data);\n\tg_free(prefix);\n\n\t/* Process list unconfirmed messages */\n\tif (data.list) {\n\t\tGSList *entry;\n\n\t\twhile ((entry = data.list) != NULL) {\n\t\t\tstruct unconfirmed_message *unconfirmed = entry->data;\n\t\t\tdata.list = g_slist_remove(data.list, unconfirmed);\n\n\t\t\tSIPE_DEBUG_INFO(\"foreach_unconfirmed_message: %s\", unconfirmed->key);\n\t\t\t(*callback)(sipe_private, session, unconfirmed->msg->body, callback_data);\n\n\t\t\tg_hash_table_remove(session->unconfirmed_messages, unconfirmed->key);\n\t\t\tg_free(unconfirmed);\n\t\t}\n\t}\n}\n\nstatic void cancel_callback(struct sipe_core_private *sipe_private,\n\t\t\t    struct sip_session *session,\n\t\t\t    const gchar *body,\n\t\t\t    const gchar *with)\n{\n\tsipe_user_present_message_undelivered(sipe_private, session,\n\t\t\t\t\t      -1, -1, with, body);\n}\n\nvoid sipe_im_cancel_unconfirmed(struct sipe_core_private *sipe_private,\n\t\t\t\tstruct sip_session *session,\n\t\t\t\tconst gchar *callid,\n\t\t\t\tconst gchar *with)\n{\n\tgchar *alias = sipe_buddy_get_alias(sipe_private, with);\n\n\tSIPE_DEBUG_INFO(\"sipe_im_cancel_unconfirmed: with %s callid '%s'\",\n\t\t\twith, callid);\n\n\tforeach_unconfirmed_message(sipe_private, session, callid, with,\n\t\t\t\t    cancel_callback, alias ? alias : with);\n\tg_free(alias);\n}\n\nstatic void reenqueue_callback(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private,\n\t\t\t       struct sip_session *session,\n\t\t\t       const gchar *body,\n\t\t\t       SIPE_UNUSED_PARAMETER const gchar *with)\n{\n\tsipe_session_enqueue_message(session, body, NULL);\n}\n\nvoid sipe_im_reenqueue_unconfirmed(struct sipe_core_private *sipe_private,\n\t\t\t\t   struct sip_session *session,\n\t\t\t\t   const gchar *callid,\n\t\t\t\t   const gchar *with)\n{\n\t/* Remember original list, start with an empty list  */\n\tGSList *first = session->outgoing_message_queue;\n\tsession->outgoing_message_queue = NULL;\n\n\tSIPE_DEBUG_INFO(\"sipe_im_reenqueue_unconfirmed: with %s callid '%s'\",\n\t\t\twith, callid);\n\n\t/* Enqueue unconfirmed messages */\n\tforeach_unconfirmed_message(sipe_private, session, callid, with,\n\t\t\t\t    reenqueue_callback, NULL);\n\n\t/* Append or restore original list */\n\tif (session->outgoing_message_queue) {\n\t\tGSList *last = g_slist_last(session->outgoing_message_queue);\n\t\tlast->next = first;\n\t} else {\n\t\tsession->outgoing_message_queue = first;\n\t}\n}\n\nvoid sipe_core_im_send(struct sipe_core_public *sipe_public,\n\t\t       const gchar *who,\n\t\t       const gchar *what)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tstruct sip_session *session;\n\tstruct sip_dialog *dialog;\n\tgchar *uri = sip_uri(who);\n\n\tSIPE_DEBUG_INFO(\"sipe_core_im_send: '%s'\", what);\n\n\tsession = sipe_session_find_or_add_im(sipe_private, uri);\n\tdialog = sipe_dialog_find(session, uri);\n\n\t/* Queue the message */\n\tsipe_session_enqueue_message(session, what, NULL);\n\n\tif (dialog && !dialog->outgoing_invite) {\n                if (dialog->delayed_invite)\n\t\t\tsipe_incoming_cancel_delayed_invite(sipe_private,\n\t\t\t\t\t\t\t    dialog);\n\t\tsipe_im_process_queue(sipe_private, session);\n\t} else if (!dialog || !dialog->outgoing_invite) {\n\t\t/* Need to send the INVITE to get the outgoing dialog setup */\n\t\tsipe_im_invite(sipe_private, session, uri, what, NULL, NULL, FALSE);\n\t}\n\n\tg_free(uri);\n}\n\nvoid sipe_core_im_close(struct sipe_core_public *sipe_public,\n\t\t\tconst gchar *who)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\n\tSIPE_DEBUG_INFO(\"sipe_core_im_close: conversation with %s closed\", who);\n\tsipe_session_close(sipe_private,\n\t\t\t   sipe_session_find_im(sipe_private, who));\n}\n\nvoid sipe_im_cancel_dangling(struct sipe_core_private *sipe_private,\n\t\t\t     struct sip_session *session,\n\t\t\t     struct sip_dialog *dialog,\n\t\t\t     const gchar *with,\n\t\t\t     unconfirmed_callback callback)\n{\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_im_cancel_dangling: assuming dangling IM session, dropping it.\");\n\tsip_transport_bye(sipe_private, dialog);\n\n\t(*callback)(sipe_private, session, dialog->callid, with);\n\n\t/* We might not get a valid reply to our BYE,\n\t   so make sure the dialog is removed for sure. */\n\tsipe_dialog_remove(session, with);\n\t/* dialog is no longer valid */\n}\n\nvoid sipe_im_topic(struct sipe_core_private *sipe_private,\n\t\t   struct sip_session *session,\n\t\t   const gchar *topic)\n{\n\tg_free(session->subject);\n\tsession->subject = g_strdup(topic);\n\tsipe_backend_im_topic(SIPE_CORE_PUBLIC, session->with, topic);\n}\n\nvoid process_incoming_info_conversation(struct sipe_core_private *sipe_private,\n\t\t\t\t\tstruct sipmsg *msg)\n{\n\tsipe_xml *xml = sipe_xml_parse(msg->body, msg->bodylen);\n\tconst gchar *from = NULL;\n\tgchar *subject = NULL;\n\n\n\tif (!xml)\n\t\treturn;\n\n\tif (sipe_strequal(sipe_xml_name(xml), \"ConversationInfo\")) {\n\t\tconst sipe_xml *node = sipe_xml_child(xml, \"From\");\n\t\tif (node)\n\t\t\tfrom = sipe_xml_attribute(node, \"uri\");\n\n\t\tnode = sipe_xml_child(xml, \"Subject\");\n\t\tif (node)\n\t\t\tsubject = sipe_xml_data(node);\n\t}\n\n\tif (from && subject) {\n\t\tstruct sip_session *session;\n\t\tsession = sipe_session_find_im(sipe_private, from);\n\n\t\tif (session)\n\t\t\tsipe_im_topic(sipe_private, session, subject);\n\t}\n\n\tg_free(subject);\n\tsipe_xml_free(xml);\n\n\tsip_transport_response(sipe_private, msg, 200, \"OK\", NULL);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-im.h",
    "content": "/**\n * @file sipe-im.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sip_dialog;\nstruct sip_session;\nstruct sipe_core_private;\n\n#ifdef HAVE_GMIME\n/* pls. don't add multipart/related - it's not used in IM modality */\n#define SDP_ACCEPT_TYPES  \"text/plain text/html image/gif multipart/alternative application/im-iscomposing+xml application/ms-imdn+xml text/x-msmsgsinvite\"\n#else\n/* this is a rediculous hack as Pidgin's MIME implementastion doesn't support (or have bug) in multipart/alternative */\n/* OCS/OC won't use multipart/related so we don't advertase it */\n#define SDP_ACCEPT_TYPES  \"text/plain text/html image/gif application/im-iscomposing+xml application/ms-imdn+xml text/x-msmsgsinvite\"\n#endif\n\n/**\n * Send invitation and initial message to IM session\n *\n * @param sipe_private SIPE core private data\n * @param session      session for the IM conversation(s)\n * @param who          URI of the invitee\n * @param msg_body     message body or NULL\n * @param content_type message body MIME type\n * @param referred_by  value for Referred-By or NULL\n * @param is_triggered triggered invite or not\n */\nvoid sipe_im_invite(struct sipe_core_private *sipe_private,\n\t\t    struct sip_session *session,\n\t\t    const gchar *who,\n\t\t    const gchar *msg_body,\n\t\t    const gchar *content_type,\n\t\t    const gchar *referred_by,\n\t\t    const gboolean is_triggered);\n\n/**\n * Process queue IM messages\n *\n * @param sipe_private SIPE core private data\n * @param session      session for the IM conversation(s)\n */\nvoid sipe_im_process_queue(struct sipe_core_private *sipe_private,\n\t\t\t   struct sip_session *session);\n\n/**\n * Cancel unconfirmed IM messages\n *\n * @param sipe_private SIPE core private data\n * @param session      session for the IM conversation(s)\n * @param callid       Call ID of the conversation\n * @param with         URI of the remote party\n */\nvoid sipe_im_cancel_unconfirmed(struct sipe_core_private *sipe_private,\n\t\t\t\tstruct sip_session *session,\n\t\t\t\tconst gchar *callid,\n\t\t\t\tconst gchar *with);\n\n/**\n * Re-enqueue unconfirmed IM messages\n *\n * @param sipe_private SIPE core private data\n * @param session      session for the IM conversation(s)\n * @param callid       Call ID of the conversation\n * @param with         URI of the remote party\n */\nvoid sipe_im_reenqueue_unconfirmed(struct sipe_core_private *sipe_private,\n\t\t\t\t   struct sip_session *session,\n\t\t\t\t   const gchar *callid,\n\t\t\t\t   const gchar *with);\n\ntypedef void (*unconfirmed_callback)(struct sipe_core_private *sipe_private,\n\t\t\t\t     struct sip_session *session,\n\t\t\t\t     const gchar *callid,\n\t\t\t\t     const gchar *with);\n\n/**\n * Close dangling IM session\n *\n * @param sipe_private (in) SIPE core data.\n * @param session      (in) pointer to session\n * @param dialog       (in) pointer to dialog\n * @param with         (in) URI of dialog partner\n * @param callback     (in) callback for unconfirmed message\n */\nvoid sipe_im_cancel_dangling(struct sipe_core_private *sipe_private,\n\t\t\t     struct sip_session *session,\n\t\t\t     struct sip_dialog *dialog,\n\t\t\t     const gchar *with,\n\t\t\t     unconfirmed_callback callback);\n\n/**\n * Sets a topic for IM conversation\n *\n * @param sipe_private (in) SIPE core data\n * @param session      (in) pointer to session\n * @param topic        (in) string describing conversation topic\n */\nvoid sipe_im_topic(struct sipe_core_private *sipe_private,\n\t\t   struct sip_session *session,\n\t\t   const gchar *topic);\n\n/**\n * Processes INFO message with application/xml+conversationinfo content type\n *\n * @param sipe_private (in) SIPE core data\n * @param msg          (in) SIP INFO message\n */\nvoid process_incoming_info_conversation(struct sipe_core_private *sipe_private,\n\t\t\t\t\tstruct sipmsg *msg);\n"
  },
  {
    "path": "src/core/sipe-incoming.c",
    "content": "/**\n * @file sipe-incoming.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipmsg.h\"\n#include \"sip-csta.h\"\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-chat.h\"\n#include \"sipe-conf.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-appshare.h\"\n#include \"sipe-dialog.h\"\n#include \"sipe-ft.h\"\n#include \"sipe-ft-lync.h\"\n#include \"sipe-groupchat.h\"\n#include \"sipe-im.h\"\n#include \"sipe-incoming.h\"\n#include \"sipe-media.h\"\n#include \"sipe-mime.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-schedule.h\"\n#include \"sipe-session.h\"\n#include \"sipe-user.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n\nvoid process_incoming_bye(struct sipe_core_private *sipe_private,\n\t\t\t  struct sipmsg *msg)\n{\n\tconst gchar *callid = sipmsg_find_call_id_header(msg);\n\tgchar *from = sipmsg_parse_from_address(msg);\n\tstruct sip_session *session;\n\tstruct sip_dialog *dialog;\n\n#ifdef HAVE_VV\n\tstruct sipe_media_call_private *call_private =\n\t\t\tg_hash_table_lookup(sipe_private->media_calls, callid);\n\tif (is_media_session_msg(call_private, msg)) {\n\t\t// BYE ends a media call\n\t\tsipe_media_hangup(call_private);\n\t}\n#endif\n\n\t/* collect dialog identification\n\t * we need callid, ourtag and theirtag to unambiguously identify dialog\n\t */\n\t/* take data before 'msg' will be modified by sip_transport_response */\n\tdialog = g_new0(struct sip_dialog, 1);\n\tdialog->callid = g_strdup(callid);\n\tdialog->cseq = sipmsg_parse_cseq(msg);\n\tdialog->with = g_strdup(from);\n\tsipe_dialog_parse(dialog, msg, FALSE);\n\n\tsip_transport_response(sipe_private, msg, 200, \"OK\", NULL);\n\n\tsession = sipe_session_find_chat_or_im(sipe_private, callid, from);\n\tif (!session) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_incoming_bye: couldn't find session. Ignoring\");\n\t\tsipe_dialog_free(dialog);\n\t\tg_free(from);\n\t\treturn;\n\t}\n\n\tSIPE_DEBUG_INFO(\"process_incoming_bye: session found (chat ID %s)\",\n\t\t\t(session->chat_session && session->chat_session->id) ?\n\t\t\tsession->chat_session->id : \"<NO CHAT>\");\n\n\tif (session->chat_session &&\n\t    (session->chat_session->type == SIPE_CHAT_TYPE_MULTIPARTY) &&\n\t    session->chat_session->id &&\n\t    !g_ascii_strcasecmp(from, session->chat_session->id))\n\t\tsipe_chat_set_roster_manager(session, NULL);\n\n\tsipe_im_cancel_unconfirmed(sipe_private, session, callid, from);\n\n\t/* This what BYE is essentially for - terminating dialog */\n\tsipe_dialog_remove_3(session, dialog);\n\tsipe_dialog_free(dialog);\n\tif (session->chat_session) {\n\t\tif ((session->chat_session->type == SIPE_CHAT_TYPE_CONFERENCE) &&\n\t\t    !g_ascii_strcasecmp(from, session->im_mcu_uri)) {\n\t\t\tSIPE_DEBUG_INFO(\"process_incoming_bye: disconnected from conference %s\",\n\t\t\t\t\tsession->im_mcu_uri);\n\t\t\tsipe_conf_immcu_closed(sipe_private, session);\n\t\t} else if (session->chat_session->type == SIPE_CHAT_TYPE_MULTIPARTY) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_incoming_bye: disconnected from multiparty chat\");\n\t\t\tsipe_backend_chat_remove(session->chat_session->backend,\n\t\t\t\t\t\t from);\n\t\t}\n\t}\n\n\tg_free(from);\n}\n\nvoid process_incoming_cancel(struct sipe_core_private *sipe_private,\n\t\t\t     struct sipmsg *msg)\n{\n\tconst gchar *callid = sipmsg_find_call_id_header(msg);\n\n#ifdef HAVE_VV\n\tstruct sipe_media_call_private *call_private =\n\t\t\tg_hash_table_lookup(sipe_private->media_calls, callid);\n\tif (is_media_session_msg(call_private, msg)) {\n\t\tprocess_incoming_cancel_call(call_private, msg);\n\t\treturn;\n\t}\n#endif\n\n\tif (!sipe_session_find_chat_by_callid(sipe_private, callid))\n\t\tsipe_conf_cancel_unaccepted(sipe_private, msg);\n}\n\nvoid process_incoming_info(struct sipe_core_private *sipe_private,\n\t\t\t   struct sipmsg *msg)\n{\n\tconst gchar *contenttype = sipmsg_find_content_type_header(msg);\n\tconst gchar *callid = sipmsg_find_call_id_header(msg);\n\tgchar *from;\n\tstruct sip_session *session;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"process_incoming_info\");\n\n\t/* Call Control protocol */\n\tif (g_str_has_prefix(contenttype, \"application/csta+xml\"))\n\t{\n\t\tprocess_incoming_info_csta(sipe_private, msg);\n\t\treturn;\n\t}\n\telse if (g_str_has_prefix(contenttype, \"application/xml+conversationinfo\"))\n\t{\n\t\tprocess_incoming_info_conversation(sipe_private, msg);\n\t\treturn;\n\t}\n#ifdef HAVE_XDATA\n\telse if (g_str_has_prefix(contenttype, \"application/ms-filetransfer+xml\"))\n\t{\n\t\tprocess_incoming_info_ft_lync(sipe_private, msg);\n\t\treturn;\n\t}\n#endif\n\n\tfrom = sipmsg_parse_from_address(msg);\n\tsession = sipe_session_find_chat_or_im(sipe_private, callid, from);\n\tif (!session) {\n\t\tg_free(from);\n\t\treturn;\n\t}\n\n\t/* Group Chat uses text/plain */\n\tif (session->is_groupchat) {\n\t\tprocess_incoming_info_groupchat(sipe_private, msg, session);\n\t\tg_free(from);\n\t\treturn;\n\t}\n\n\tif (g_str_has_prefix(contenttype, \"application/x-ms-mim\"))\n\t{\n\t\tsipe_xml *xn_action           = sipe_xml_parse(msg->body, msg->bodylen);\n\t\tconst sipe_xml *xn_request_rm = sipe_xml_child(xn_action, \"RequestRM\");\n\t\tconst sipe_xml *xn_set_rm     = sipe_xml_child(xn_action, \"SetRM\");\n\n\t\tsipmsg_add_header(msg, \"Content-Type\", \"application/x-ms-mim\");\n\n\t\tif (xn_request_rm) {\n\t\t\t//const char *rm = sipe_xml_attribute(xn_request_rm, \"uri\");\n\t\t\tint bid = sipe_xml_int_attribute(xn_request_rm, \"bid\", 0);\n\t\t\tgchar *body = g_strdup_printf(\n\t\t\t\t\"<?xml version=\\\"1.0\\\"?>\\r\\n\"\n\t\t\t\t\"<action xmlns=\\\"http://schemas.microsoft.com/sip/multiparty/\\\">\"\n\t\t\t\t\"<RequestRMResponse uri=\\\"sip:%s\\\" allow=\\\"%s\\\"/></action>\\r\\n\",\n\t\t\t\tsipe_private->username,\n\t\t\t\tsession->bid < bid ? \"true\" : \"false\");\n\t\t\tsip_transport_response(sipe_private, msg, 200, \"OK\", body);\n\t\t\tg_free(body);\n\t\t} else if (xn_set_rm) {\n\t\t\tgchar *body;\n\n\t\t\tsipe_chat_set_roster_manager(session,\n\t\t\t\t\t\t     sipe_xml_attribute(xn_set_rm, \"uri\"));\n\n\t\t\tbody = g_strdup_printf(\n\t\t\t\t\"<?xml version=\\\"1.0\\\"?>\\r\\n\"\n\t\t\t\t\"<action xmlns=\\\"http://schemas.microsoft.com/sip/multiparty/\\\">\"\n\t\t\t\t\"<SetRMResponse uri=\\\"sip:%s\\\"/></action>\\r\\n\",\n\t\t\t\tsipe_private->username);\n\t\t\tsip_transport_response(sipe_private, msg, 200, \"OK\", body);\n\t\t\tg_free(body);\n\t\t}\n\t\tsipe_xml_free(xn_action);\n\n\t}\n\telse\n\t{\n\t\t/* looks like purple lacks typing notification for chat */\n\t\tif (!session->chat_session) {\n\t\t\tsipe_xml *xn_keyboard_activity  = sipe_xml_parse(msg->body, msg->bodylen);\n\t\t\tconst char *status = sipe_xml_attribute(sipe_xml_child(xn_keyboard_activity, \"status\"),\n\t\t\t\t\t\t\t\t\"status\");\n\t\t\tif (sipe_strequal(status, \"type\")) {\n\t\t\t\tsipe_backend_user_feedback_typing(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t  from);\n\t\t\t} else if (sipe_strequal(status, \"idle\")) {\n\t\t\t\tsipe_backend_user_feedback_typing_stop(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t       from);\n\t\t\t}\n\t\t\tsipe_xml_free(xn_keyboard_activity);\n\t\t}\n\n\t\tsip_transport_response(sipe_private, msg, 200, \"OK\", NULL);\n\t}\n\tg_free(from);\n}\n\nstatic gboolean sipe_process_incoming_x_msmsgsinvite(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t     struct sip_dialog *dialog,\n\t\t\t\t\t\t     GSList *parsed_body)\n{\n\tgboolean found = FALSE;\n\n\tif (parsed_body) {\n\t\tconst gchar *invitation_command = sipe_utils_nameval_find(parsed_body, \"Invitation-Command\");\n\n\t\tif (sipe_strequal(invitation_command, \"INVITE\")) {\n\t\t\tsipe_ft_incoming_transfer(sipe_private, dialog, parsed_body);\n\t\t\tfound = TRUE;\n\t\t} else if (sipe_strequal(invitation_command, \"CANCEL\")) {\n\t\t\tsipe_ft_incoming_cancel(dialog, parsed_body);\n\t\t\tfound = TRUE;\n\t\t} else if (sipe_strequal(invitation_command, \"ACCEPT\")) {\n\t\t\tsipe_ft_incoming_accept(dialog, parsed_body);\n\t\t\tfound = TRUE;\n\t\t}\n\t}\n\treturn found;\n}\n\n#ifdef HAVE_VV\nstatic void sipe_invite_mime_cb(gpointer user_data, const GSList *fields,\n\t\t\t\tconst gchar *body, gsize length)\n{\n\tstruct sipmsg *msg = user_data;\n\tconst gchar *type;\n\tgchar *body_lcase;\n\n\tif (g_str_has_prefix(sipmsg_find_content_type_header(msg),\n\t\t\t     \"application/sdp\")) {\n\t\t/* We have already found suitable alternative and set message's body\n\t\t * and Content-Type accordingly. */\n\t\treturn;\n\t}\n\n\ttype = sipe_utils_nameval_find(fields, \"Content-Type\");\n\n\tif (!body || !g_str_has_prefix(type, \"application/sdp\"))\n\t\treturn;\n\n\tbody_lcase = g_ascii_strdown(body, length);\n\n\tif (strstr(body_lcase, \" typ host\") || strstr(body_lcase, \" typ relay\") ||\n\t    strstr(body_lcase, \" typ srflx\") || strstr(body_lcase, \" typ prflx\")) {\n\t\t/* RFC 5245 SDP body */\n\t\tsipmsg_remove_header_now(msg, \"Content-Type\");\n\t\tsipmsg_add_header_now(msg, \"Content-Type\", type);\n\n\t\t/* Replace message body with chosen alternative, so we can continue to\n\t\t * process it as a normal single part message. */\n\t\tg_free(msg->body);\n\t\tmsg->body = g_strndup(body, length);\n\t\tmsg->bodylen = length;\n\t}\n\n\tg_free(body_lcase);\n}\n#endif\n\nstatic void send_invite_response(struct sipe_core_private *sipe_private,\n\t\t\t\t struct sipmsg *msg)\n{\n\tgchar *body = g_strdup_printf(\n\t\t\"v=0\\r\\n\"\n\t\t\"o=- 0 0 IN %s %s\\r\\n\"\n\t\t\"s=session\\r\\n\"\n\t\t\"c=IN %s %s\\r\\n\"\n\t\t\"t=0 0\\r\\n\"\n\t\t\"m=%s %d sip sip:%s\\r\\n\"\n\t\t\"a=accept-types:\" SDP_ACCEPT_TYPES \"\\r\\n\",\n\t\tsip_transport_sdp_address_marker(sipe_private),\n\t\tsip_transport_ip_address(sipe_private),\n\t\tsip_transport_sdp_address_marker(sipe_private),\n\t\tsip_transport_ip_address(sipe_private),\n\t\tSIPE_CORE_PRIVATE_FLAG_IS(OCS2007) ? \"message\" : \"x-ms-message\",\n\t\tsip_transport_port(sipe_private),\n\t\tsipe_private->username);\n\tsipmsg_add_header(msg, \"Content-Type\", \"application/sdp\");\n\tsip_transport_response(sipe_private, msg, 200, \"OK\", body);\n\tg_free(body);\n}\n\nstruct sipe_delayed_invite {\n\tgchar *action;\n\tstruct sipmsg *msg;\n};\n\nstatic void delayed_invite_destroy(gpointer data)\n{\n\tstruct sipe_delayed_invite *delayed_invite = data;\n\tsipmsg_free(delayed_invite->msg);\n\tg_free(delayed_invite->action);\n\tg_free(delayed_invite);\n}\n\nstatic void delayed_invite_timeout(struct sipe_core_private *sipe_private,\n\t\t\t\t   gpointer data)\n{\n\tstruct sipe_delayed_invite *delayed_invite = data;\n\tsend_invite_response(sipe_private, delayed_invite->msg);\n}\n\nstatic void delayed_invite_response(struct sipe_core_private *sipe_private,\n\t\t\t\t    struct sipmsg *msg,\n\t\t\t\t    const gchar *callid)\n{\n\tstruct sipe_delayed_invite *delayed_invite = g_new0(struct sipe_delayed_invite, 1);\n\n\tdelayed_invite->action = g_strdup_printf(\"<delayed-invite-%s>\", callid);\n\tdelayed_invite->msg    = sipmsg_copy(msg);\n\tsipe_schedule_seconds(sipe_private,\n\t\t\t      delayed_invite->action,\n\t\t\t      delayed_invite,\n\t\t\t      10,\n\t\t\t      delayed_invite_timeout,\n\t\t\t      delayed_invite_destroy);\n}\n\nvoid sipe_incoming_cancel_delayed_invite(struct sipe_core_private *sipe_private,\n\t\t\t\t\t struct sip_dialog *dialog)\n{\n\tstruct sipe_delayed_invite *delayed_invite = dialog->delayed_invite;\n\tdialog->delayed_invite = NULL;\n\tsend_invite_response(sipe_private, delayed_invite->msg);\n\tsipe_schedule_cancel(sipe_private, delayed_invite->action);\n}\n\nvoid process_incoming_invite(struct sipe_core_private *sipe_private,\n\t\t\t     struct sipmsg *msg)\n{\n\tgboolean is_multiparty = FALSE;\n\tgboolean was_multiparty = TRUE;\n\tgboolean just_joined = FALSE;\n\tgchar *from;\n\tconst gchar *callid         = sipmsg_find_call_id_header(msg);\n\tconst gchar *roster_manager = sipmsg_find_header(msg, \"Roster-Manager\");\n\tconst gchar *end_points_hdr = sipmsg_find_header(msg, \"EndPoints\");\n\tconst gchar *trig_invite    = sipmsg_find_header(msg, \"TriggeredInvite\");\n\tconst gchar *content_type   = sipmsg_find_content_type_header(msg);\n\tconst gchar *subject        = sipmsg_find_header(msg, \"Subject\");\n\tGSList *end_points = NULL;\n\tstruct sip_session *session;\n\tstruct sip_dialog *dialog;\n\tconst gchar *ms_text_format;\n\tgboolean dont_delay = FALSE;\n\n#ifdef HAVE_VV\n\tif (g_str_has_prefix(content_type, \"multipart/alternative\")) {\n\t\tsipe_mime_parts_foreach(content_type, msg->body, sipe_invite_mime_cb, msg);\n\t\t/* Reload Content-Type to get type of the selected message part */\n\t\tcontent_type = sipmsg_find_content_type_header(msg);\n\t}\n#endif\n\n\tif (g_str_has_prefix(content_type, \"multipart/mixed\")) {\n\t\tif (sipe_mime_parts_contain(content_type, msg->body,\n\t\t\t\t\t    \"application/ms-filetransfer+xml\")) {\n\t\t\t/* Lync 2010 file transfer */\n#ifdef HAVE_XDATA\n\t\t\tprocess_incoming_invite_ft_lync(sipe_private, msg);\n#else\n\t\t\tsip_transport_response(sipe_private, msg,\n\t\t\t\t\t       488, \"Not Acceptable Here\", NULL);\n#endif\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/* Invitation to join conference */\n\tif (g_str_has_prefix(content_type, \"application/ms-conf-invite+xml\")) {\n\t\tprocess_incoming_invite_conf(sipe_private, msg);\n\t\treturn;\n\t}\n\n#ifdef HAVE_VV\n\t/* Application sharing */\n\tif (sipe_strcase_equal(content_type, \"application/sdp\") && msg->body &&\n\t    strstr(msg->body, \"m=applicationsharing\") &&\n\t    sipe_strequal(sipmsg_find_cseq_header(msg), \"1 INVITE\")) {\n#ifdef HAVE_APPSHARE\n\t\tprocess_incoming_invite_appshare(sipe_private, msg);\n#else\n\t\tsip_transport_response(sipe_private, msg,\n\t\t\t\t       488, \"Not Acceptable Here\", NULL);\n#endif\n\t\treturn;\n\t}\n\n\t/* Invitation to audio call or file transfer */\n\tif (msg->body &&\n\t    (strstr(msg->body, \"m=audio\") || strstr(msg->body, \"m=data\") || strstr(msg->body, \"m=applicationsharing\"))) {\n\t\tprocess_incoming_invite_call(sipe_private, msg, msg->body);\n\t\treturn;\n\t}\n#endif\n\n\t/* Only accept text invitations */\n\tif (msg->body && !(strstr(msg->body, \"m=message\") || strstr(msg->body, \"m=x-ms-message\"))) {\n\t\tsip_transport_response(sipe_private, msg, 501, \"Not implemented\", NULL);\n\t\treturn;\n\t}\n\n\t// TODO There *must* be a better way to clean up the To header to add a tag...\n\tsipmsg_update_to_header_tag(msg);\n\n\tif (end_points_hdr) {\n\t\tend_points = sipmsg_parse_endpoints_header(end_points_hdr);\n\n\t\tif (g_slist_length(end_points) > 2) {\n\t\t\tis_multiparty = TRUE;\n\t\t}\n\t}\n\tif (trig_invite && !g_ascii_strcasecmp(trig_invite, \"TRUE\")) {\n\t\tis_multiparty = TRUE;\n\t}\n\n\t/* Multiparty session */\n\tsession = sipe_session_find_chat_by_callid(sipe_private, callid);\n\tif (is_multiparty) {\n\n\t\tif (session) {\n\t\t\tif (session->chat_session) {\n\t\t\t\t/* Update roster manager for existing multiparty session */\n\t\t\t\tif (roster_manager)\n\t\t\t\t\tsipe_chat_set_roster_manager(session, roster_manager);\n\n\t\t\t} else {\n\t\t\t\tgchar *chat_title = sipe_chat_get_name();\n\n\t\t\t\t/* Convert IM session to multiparty session */\n\t\t\t\tg_free(session->with);\n\t\t\t\tsession->with = NULL;\n\t\t\t\twas_multiparty = FALSE;\n\t\t\t\tsession->chat_session = sipe_chat_create_session(SIPE_CHAT_TYPE_MULTIPARTY,\n\t\t\t\t\t\t\t\t\t\t roster_manager,\n\t\t\t\t\t\t\t\t\t\t chat_title);\n\n\t\t\t\tg_free(chat_title);\n\t\t\t}\n\t\t} else {\n\t\t\t/* New multiparty session */\n\t\t\tsession = sipe_session_add_chat(sipe_private,\n\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\tTRUE,\n\t\t\t\t\t\t\troster_manager);\n\t\t}\n\n\t\t/* Create chat */\n\t\tif (!session->chat_session->backend) {\n\t\t\tgchar *self = sip_uri_self(sipe_private);\n\t\t\tsession->chat_session->backend = sipe_backend_chat_create(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\t\t  session->chat_session,\n\t\t\t\t\t\t\t\t\t\t  session->chat_session->title,\n\t\t\t\t\t\t\t\t\t\t  self);\n\t\t\tg_free(self);\n\t\t}\n\t}\n\n\t/* IM session */\n\tfrom = sipmsg_parse_from_address(msg);\n\tif (!session)\n\t\tsession = sipe_session_find_or_add_im(sipe_private, from);\n\n\t/* session is now initialized */\n\tg_free(session->callid);\n\tsession->callid = g_strdup(callid);\n\n\tif (is_multiparty && end_points) {\n\t\tgchar *to = sipmsg_parse_to_address(msg);\n\t\tGSList *entry = end_points;\n\t\twhile (entry) {\n\t\t\tstruct sipendpoint *end_point = entry->data;\n\t\t\tentry = entry->next;\n\n\t\t\tif (!g_ascii_strcasecmp(from, end_point->contact) ||\n\t\t\t    !g_ascii_strcasecmp(to,   end_point->contact))\n\t\t\t\tcontinue;\n\n\t\t\tdialog = sipe_dialog_find(session, end_point->contact);\n\t\t\tif (dialog) {\n\t\t\t\tg_free(dialog->theirepid);\n\t\t\t\tdialog->theirepid = end_point->epid;\n\t\t\t\tend_point->epid = NULL;\n\t\t\t} else {\n\t\t\t\tdialog = sipe_dialog_add(session);\n\n\t\t\t\tdialog->callid = g_strdup(session->callid);\n\t\t\t\tdialog->with = end_point->contact;\n\t\t\t\tend_point->contact = NULL;\n\t\t\t\tdialog->theirepid = end_point->epid;\n\t\t\t\tend_point->epid = NULL;\n\n\t\t\t\tjust_joined = TRUE;\n\n\t\t\t\t/* send triggered INVITE */\n\t\t\t\tsipe_im_invite(sipe_private, session, dialog->with, NULL, NULL, NULL, TRUE);\n\t\t\t}\n\t\t}\n\t\tg_free(to);\n\t}\n\n\tif (end_points) {\n\t\tGSList *entry = end_points;\n\t\twhile (entry) {\n\t\t\tstruct sipendpoint *end_point = entry->data;\n\t\t\tentry = entry->next;\n\t\t\tg_free(end_point->contact);\n\t\t\tg_free(end_point->epid);\n\t\t\tg_free(end_point);\n\t\t}\n\t\tg_slist_free(end_points);\n\t}\n\n\tdialog = sipe_dialog_find(session, from);\n\tif (dialog) {\n\t\tsipe_im_cancel_dangling(sipe_private, session, dialog, from,\n\t\t\t\t\tsipe_im_reenqueue_unconfirmed);\n\t\t/* dialog is no longer valid */\n\t} else {\n\t\tjust_joined = TRUE;\n\t}\n\n\tdialog = sipe_dialog_add(session);\n\tdialog->with = g_strdup(from);\n\tdialog->callid = g_strdup(session->callid);\n\tdialog->is_established = TRUE;\n\tsipe_dialog_parse(dialog, msg, FALSE);\n\n\tif (is_multiparty && !was_multiparty) {\n\t\t/* add current IM counterparty to chat */\n\t\tsipe_backend_chat_add(session->chat_session->backend,\n\t\t\t\t      sipe_dialog_first(session)->with,\n\t\t\t\t      FALSE);\n\t}\n\n\t/* add inviting party to chat */\n\tif (just_joined && session->chat_session) {\n\t\tsipe_backend_chat_add(session->chat_session->backend,\n\t\t\t\t      from,\n\t\t\t\t      TRUE);\n\t}\n\n\tif (!is_multiparty && subject)\n\t\tsipe_im_topic(sipe_private, session, subject);\n\n\t/* ms-text-format: text/plain; charset=UTF-8;msgr=WAAtAE0...DIADQAKAA0ACgA;ms-body=SGk= */\n\n\t/* This used only in 2005 official client, not 2007 or Reuters.\n\t   Disabled for most cases as interfering with audit of messages which only is applied to regular MESSAGEs.\n\t   Only enabled for 2005 multiparty chats as otherwise the first message got lost completely.\n\t*/\n\t/* also enabled for 2005 file transfer. Didn't work otherwise. */\n\tms_text_format = sipmsg_find_header(msg, \"ms-text-format\");\n\tif (is_multiparty ||\n\t    (ms_text_format && g_str_has_prefix(ms_text_format, \"text/x-msmsgsinvite\")) )\n\t{\n\t\tif (ms_text_format) {\n\t\t\tif (g_str_has_prefix(ms_text_format, \"text/x-msmsgsinvite\"))\n\t\t\t{\n\t\t\t\tdont_delay = TRUE;\n\t\t\t}\n\t\t\telse if (g_str_has_prefix(ms_text_format, \"text/plain\") ||\n\t\t\t\t g_str_has_prefix(ms_text_format, \"text/html\")  ||\n\t\t\t\t g_str_has_prefix(ms_text_format, \"text/rtf\"))\n\t\t\t{\n\t\t\t\t/* please do not optimize logic inside as this code may be re-enabled for other cases */\n\t\t\t\tgchar *html = get_html_message(ms_text_format, NULL);\n\t\t\t\tif (html) {\n\t\t\t\t\tif (is_multiparty) {\n\t\t\t\t\t\tsipe_backend_chat_message(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\t  session->chat_session->backend,\n\t\t\t\t\t\t\t\t\t  from,\n\t\t\t\t\t\t\t\t\t  0,\n\t\t\t\t\t\t\t\t\t  html);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsipe_backend_im_message(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\tfrom,\n\t\t\t\t\t\t\t\t\thtml);\n\t\t\t\t\t}\n\t\t\t\t\tg_free(html);\n\t\t\t\t\tsipmsg_add_header(msg, \"Supported\", \"ms-text-format\"); /* accepts received message */\n\t\t\t\t\tdont_delay = TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tg_free(from);\n\n\tsipmsg_add_header(msg, \"Supported\", \"com.microsoft.rtc-multiparty\");\n\n\tif (dont_delay || !SIPE_CORE_PRIVATE_FLAG_IS(MPOP)) {\n\t\tsend_invite_response(sipe_private, msg);\n\t} else {\n\t\tdelayed_invite_response(sipe_private, msg, session->callid);\n\t}\n}\n\nvoid process_incoming_message(struct sipe_core_private *sipe_private,\n\t\t\t      struct sipmsg *msg)\n{\n\tgchar *from;\n\tconst gchar *contenttype;\n\tgboolean found = FALSE;\n\n\tfrom = sipmsg_parse_from_address(msg);\n\n\tif (!from) return;\n\n\tSIPE_DEBUG_INFO(\"got message from %s: %s\", from, msg->body);\n\n\tcontenttype = sipmsg_find_content_type_header(msg);\n\tif (g_str_has_prefix(contenttype, \"text/plain\")            ||\n\t    g_str_has_prefix(contenttype, \"text/html\")             ||\n\t    g_str_has_prefix(contenttype, \"text/rtf\")              ||\n\t    g_str_has_prefix(contenttype, \"multipart/related\")     ||\n\t    g_str_has_prefix(contenttype, \"multipart/alternative\"))\n\t{\n\t\tconst gchar *callid = sipmsg_find_call_id_header(msg);\n\t\tgchar *html = get_html_message(contenttype, msg->body);\n\n\t\tstruct sip_session *session = sipe_session_find_chat_or_im(sipe_private,\n\t\t\t\t\t\t\t\t\t   callid,\n\t\t\t\t\t\t\t\t\t   from);\n\t\tif (session && session->chat_session) {\n\t\t\tif (session->chat_session->type == SIPE_CHAT_TYPE_CONFERENCE) { /* a conference */\n\t\t\t\tgchar *tmp = sipmsg_parse_address_from_header(msg, \"Ms-Sender\");\n\t\t\t\tgchar *sender = parse_from(tmp);\n\t\t\t\tg_free(tmp);\n\t\t\t\tsipe_backend_chat_message(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t  session->chat_session->backend,\n\t\t\t\t\t\t\t  sender,\n\t\t\t\t\t\t\t  0,\n\t\t\t\t\t\t\t  html);\n\t\t\t\tg_free(sender);\n\t\t\t} else { /* a multiparty chat */\n\t\t\t\tsipe_backend_chat_message(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t  session->chat_session->backend,\n\t\t\t\t\t\t\t  from,\n\t\t\t\t\t\t\t  0,\n\t\t\t\t\t\t\t  html);\n\t\t\t}\n\t\t} else {\n\t\t\tsipe_backend_im_message(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\tfrom,\n\t\t\t\t\t\thtml);\n\t\t}\n\t\tg_free(html);\n\t\tsip_transport_response(sipe_private, msg, 200, \"OK\", NULL);\n\t\tfound = TRUE;\n\n\t} else if (g_str_has_prefix(contenttype, \"application/im-iscomposing+xml\")) {\n\t\tsipe_xml *isc = sipe_xml_parse(msg->body, msg->bodylen);\n\t\tconst sipe_xml *state;\n\t\tgchar *statedata;\n\n\t\tif (!isc) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_incoming_message: can not parse iscomposing\");\n\t\t\tg_free(from);\n\t\t\treturn;\n\t\t}\n\n\t\tstate = sipe_xml_child(isc, \"state\");\n\n\t\tif (!state) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_incoming_message: no state found\");\n\t\t\tsipe_xml_free(isc);\n\t\t\tg_free(from);\n\t\t\treturn;\n\t\t}\n\n\t\tstatedata = sipe_xml_data(state);\n\t\tif (statedata) {\n\t\t\tif (strstr(statedata, \"active\")) {\n\t\t\t\tsipe_backend_user_feedback_typing(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t  from);\n\t\t\t} else {\n\t\t\t\tsipe_backend_user_feedback_typing_stop(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t       from);\n\t\t\t}\n\t\t\tg_free(statedata);\n\t\t}\n\t\tsipe_xml_free(isc);\n\t\tsip_transport_response(sipe_private, msg, 200, \"OK\", NULL);\n\t\tfound = TRUE;\n\t} else if (g_str_has_prefix(contenttype, \"text/x-msmsgsinvite\")) {\n\t\tconst gchar *callid = sipmsg_find_call_id_header(msg);\n\t\tstruct sip_session *session = sipe_session_find_chat_or_im(sipe_private,\n\t\t\t\t\t\t\t\t\t   callid,\n\t\t\t\t\t\t\t\t\t   from);\n\t\tif (session) {\n\t\t\tstruct sip_dialog *dialog = sipe_dialog_find(session, from);\n\t\t\tGSList *body = sipe_ft_parse_msg_body(msg->body);\n\t\t\tfound = sipe_process_incoming_x_msmsgsinvite(sipe_private, dialog, body);\n\t\t\tsipe_utils_nameval_free(body);\n\t\t\tif (found) {\n\t\t\t\tsip_transport_response(sipe_private, msg, 200, \"OK\", NULL);\n\t\t\t}\n\t\t} else {\n\t\t\tsip_transport_response(sipe_private, msg, 481,\n\t\t\t\t\t       \"Call Leg/Transaction Does Not Exist\", NULL);\n\t\t\tfound = TRUE;\n\t\t}\n\t}\n\tif (!found) {\n\t\tconst gchar *callid = sipmsg_find_call_id_header(msg);\n\t\tstruct sip_session *session = sipe_session_find_chat_or_im(sipe_private,\n\t\t\t\t\t\t\t\t\t   callid,\n\t\t\t\t\t\t\t\t\t   from);\n\t\tif (session) {\n\t\t\tgchar *errmsg = g_strdup_printf(_(\"Received a message with unrecognized contents from %s\"),\n\t\t\t\t\t\t\tfrom);\n\t\t\tsipe_user_present_error(sipe_private, session, errmsg);\n\t\t\tg_free(errmsg);\n\t\t}\n\n\t\tSIPE_DEBUG_INFO(\"got unknown mime-type '%s'\", contenttype);\n\t\tsip_transport_response(sipe_private, msg, 415, \"Unsupported media type\", NULL);\n\t}\n\tg_free(from);\n}\n\nvoid process_incoming_options(struct sipe_core_private *sipe_private,\n\t\t\t      struct sipmsg *msg)\n{\n\tgchar *body;\n\n\tsipmsg_add_header(msg, \"Allow\", \"INVITE, MESSAGE, INFO, SUBSCRIBE, OPTIONS, BYE, CANCEL, NOTIFY, ACK, REFER, BENOTIFY\");\n\tsipmsg_add_header(msg, \"Content-Type\", \"application/sdp\");\n\n\tbody = g_strdup_printf(\n\t\t\"v=0\\r\\n\"\n\t\t\"o=- 0 0 IN IP4 0.0.0.0\\r\\n\"\n\t\t\"s=session\\r\\n\"\n\t\t\"c=IN IP4 0.0.0.0\\r\\n\"\n\t\t\"t=0 0\\r\\n\"\n\t\t\"m=%s %d sip sip:%s\\r\\n\"\n\t\t\"a=accept-types:\" SDP_ACCEPT_TYPES \"\\r\\n\",\n\t\tSIPE_CORE_PRIVATE_FLAG_IS(OCS2007) ? \"message\" : \"x-ms-message\",\n\t\tsip_transport_port(sipe_private),\n\t\tsipe_private->username);\n\tsip_transport_response(sipe_private, msg, 200, \"OK\", body);\n\tg_free(body);\n}\n\nvoid process_incoming_refer(struct sipe_core_private *sipe_private,\n\t\t\t    struct sipmsg *msg)\n{\n\tgchar *self = sip_uri_self(sipe_private);\n\tconst gchar *callid = sipmsg_find_call_id_header(msg);\n\tgchar *from = sipmsg_parse_from_address(msg);\n\tgchar *refer_to = sipmsg_parse_address_from_header(msg, \"Refer-to\");\n\tgchar *referred_by = g_strdup(sipmsg_find_header(msg, \"Referred-By\"));\n\tstruct sip_session *session;\n\tstruct sip_dialog *dialog;\n\n\tsession = sipe_session_find_chat_by_callid(sipe_private, callid);\n\tdialog = sipe_dialog_find(session, from);\n\n\tif (!session || !dialog || !session->chat_session ||\n\t    (session->chat_session->type != SIPE_CHAT_TYPE_MULTIPARTY) ||\n\t    !session->chat_session->id ||\n\t    !sipe_strcase_equal(session->chat_session->id, self)) {\n\t\tsip_transport_response(sipe_private, msg, 500, \"Server Internal Error\", NULL);\n\t} else {\n\t\tsip_transport_response(sipe_private, msg, 202, \"Accepted\", NULL);\n\n\t\tsipe_im_invite(sipe_private, session, refer_to, NULL, NULL, referred_by, FALSE);\n\t}\n\n\tg_free(self);\n\tg_free(from);\n\tg_free(refer_to);\n\tg_free(referred_by);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-incoming.h",
    "content": "/**\n * @file sipe-incoming.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\nstruct sip_dialog;\nstruct sipmsg;\n\nvoid process_incoming_bye(struct sipe_core_private *sipe_private,\n\t\t\t  struct sipmsg *msg);\nvoid process_incoming_cancel(struct sipe_core_private *sipe_private,\n\t\t\t     struct sipmsg *msg);\nvoid process_incoming_info(struct sipe_core_private *sipe_private,\n\t\t\t   struct sipmsg *msg);\nvoid process_incoming_invite(struct sipe_core_private *sipe_private,\n\t\t\t     struct sipmsg *msg);\nvoid process_incoming_message(struct sipe_core_private *sipe_private,\n\t\t\t      struct sipmsg *msg);\nvoid process_incoming_options(struct sipe_core_private *sipe_private,\n\t\t\t      struct sipmsg *msg);\nvoid process_incoming_refer(struct sipe_core_private *sipe_private,\n\t\t\t    struct sipmsg *msg);\n\nvoid sipe_incoming_cancel_delayed_invite(struct sipe_core_private *sipe_private,\n\t\t\t\t\t struct sip_dialog *dialog);\n"
  },
  {
    "path": "src/core/sipe-lync-autodiscover.c",
    "content": "/**\n * @file sipe-lync-autodiscover.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2016-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n * Specification references:\n *\n *   - [MS-OCDISCWS]: https://msdn.microsoft.com/en-us/library/hh623245.aspx\n *   - Understanding Autodiscover in Lync Server 2013\n *                    https://technet.microsoft.com/en-us/library/jj945654.aspx\n */\n\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-http.h\"\n#include \"sipe-lync-autodiscover.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-svc.h\"\n#include \"sipe-webticket.h\"\n#include \"sipe-xml.h\"\n\n#define LYNC_AUTODISCOVER_ACCEPT_HEADER \\\n\t\"Accept: application/vnd.microsoft.rtc.autodiscover+xml;v=1\\r\\n\"\n\nstruct lync_autodiscover_request {\n\tsipe_lync_autodiscover_callback *cb;\n\tgpointer cb_data;\n\tgpointer id;                       /* != NULL for active request */\n\tstruct sipe_http_request *request;\n\tstruct sipe_svc_session *session;\n\tconst gchar *protocol;\n\tconst gchar **method;\n\tgchar *uri;\n\tgboolean is_pending;\n};\n\nstruct sipe_lync_autodiscover {\n\tGSList *pending_requests;\n};\n\n/* Use \"lar\" inside the code fragment */\n#define FOR_ALL_REQUESTS_WITH_SAME_ID(code) \\\n\t{                                                                   \\\n\t\tGSList *entry = sipe_private->lync_autodiscover->pending_requests; \\\n\t\twhile (entry) {                                                    \\\n\t\t\tstruct lync_autodiscover_request *lar = entry->data;       \\\n\t\t\tentry = entry->next;                                       \\\n\t\t\tif (lar->id == id) {                                       \\\n\t\t\t\tcode;                                              \\\n\t\t\t}                                                          \\\n\t\t}                                                                  \\\n        }\n\nstatic void sipe_lync_autodiscover_request_free(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\tstruct lync_autodiscover_request *request)\n{\n\tstruct sipe_lync_autodiscover *sla = sipe_private->lync_autodiscover;\n\n\tsla->pending_requests = g_slist_remove(sla->pending_requests, request);\n\n\tif (request->request)\n\t\tsipe_http_request_cancel(request->request);\n\tif (request->cb)\n\t\t/* Callback: aborted */\n\t\t(*request->cb)(sipe_private, NULL, request->cb_data);\n\tsipe_svc_session_close(request->session);\n\tg_free(request->uri);\n\tg_free(request);\n}\n\nstatic void sipe_lync_autodiscover_cb(struct sipe_core_private *sipe_private,\n\t\t\t\t      guint status,\n\t\t\t\t      GSList *headers,\n\t\t\t\t      const gchar *body,\n\t\t\t\t      gpointer callback_data);\nstatic void lync_request(struct sipe_core_private *sipe_private,\n\t\t\t struct lync_autodiscover_request *request,\n\t\t\t const gchar *uri,\n\t\t\t const gchar *headers)\n{\n\trequest->request = sipe_http_request_get(sipe_private,\n\t\t\t\t\t\t uri,\n\t\t\t\t\t\t headers ? headers : LYNC_AUTODISCOVER_ACCEPT_HEADER,\n\t\t\t\t\t\t sipe_lync_autodiscover_cb,\n\t\t\t\t\t\t request);\n\n\tif (request->request)\n\t\tsipe_http_request_ready(request->request);\n}\n\nstatic GSList *sipe_lync_autodiscover_add(GSList *servers,\n\t\t\t\t\t  const sipe_xml *node,\n\t\t\t\t\t  const gchar *name)\n{\n\tconst sipe_xml *child = sipe_xml_child(node, name);\n\tconst gchar *fqdn = sipe_xml_attribute(child, \"fqdn\");\n\tguint port = sipe_xml_int_attribute(child, \"port\", 0);\n\n\t/* Add new entry to head of list */\n\tif (fqdn && (port != 0)) {\n\t\tstruct sipe_lync_autodiscover_data *lync_data = g_new0(struct sipe_lync_autodiscover_data, 1);\n\t\tlync_data->server = g_strdup(fqdn);\n\t\tlync_data->port   = port;\n\t\tservers = g_slist_prepend(servers, lync_data);\n\t}\n\n\treturn(servers);\n}\n\nGSList *sipe_lync_autodiscover_pop(GSList *servers)\n{\n\tif (servers) {\n\t\tstruct sipe_lync_autodiscover_data *lync_data = servers->data;\n\t\tservers = g_slist_remove(servers, lync_data);\n\n\t\tif (lync_data) {\n\t\t\tg_free((gchar *) lync_data->server);\n\t\t\tg_free(lync_data);\n\t\t}\n\t}\n\n\treturn(servers);\n}\n\nstatic void sipe_lync_autodiscover_queue_request(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t struct lync_autodiscover_request *request);\nstatic void sipe_lync_autodiscover_parse(struct sipe_core_private *sipe_private,\n\t\t\t\t\t struct lync_autodiscover_request *request,\n\t\t\t\t\t const gchar *body)\n{\n\tsipe_xml *xml = sipe_xml_parse(body, strlen(body));\n\tconst sipe_xml *node;\n\tgboolean next = TRUE;\n\n\t/* Root/Link: resources exposed by this server */\n\tfor (node = sipe_xml_child(xml, \"Root/Link\");\n\t     node;\n\t     node = sipe_xml_twin(node)) {\n\t\tconst gchar *token = sipe_xml_attribute(node, \"token\");\n\t\tconst gchar *uri = sipe_xml_attribute(node, \"href\");\n\n\t\tif (token && uri) {\n\t\t\t/* Redirect? */\n\t\t\tif (sipe_strcase_equal(token, \"Redirect\")) {\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_lync_autodiscover_parse: redirect to %s\",\n\t\t\t\t\t\turi);\n\t\t\t\tlync_request(sipe_private, request, uri, NULL);\n\t\t\t\tnext = FALSE;\n\t\t\t\tbreak;\n\n\t\t\t/* User? */\n\t\t\t} else if (sipe_strcase_equal(token, \"User\")) {\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_lync_autodiscover_parse: user %s\",\n\t\t\t\t\t\turi);\n\n\t\t\t\t/* remember URI for authentication failure */\n\t\t\t\trequest->uri = g_strdup(uri);\n\n\t\t\t\tlync_request(sipe_private, request, uri, NULL);\n\t\t\t\tnext = FALSE;\n\t\t\t\tbreak;\n\n\t\t\t} else\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_lync_autodiscover_parse: unknown token %s\",\n\t\t\t\t\t\ttoken);\n\t\t}\n\t}\n\n\t/* User/Link: topology information of the user’s home server */\n\tfor (node = sipe_xml_child(xml, \"User/Link\");\n\t     node;\n\t     node = sipe_xml_twin(node)) {\n\t\tconst gchar *token = sipe_xml_attribute(node, \"token\");\n\t\tconst gchar *uri = sipe_xml_attribute(node, \"href\");\n\n\t\tif (token && uri) {\n\t\t\t/* Redirect? */\n\t\t\tif (sipe_strcase_equal(token, \"Redirect\")) {\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_lync_autodiscover_parse: redirect to %s\",\n\t\t\t\t\t\turi);\n\t\t\t\tlync_request(sipe_private, request, uri, NULL);\n\t\t\t\tnext = FALSE;\n\t\t\t\tbreak;\n\t\t\t} else\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_lync_autodiscover_parse: unknown token %s\",\n\t\t\t\t\t\ttoken);\n\t\t}\n\t}\n\n\t/* if nothing else matched */\n\tif (next) {\n\t\tconst gchar *access_location = sipe_xml_attribute(xml, \"AccessLocation\");\n\n\t\t/* User: topology information of the user’s home server */\n\t\tif ((node = sipe_xml_child(xml, \"User\")) != NULL) {\n\t\t\tgpointer id = request->id;\n\n\t\t\t/* Active request? */\n\t\t\tif (id) {\n\t\t\t\tGSList *servers;\n\n\t\t\t\t/* List is reversed, i.e. internal will be tried first */\n\t\t\t\tservers = g_slist_prepend(NULL, NULL);\n\n\t\t\t\tif (!access_location ||\n\t\t\t\t    sipe_strcase_equal(access_location, \"external\")) {\n\t\t\t\t\tservers = sipe_lync_autodiscover_add(servers,\n\t\t\t\t\t\t\t\t\t     node,\n\t\t\t\t\t\t\t\t\t     \"SipClientExternalAccess\");\n\t\t\t\t}\n\n\t\t\t\tif (!access_location ||\n\t\t\t\t    sipe_strcase_equal(access_location, \"internal\")) {\n\t\t\t\t\tservers = sipe_lync_autodiscover_add(servers,\n\t\t\t\t\t\t\t\t\t     node,\n\t\t\t\t\t\t\t\t\t     \"SipClientInternalAccess\");\n\t\t\t\t}\n\n\t\t\t\t/* Callback takes ownership of servers list */\n\t\t\t\t(*request->cb)(sipe_private, servers, request->cb_data);\n\n\t\t\t\t/* We're done with requests for this callback */\n\t\t\t\tFOR_ALL_REQUESTS_WITH_SAME_ID( \\\n\t\t\t\t\tlar->cb = NULL;        \\\n\t\t\t\t\tlar->id = NULL         \\\n\t\t\t\t\t);\n\n\t\t\t}\n\n\t\t\t/* Request completed */\n\t\t\tnext = FALSE;\n\t\t\tsipe_lync_autodiscover_request_free(sipe_private, request);\n\t\t\t/* request is invalid */\n\t\t}\n\t}\n\n\tsipe_xml_free(xml);\n\n\tif (next)\n\t\tsipe_lync_autodiscover_queue_request(sipe_private, request);\n}\n\nstatic void sipe_lync_autodiscover_webticket(struct sipe_core_private *sipe_private,\n\t\t\t\t\t     SIPE_UNUSED_PARAMETER const gchar *base_uri,\n\t\t\t\t\t     const gchar *auth_uri,\n\t\t\t\t\t     const gchar *wsse_security,\n\t\t\t\t\t     SIPE_UNUSED_PARAMETER const gchar *failure_msg,\n\t\t\t\t\t     gpointer callback_data)\n{\n\tstruct lync_autodiscover_request *request = callback_data;\n\tgchar *saml;\n\n\t/* Extract SAML Assertion from WSSE Security XML text */\n\tif (wsse_security &&\n\t    ((saml = sipe_xml_extract_raw(wsse_security,\n\t\t\t\t\t  \"Assertion\",\n\t\t\t\t\t  TRUE)) != NULL)) {\n\t\tgchar *base64 = g_base64_encode((const guchar *) saml,\n\t\t\t\t\t\tstrlen(saml));\n\t\tgchar *headers = g_strdup_printf(LYNC_AUTODISCOVER_ACCEPT_HEADER\n\t\t\t\t\t\t \"X-MS-WebTicket: opaque=%s\\r\\n\",\n\t\t\t\t\t\t base64);\n\t\tg_free(base64);\n\n\t\tSIPE_DEBUG_INFO(\"sipe_lync_autodiscover_webticket: got ticket for Auth URI %s\",\n\t\t\t\tauth_uri);\n\t\tg_free(saml);\n\n\t\tlync_request(sipe_private, request, auth_uri, headers);\n\t\tg_free(headers);\n\n\t} else\n\t\tsipe_lync_autodiscover_queue_request(sipe_private, request);\n}\n\nstatic void sipe_lync_autodiscover_cb(struct sipe_core_private *sipe_private,\n\t\t\t\t      guint status,\n\t\t\t\t      GSList *headers,\n\t\t\t\t      const gchar *body,\n\t\t\t\t      gpointer callback_data)\n{\n\tstruct lync_autodiscover_request *request = callback_data;\n\tconst gchar *type = sipe_utils_nameval_find(headers, \"Content-Type\");\n\tgchar *uri = request->uri;\n\n\trequest->request = NULL;\n\trequest->uri     = NULL;\n\n\tswitch (status) {\n\tcase SIPE_HTTP_STATUS_OK:\n\t\t/* only accept Autodiscover XML responses */\n\t\tif (body && g_str_has_prefix(type, \"application/vnd.microsoft.rtc.autodiscover+xml\"))\n\t\t\tsipe_lync_autodiscover_parse(sipe_private, request, body);\n\t\telse\n\t\t\tsipe_lync_autodiscover_queue_request(sipe_private, request);\n\t\tbreak;\n\n\tcase SIPE_HTTP_STATUS_FAILED:\n\t\t{\n\t\t\tif (uri) {\n\t\t\t\t/* check for authentication failure */\n\t\t\t\tconst gchar *webticket_uri = sipe_utils_nameval_find(headers,\n\t\t\t\t\t\t\t\t\t\t     \"X-MS-WebTicketURL\");\n\n\t\t\t\tif (!(webticket_uri &&\n\t\t\t\t      sipe_webticket_request_with_auth(sipe_private,\n\t\t\t\t\t\t\t\t       request->session,\n\t\t\t\t\t\t\t\t       webticket_uri,\n\t\t\t\t\t\t\t\t       uri, /* Auth URI */\n\t\t\t\t\t\t\t\t       sipe_lync_autodiscover_webticket,\n\t\t\t\t\t\t\t\t       request)))\n\t\t\t\t\tsipe_lync_autodiscover_queue_request(sipe_private, request);\n\t\t\t} else\n\t\t\t\tsipe_lync_autodiscover_queue_request(sipe_private, request);\n\t        }\n\t\tbreak;\n\n\tcase SIPE_HTTP_STATUS_ABORTED:\n\t\t/* we are not allowed to generate new requests */\n\t\tsipe_lync_autodiscover_request_free(sipe_private, request);\n\t\tbreak;\n\n\tdefault:\n\t\tsipe_lync_autodiscover_queue_request(sipe_private, request);\n\t\tbreak;\n\t}\n\n\tg_free(uri);\n}\n\n/* Proceed to next method for request */\nstatic void sipe_lync_autodiscover_request(struct sipe_core_private *sipe_private,\n\t\t\t\t\t   struct lync_autodiscover_request *request)\n{\n\tgpointer id = request->id;\n\n\t/* Active request? */\n\tif (id) {\n\t\tstatic const gchar *methods[] = {\n\t\t\t\"%s://LyncDiscoverInternal.%s/?sipuri=%s\",\n\t\t\t\"%s://LyncDiscover.%s/?sipuri=%s\",\n\t\t\tNULL\n\t\t};\n\n\t\trequest->is_pending = TRUE;\n\n\t\tif (request->method)\n\t\t\trequest->method++;\n\t\telse\n\t\t\trequest->method = methods;\n\n\t\tif (*request->method) {\n\t\t\tgchar *uri = g_strdup_printf(*request->method,\n\t\t\t\t\t\t     request->protocol,\n\t\t\t\t\t\t     SIPE_CORE_PUBLIC->sip_domain,\n\t\t\t\t\t\t     sipe_private->username);\n\n\t\t\tSIPE_DEBUG_INFO(\"sipe_lync_autodiscover_request: trying '%s'\", uri);\n\n\t\t\tlync_request(sipe_private, request, uri, NULL);\n\t\t\tg_free(uri);\n\n\t\t} else {\n\t\t\tguint count = 0;\n\n\t\t\t/* Count entries with the same request ID */\n\t\t\tFOR_ALL_REQUESTS_WITH_SAME_ID( \\\n\t\t\t\tcount++;\t       \\\n\t\t\t);\n\n\t\t\tif (count == 1) {\n\t\t\t\t/*\n\t\t\t\t * This is the last pending request for this\n\t\t\t\t * ID, i.e. autodiscover has failed. Create\n\t\t\t\t * empty server list and return it.\n\t\t\t\t */\n\t\t\t\tGSList *servers = g_slist_prepend(NULL, NULL);\n\n\t\t\t\t/* All methods tried, indicate failure to caller */\n\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_lync_autodiscover_request: no more methods to try!\");\n\n\t\t\t\t/* Callback takes ownership of servers list */\n\t\t\t\t(*request->cb)(sipe_private, servers, request->cb_data);\n\t\t\t}\n\n\t\t\t/* Request completed */\n\t\t\trequest->cb = NULL;\n\t\t\tsipe_lync_autodiscover_request_free(sipe_private, request);\n\t\t\t/* request is invalid */\n\t\t}\n\t} else {\n\t\t/* Inactive request, callback already NULL */\n\t\tsipe_lync_autodiscover_request_free(sipe_private, request);\n\t\t/* request is invalid */\n\t}\n}\n\n/* Proceed to next method for all requests */\nstatic void sipe_lync_autodiscover_queue_request(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t struct lync_autodiscover_request *request)\n{\n\tgpointer id = request->id;\n\n\t/* This request is ready to proceed to next method */\n\trequest->is_pending = FALSE;\n\n\t/* Is any request for the same ID still pending? */\n\tFOR_ALL_REQUESTS_WITH_SAME_ID( \\\n\t\tif (lar->is_pending)   \\\n\t\t\treturn\t       \\\n\t);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_lync_autodiscover_queue_request: proceed in lockstep\");\n\n\t/* No, proceed to next method for all requests */\n\tFOR_ALL_REQUESTS_WITH_SAME_ID(\t\t\t     \\\n\t\tsipe_lync_autodiscover_request(sipe_private, \\\n\t\t\t\t\t       lar)\t     \\\n\t);\n}\n\nstatic gpointer sipe_lync_autodiscover_create(struct sipe_core_private *sipe_private,\n\t\t\t\t\t      gpointer id,\n\t\t\t\t\t      const gchar *protocol,\n\t\t\t\t\t      sipe_lync_autodiscover_callback *callback,\n\t\t\t\t\t      gpointer callback_data)\n{\n\tstruct sipe_lync_autodiscover *sla = sipe_private->lync_autodiscover;\n\tstruct lync_autodiscover_request *request = g_new0(struct lync_autodiscover_request, 1);\n\n\t/* use address of first request structure as unique ID */\n\tif (id == NULL)\n\t\tid = request;\n\n\trequest->protocol = protocol;\n\trequest->cb       = callback;\n\trequest->cb_data  = callback_data;\n\trequest->id       = id;\n\trequest->session  = sipe_svc_session_start();\n\n\tsla->pending_requests = g_slist_prepend(sla->pending_requests,\n\t\t\t\t\t\trequest);\n\n\tsipe_lync_autodiscover_request(sipe_private, request);\n\n\treturn(id);\n}\n\nvoid sipe_lync_autodiscover_start(struct sipe_core_private *sipe_private,\n\t\t\t\t  sipe_lync_autodiscover_callback *callback,\n\t\t\t\t  gpointer callback_data)\n{\n\tgpointer id = NULL;\n\n#define CREATE(protocol) \\\n\tid = sipe_lync_autodiscover_create(sipe_private,  \\\n\t\t\t\t\t   id,            \\\n\t\t\t\t\t   #protocol,     \\\n\t\t\t\t\t   callback,      \\\n\t\t\t\t\t   callback_data)\n\tCREATE(http);\n\tCREATE(https);\n}\n\nvoid sipe_lync_autodiscover_init(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_lync_autodiscover *sla = g_new0(struct sipe_lync_autodiscover, 1);\n\n\tsipe_private->lync_autodiscover = sla;\n}\n\nvoid sipe_lync_autodiscover_free(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_lync_autodiscover *sla = sipe_private->lync_autodiscover;\n\n\twhile (sla->pending_requests)\n\t\tsipe_lync_autodiscover_request_free(sipe_private,\n\t\t\t\t\t\t    sla->pending_requests->data);\n\n\tg_free(sla);\n\tsipe_private->lync_autodiscover = NULL;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-lync-autodiscover.h",
    "content": "/**\n * @file sipe-lync-autodiscover.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\n\n/* Lync data determined by autodiscover */\nstruct sipe_lync_autodiscover_data {\n    const gchar *server;\n    guint        port;\n};\n\n/**\n * Lync autodiscover callback\n *\n * @param sipe_private  SIPE core private data\n * @param servers       list with Lync autodiscover data\n * @param callback_data callback data\n *\n * servers will be @c NULL when request got aborted.\n * last entry in the list will be a @c NULL entry.\n */\ntypedef void (sipe_lync_autodiscover_callback)(struct sipe_core_private *sipe_private,\n\t\t\t\t\t       GSList *servers,\n\t\t\t\t\t       gpointer callback_data);\n\n/**\n * Free first callback data entry on the server list\n *\n * @param servers list given to callback (may be @c NULL)\n *\n * @return new list header\n */\nGSList *sipe_lync_autodiscover_pop(GSList *servers);\n\n/**\n * Trigger Lync autodiscover\n *\n * @param sipe_private  SIPE core private data\n * @param callback      callback function\n * @param callback_data callback data\n */\nvoid sipe_lync_autodiscover_start(struct sipe_core_private *sipe_private,\n\t\t\t\t  sipe_lync_autodiscover_callback *callback,\n\t\t\t\t  gpointer callback_data);\n\n/**\n * Initialize Lync autodiscover data\n *\n * @param sipe_private SIPE core private data\n */\nvoid sipe_lync_autodiscover_init(struct sipe_core_private *sipe_private);\n\n/**\n * Free Lync autodiscover data\n *\n * @param sipe_private SIPE core private data\n */\nvoid sipe_lync_autodiscover_free(struct sipe_core_private *sipe_private);\n"
  },
  {
    "path": "src/core/sipe-media.c",
    "content": "/**\n * @file sipe-media.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2019 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2010 Jakub Adam <jakub.adam@ktknet.cz>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipmsg.h\"\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sdpmsg.h\"\n#include \"sipe-conf.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-dialog.h\"\n#include \"sipe-media.h\"\n#include \"sipe-ocs2007.h\"\n#include \"sipe-session.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-schedule.h\"\n#include \"sipe-xml.h\"\n\n/* [MS-SDPEXT] 3.1.5.31.2 says a range size of 100 SHOULD be used for video and\n * some clients really demand this. */\n#define VIDEO_SSRC_COUNT 100\n\nstruct sipe_media_call_private {\n\tstruct sipe_media_call public;\n\n\t/* private part starts here */\n\tstruct sipe_core_private\t*sipe_private;\n\n\tstruct sip_session\t\t*session;\n\tstruct sip_session\t\t*conference_session;\n\n\tGSList\t\t\t\t*streams;\n\n\tstruct sipmsg\t\t\t*invitation;\n\tSipeIceVersion\t\t\t ice_version;\n\tgboolean\t\t\t encryption_compatible;\n\tgchar\t\t\t\t*extra_invite_section;\n\tgchar\t\t\t\t*invite_content_type;\n\n\tGSList\t\t\t\t*ssrc_ranges;\n\n\tstruct sdpmsg\t\t\t*smsg;\n\tGSList\t\t\t\t*failed_media;\n\tgchar \t\t\t\t*ringing_key;\n\tgchar \t\t\t\t*timeout_key;\n};\n#define SIPE_MEDIA_CALL         ((struct sipe_media_call *) call_private)\n#define SIPE_MEDIA_CALL_PRIVATE ((struct sipe_media_call_private *) call)\n\nstruct sipe_media_stream_private {\n\tstruct sipe_media_stream public;\n\n\tgchar *timeout_key;\n\n\tguchar *encryption_key;\n\tint encryption_key_id;\n\tgboolean remote_candidates_and_codecs_set;\n\tgboolean established;\n#ifdef HAVE_XDATA\n\tgboolean sdp_negotiation_concluded;\n\tgboolean writable;\n#endif\n\n\tGSList *extra_sdp;\n\n\tGQueue *write_queue;\n\tGQueue *async_reads;\n\tgssize read_pos;\n\n\t/* User data associated with the stream. */\n\tgpointer data;\n\tGDestroyNotify data_free_func;\n};\n#define SIPE_MEDIA_STREAM         ((struct sipe_media_stream *) stream_private)\n#define SIPE_MEDIA_STREAM_PRIVATE ((struct sipe_media_stream_private *) stream)\n\n#define SIPE_MEDIA_STREAM_CONNECTION_TIMEOUT_SECONDS 120\n#define SIPE_MEDIA_CALL_RINGING_TIMEOUT_SECONDS 60\n#define SIPE_MEDIA_CALL_TIMEOUT_SECONDS 120\n\nstruct async_read_data {\n\tguint8 *buffer;\n\tgssize len;\n\tsipe_media_stream_read_callback callback;\n};\n\nstatic void stream_schedule_cancel_timeout(struct sipe_media_call *call,\n\t\t\t\t\t   struct sipe_media_stream_private *stream_private);\n\nstatic void call_schedule_cancel_request_timeout(struct sipe_media_call *call);\nstatic void call_schedule_cancel_ringing_timeout(struct sipe_media_call *call);\n\nstatic void sipe_media_codec_list_free(GList *codecs)\n{\n\tfor (; codecs; codecs = g_list_delete_link(codecs, codecs))\n\t\tsipe_backend_codec_free(codecs->data);\n}\n\nstatic void sipe_media_candidate_list_free(GList *candidates)\n{\n\tfor (; candidates; candidates = g_list_delete_link(candidates, candidates))\n\t\tsipe_backend_candidate_free(candidates->data);\n}\n\nstatic void\nsipe_media_stream_free(struct sipe_media_stream_private *stream_private)\n{\n\tstruct sipe_media_call_private *call_private;\n\n\tcall_private = (struct sipe_media_call_private *)SIPE_MEDIA_STREAM->call;\n\n\tstream_schedule_cancel_timeout(SIPE_MEDIA_CALL, stream_private);\n\n\tsipe_media_stream_set_data(SIPE_MEDIA_STREAM, NULL, NULL);\n\n\tif (call_private) {\n\t\tcall_private->streams = g_slist_remove(call_private->streams,\n\t\t\t\t\t\t       stream_private);\n\n\t\tif (SIPE_MEDIA_STREAM->ssrc_range) {\n\t\t\tcall_private->ssrc_ranges =\n\t\t\t\tg_slist_remove(call_private->ssrc_ranges,\n\t\t\t\t\t       SIPE_MEDIA_STREAM->ssrc_range);\n\t\t\tg_free(SIPE_MEDIA_STREAM->ssrc_range);\n\t\t}\n\t}\n\n\tif (SIPE_MEDIA_STREAM->backend_private) {\n\t\tsipe_backend_media_stream_free(SIPE_MEDIA_STREAM->backend_private);\n\t}\n\tg_free(SIPE_MEDIA_STREAM->id);\n\tg_free(stream_private->encryption_key);\n\tg_queue_free_full(stream_private->write_queue,\n\t\t\t  (GDestroyNotify)g_byte_array_unref);\n\tg_queue_free_full(stream_private->async_reads, g_free);\n\tsipe_utils_nameval_free(stream_private->extra_sdp);\n\tg_free(stream_private);\n}\n\nstatic gboolean\ncall_private_equals(SIPE_UNUSED_PARAMETER const gchar *callid,\n\t\t    struct sipe_media_call_private *call_private1,\n\t\t    struct sipe_media_call_private *call_private2)\n{\n\treturn call_private1 == call_private2;\n}\n\nstatic void\nsipe_media_call_free(struct sipe_media_call_private *call_private)\n{\n\tif (call_private) {\n\t\tg_hash_table_foreach_remove(call_private->sipe_private->media_calls,\n\t\t\t\t\t    (GHRFunc) call_private_equals, call_private);\n\n\t\tcall_schedule_cancel_request_timeout(SIPE_MEDIA_CALL);\n\t\tcall_schedule_cancel_ringing_timeout(SIPE_MEDIA_CALL);\n\n\t\twhile (call_private->streams) {\n\t\t\tsipe_media_stream_free(call_private->streams->data);\n\t\t}\n\n\t\tsipe_backend_media_free(call_private->public.backend_private);\n\n\t\tif (call_private->session) {\n\t\t\tsipe_session_remove(call_private->sipe_private,\n\t\t\t\t\t    call_private->session);\n\t\t}\n\n\t\tif (call_private->invitation)\n\t\t\tsipmsg_free(call_private->invitation);\n\n\t\t// Frees any referenced extra invite data.\n\t\tsipe_media_add_extra_invite_section(SIPE_MEDIA_CALL, NULL, NULL);\n\n\t\tsipe_utils_slist_free_full(call_private->ssrc_ranges, g_free);\n\n\t\tsdpmsg_free(call_private->smsg);\n\t\tsipe_utils_slist_free_full(call_private->failed_media,\n\t\t\t\t  (GDestroyNotify)sdpmedia_free);\n\t\tg_free(SIPE_MEDIA_CALL->with);\n\t\tg_free(call_private);\n\t}\n}\n\nstatic gint\ncandidate_sort_cb(struct sdpcandidate *c1, struct sdpcandidate *c2)\n{\n\tint cmp = g_strcmp0(c1->foundation, c2->foundation);\n\tif (cmp == 0) {\n\t\tcmp = g_strcmp0(c1->username, c2->username);\n\t\tif (cmp == 0)\n\t\t\tcmp = c1->component - c2->component;\n\t}\n\n\treturn cmp;\n}\n\nstatic GSList *\nbackend_candidates_to_sdpcandidate(GList *candidates)\n{\n\tGSList *result = NULL;\n\tGList *i;\n\n\tfor (i = candidates; i; i = i->next) {\n\t\tstruct sipe_backend_candidate *candidate = i->data;\n\t\tstruct sdpcandidate *c;\n\n\t\tgchar *ip = sipe_backend_candidate_get_ip(candidate);\n\t\tgchar *base_ip = sipe_backend_candidate_get_base_ip(candidate);\n\t\tif (is_empty(ip) || strchr(ip, ':') ||\n\t\t    (base_ip && strchr(base_ip, ':'))) {\n\t\t\t/* Ignore IPv6 candidates. */\n\t\t\tg_free(ip);\n\t\t\tg_free(base_ip);\n\t\t\tcontinue;\n\t\t}\n\n\t\tc = g_new(struct sdpcandidate, 1);\n\t\tc->foundation = sipe_backend_candidate_get_foundation(candidate);\n\t\tc->component = sipe_backend_candidate_get_component_type(candidate);\n\t\tc->type = sipe_backend_candidate_get_type(candidate);\n\t\tc->protocol = sipe_backend_candidate_get_protocol(candidate);\n\t\tc->ip = ip;\n\t\tc->port = sipe_backend_candidate_get_port(candidate);\n\t\tc->base_ip = base_ip;\n\t\tc->base_port = sipe_backend_candidate_get_base_port(candidate);\n\t\tc->priority = sipe_backend_candidate_get_priority(candidate);\n\t\tc->username = sipe_backend_candidate_get_username(candidate);\n\t\tc->password = sipe_backend_candidate_get_password(candidate);\n\n\t\tresult = g_slist_insert_sorted(result, c,\n\t\t\t\t\t       (GCompareFunc)candidate_sort_cb);\n\t}\n\n\treturn result;\n}\n\nstatic void\nget_stream_ip_and_ports(GSList *candidates,\n\t\t\tgchar **ip, guint *rtp_port, guint *rtcp_port)\n{\n\tguint32 rtp_max_priority = 0;\n\tguint32 rtcp_max_priority = 0;\n\n\t*ip = 0;\n\t*rtp_port = 0;\n\t*rtcp_port = 0;\n\n\tfor (; candidates; candidates = candidates->next) {\n\t\tstruct sdpcandidate *candidate = candidates->data;\n\n\t\tif (candidate->component == SIPE_COMPONENT_RTP &&\n\t\t    candidate->priority > rtp_max_priority) {\n\t\t\trtp_max_priority = candidate->priority;\n\t\t\t*rtp_port = candidate->port;\n\n\t\t\tg_free(*ip);\n\t\t\t*ip = g_strdup(candidate->ip);\n\t\t} else if (candidate->component == SIPE_COMPONENT_RTCP &&\n\t\t\t   candidate->priority > rtcp_max_priority) {\n\t\t\trtcp_max_priority = candidate->priority;\n\t\t\t*rtcp_port = candidate->port;\n\t\t}\n\t}\n}\n\nstatic gint\nsdpcodec_compare(gconstpointer a, gconstpointer b)\n{\n\treturn ((const struct sdpcodec *)a)->id -\n\t       ((const struct sdpcodec *)b)->id;\n}\n\nstatic GList *\nremove_wrong_farstream_0_1_tcp_candidates(GList *candidates)\n{\n\tGList *i = candidates;\n\tGHashTable *foundation_to_candidate = g_hash_table_new_full(g_str_hash,\n\t\t\t\t\t\t\t\t    g_str_equal,\n\t\t\t\t\t\t\t\t    g_free,\n\t\t\t\t\t\t\t\t    NULL);\n\n\twhile (i) {\n\t\tGList *next = i->next;\n\t\tstruct sipe_backend_candidate *c1 = i->data;\n\n\t\tif (sipe_backend_candidate_get_protocol(c1) == SIPE_NETWORK_PROTOCOL_UDP) {\n\t\t\tgchar *foundation                 = sipe_backend_candidate_get_foundation(c1);\n\t\t\tstruct sipe_backend_candidate *c2 = g_hash_table_lookup(foundation_to_candidate,\n\t\t\t\t\t\t\t\t\t\tfoundation);\n\n\t\t\tif (c2) {\n\t\t\t\tg_free(foundation);\n\n\t\t\t\tif (sipe_backend_candidate_get_port(c1) ==\n\t\t\t\t    sipe_backend_candidate_get_port(c2) ||\n\t\t\t\t    (sipe_backend_candidate_get_type(c1) !=\n\t\t\t\t     SIPE_CANDIDATE_TYPE_HOST &&\n\t\t\t\t     sipe_backend_candidate_get_base_port(c1) ==\n\t\t\t\t     sipe_backend_candidate_get_base_port(c2))) {\n\t\t\t\t\t/*\n\t\t\t\t\t * We assume that RTP+RTCP UDP pairs\n\t\t\t\t\t * that share the same port are\n\t\t\t\t\t * actually mistagged TCP candidates.\n\t\t\t\t\t */\n\t\t\t\t\tcandidates = g_list_remove(candidates, c2);\n\t\t\t\t\tcandidates = g_list_delete_link(candidates, i);\n\t\t\t\t\tsipe_backend_candidate_free(c1);\n\t\t\t\t\tsipe_backend_candidate_free(c2);\n\t\t\t\t}\n\t\t\t} else\n\t\t\t\t/* hash table takes ownership of \"foundation\" */\n\t\t\t\tg_hash_table_insert(foundation_to_candidate, foundation, c1);\n\t\t}\n\n\t\ti = next;\n\t}\n\n\tg_hash_table_destroy(foundation_to_candidate);\n\n\treturn candidates;\n}\n\nstatic void\nfill_zero_tcp_act_ports_from_tcp_pass(GSList *candidates, GSList *all_candidates)\n{\n\tGSList *i;\n\tGHashTable *ip_to_port = g_hash_table_new(g_str_hash, g_str_equal);\n\n\tfor (i = candidates; i; i = i->next) {\n\t\tstruct sdpcandidate *c = i->data;\n\t\tGSList *j;\n\n\t\tif (c->protocol != SIPE_NETWORK_PROTOCOL_TCP_ACTIVE) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tfor (j = all_candidates; j; j = j->next) {\n\t\t\tstruct sdpcandidate *passive = j->data;\n\t\t\tif (passive->protocol != SIPE_NETWORK_PROTOCOL_TCP_PASSIVE ||\n\t\t\t    c->type != passive->type) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (sipe_strequal(c->ip, passive->ip) &&\n\t\t\t    sipe_strequal(c->base_ip, passive->base_ip)) {\n\t\t\t\tif (c->port == 0) {\n\t\t\t\t\tc->port = passive->port;\n\t\t\t\t}\n\n\t\t\t\tif (c->base_port == 0) {\n\t\t\t\t\tc->base_port = passive->base_port;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (i = all_candidates; i; i = i->next) {\n\t\tstruct sdpcandidate *c = i->data;\n\n\t\tif (c->protocol == SIPE_NETWORK_PROTOCOL_TCP_PASSIVE &&\n\t\t    c->type == SIPE_CANDIDATE_TYPE_HOST) {\n\t\t\tg_hash_table_insert(ip_to_port, c->ip, &c->port);\n\t\t}\n\t}\n\n\t/* Fill base ports of all TCP relay candidates using what we have\n\t * collected from host candidates. */\n\tfor (i = candidates; i; i = i->next) {\n\t\tstruct sdpcandidate *c = i->data;\n\t\tif (c->type == SIPE_CANDIDATE_TYPE_RELAY && c->base_port == 0) {\n\t\t\tguint *base_port = (guint*)g_hash_table_lookup(ip_to_port, c->base_ip);\n\t\t\tif (base_port) {\n\t\t\t\tc->base_port = *base_port;\n\t\t\t} else {\n\t\t\t\tSIPE_DEBUG_WARNING(\"Couldn't determine base port for candidate \"\n\t\t\t\t\t\t   \"with foundation %s\", c->foundation);\n\t\t\t}\n\t\t}\n\t}\n\n\tg_hash_table_destroy(ip_to_port);\n}\n\nstatic SipeEncryptionPolicy\nget_encryption_policy(struct sipe_core_private *sipe_private)\n{\n\tSipeEncryptionPolicy result =\n\t\t\tsipe_backend_media_get_encryption_policy(SIPE_CORE_PUBLIC);\n\tif (result == SIPE_ENCRYPTION_POLICY_OBEY_SERVER) {\n\t\tresult = sipe_private->server_av_encryption_policy;\n\t}\n\n\treturn result;\n}\n\nstatic GList *\nget_local_codecs(struct sipe_media_call_private *call_private,\n\t\t struct sipe_media_stream_private *stream_private)\n{\n\tstruct sipe_core_private *sipe_private = call_private->sipe_private;\n\tgboolean is_conference = g_strstr_len(SIPE_MEDIA_CALL->with,\n\t\t\t\t\t      strlen(SIPE_MEDIA_CALL->with),\n\t\t\t\t\t      \"app:conf:audio-video:\") != NULL;\n\tGList *codecs = sipe_backend_get_local_codecs(SIPE_MEDIA_CALL,\n\t\t\t\t\t\t      SIPE_MEDIA_STREAM);\n\tGList *i;\n\n\tfor (i = codecs; i; i = i->next) {\n\t\tstruct sipe_backend_codec *codec = i->data;\n\t\tchar *name = sipe_backend_codec_get_name(codec);\n\n\t\tif (/* Do not announce Theora. Its optional parameters are too\n\t\t     * long, Communicator rejects such SDP message and does not\n\t\t     * support the codec anyway. */\n\t\t    sipe_strequal(name,\"THEORA\") ||\n\t\t    /* For an unknown reason, MS Lync A/V conferencing server\n\t\t     * does not accept SIPE audio encoded with SIREN. Disable\n\t\t     * the codec when SIPE is connected to a server version\n\t\t     * prior Skype for Business. */\n\t\t    (!SIPE_CORE_PRIVATE_FLAG_IS(SFB) && is_conference &&\n\t\t     sipe_strequal(name,\"SIREN\"))) {\n\t\t\tGList *tmp;\n\t\t\tsipe_backend_codec_free(codec);\n\t\t\ttmp = i->next;\n\t\t\tcodecs = g_list_delete_link(codecs, i);\n\t\t\ti = tmp;\n\t\t}\n\n\t\tg_free(name);\n\t}\n\n\treturn codecs;\n}\n\nstatic struct sdpmedia *\nmedia_stream_to_sdpmedia(struct sipe_media_call_private *call_private,\n\t\t\t struct sipe_media_stream_private *stream_private)\n{\n\tstruct sdpmedia *sdpmedia = g_new0(struct sdpmedia, 1);\n\tGList *codecs = get_local_codecs(call_private, stream_private);\n\tSipeEncryptionPolicy encryption_policy =\n\t\t\tget_encryption_policy(call_private->sipe_private);\n\tguint rtcp_port = 0;\n\tSipeMediaType type;\n\tGSList *attributes = NULL;\n\tGSList *sdpcandidates;\n\tGSList *all_sdpcandidates;\n\tGList *candidates;\n\tGList *i;\n\tGSList *j;\n\n\tsdpmedia->name = g_strdup(SIPE_MEDIA_STREAM->id);\n\n\tif (sipe_strequal(sdpmedia->name, \"audio\"))\n\t\ttype = SIPE_MEDIA_AUDIO;\n\telse if (sipe_strequal(sdpmedia->name, \"video\"))\n\t\ttype = SIPE_MEDIA_VIDEO;\n\telse if (sipe_strequal(sdpmedia->name, \"data\"))\n\t\ttype = SIPE_MEDIA_APPLICATION;\n\telse if (sipe_strequal(sdpmedia->name, \"applicationsharing\"))\n\t\ttype = SIPE_MEDIA_APPLICATION;\n\telse {\n\t\t// TODO: incompatible media, should not happen here\n\t\tg_free(sdpmedia->name);\n\t\tg_free(sdpmedia);\n\t\tsipe_media_codec_list_free(codecs);\n\t\treturn(NULL);\n\t}\n\n\t// Process codecs\n\tfor (i = codecs; i; i = i->next) {\n\t\tstruct sipe_backend_codec *codec = i->data;\n\t\tstruct sdpcodec *c = g_new0(struct sdpcodec, 1);\n\t\tGList *params;\n\n\t\tc->id = sipe_backend_codec_get_id(codec);\n\t\tc->name = sipe_backend_codec_get_name(codec);\n\t\tc->clock_rate = sipe_backend_codec_get_clock_rate(codec);\n\t\tc->type = type;\n\n\t\tparams = sipe_backend_codec_get_optional_parameters(codec);\n\t\tfor (; params; params = params->next) {\n\t\t\tstruct sipnameval *param = params->data;\n\t\t\tstruct sipnameval *copy = g_new0(struct sipnameval, 1);\n\n\t\t\tcopy->name = g_strdup(param->name);\n\t\t\tcopy->value = g_strdup(param->value);\n\n\t\t\tc->parameters = g_slist_append(c->parameters, copy);\n\t\t}\n\n\t\t/* Buggy(?) codecs may report non-unique id (a.k.a. payload\n\t\t * type) that must not appear in SDP messages we send. Thus,\n\t\t * let's ignore any codec having the same id as one we already\n\t\t * have in the converted list. */\n\t\tif (g_slist_find_custom(sdpmedia->codecs, c, sdpcodec_compare)) {\n\t\t\tsdpcodec_free(c);\n\t\t} else {\n\t\t\tsdpmedia->codecs = g_slist_append(sdpmedia->codecs, c);\n\t\t}\n\t}\n\n\tsipe_media_codec_list_free(codecs);\n\n\t// Process local candidates\n\t// If we have established candidate pairs, send them in SDP response.\n\t// Otherwise send all available local candidates.\n\tcandidates = sipe_backend_media_stream_get_active_local_candidates(SIPE_MEDIA_STREAM);\n\tsdpcandidates = backend_candidates_to_sdpcandidate(candidates);\n\tsipe_media_candidate_list_free(candidates);\n\n\tcandidates = sipe_backend_get_local_candidates(SIPE_MEDIA_CALL,\n\t\t\t\t\t\t       SIPE_MEDIA_STREAM);\n\tcandidates = remove_wrong_farstream_0_1_tcp_candidates(candidates);\n\tall_sdpcandidates = backend_candidates_to_sdpcandidate(candidates);\n\tsipe_media_candidate_list_free(candidates);\n\n\tif (!sdpcandidates) {\n\t\tsdpcandidates = all_sdpcandidates;\n\t}\n\n\tfill_zero_tcp_act_ports_from_tcp_pass(sdpcandidates, all_sdpcandidates);\n\n\tsdpmedia->candidates = sdpcandidates;\n\n\tif (all_sdpcandidates != sdpcandidates) {\n\t\tsipe_utils_slist_free_full(all_sdpcandidates,\n\t\t\t\t\t   (GDestroyNotify)sdpcandidate_free);\n\t}\n\n\tget_stream_ip_and_ports(sdpmedia->candidates, &sdpmedia->ip,\n\t\t\t\t&sdpmedia->port, &rtcp_port);\n\n\tif (sipe_backend_stream_is_held(SIPE_MEDIA_STREAM))\n\t\tattributes = sipe_utils_nameval_add(attributes, \"inactive\", \"\");\n\n\tif (rtcp_port) {\n\t\tgchar *tmp = g_strdup_printf(\"%u\", rtcp_port);\n\t\tattributes  = sipe_utils_nameval_add(attributes, \"rtcp\", tmp);\n\t\tg_free(tmp);\n\t}\n\n\tif (encryption_policy != call_private->sipe_private->server_av_encryption_policy) {\n\t\tconst gchar *encryption = NULL;\n\t\tswitch (encryption_policy) {\n\t\t\tcase SIPE_ENCRYPTION_POLICY_REJECTED:\n\t\t\t\tencryption = \"rejected\";\n\t\t\t\tbreak;\n\t\t\tcase SIPE_ENCRYPTION_POLICY_OPTIONAL:\n\t\t\t\tencryption = \"optional\";\n\t\t\t\tbreak;\n\t\t\tcase SIPE_ENCRYPTION_POLICY_REQUIRED:\n\t\t\tdefault:\n\t\t\t\tencryption = \"required\";\n\t\t\t\tbreak;\n\t\t}\n\n\t\tattributes = sipe_utils_nameval_add(attributes, \"encryption\", encryption);\n\t}\n\n\tif (SIPE_MEDIA_STREAM->ssrc_range) {\n\t\tgchar *tmp;\n\n\t\ttmp = g_strdup_printf(\"%u-%u\",\n\t\t\t\t      SIPE_MEDIA_STREAM->ssrc_range->begin,\n\t\t\t\t      SIPE_MEDIA_STREAM->ssrc_range->end);\n\t\tattributes = sipe_utils_nameval_add(attributes,\n\t\t\t\t\t\t    \"x-ssrc-range\", tmp);\n\t\tg_free(tmp);\n\t}\n\n\t// Process remote candidates\n\tcandidates = sipe_backend_media_stream_get_active_remote_candidates(SIPE_MEDIA_STREAM);\n\tsdpmedia->remote_candidates = backend_candidates_to_sdpcandidate(candidates);\n\tsipe_media_candidate_list_free(candidates);\n\n\tsdpmedia->encryption_active = stream_private->encryption_key &&\n\t\t\t\t      call_private->encryption_compatible &&\n\t\t\t\t      stream_private->remote_candidates_and_codecs_set &&\n\t\t\t\t      encryption_policy != SIPE_ENCRYPTION_POLICY_REJECTED;\n\n\t// Set our key if encryption is enabled.\n\tif (stream_private->encryption_key &&\n\t    encryption_policy != SIPE_ENCRYPTION_POLICY_REJECTED) {\n\t\tsdpmedia->encryption_key = g_memdup(stream_private->encryption_key,\n\t\t\t\t\t\t    SIPE_SRTP_KEY_LEN);\n\t\tsdpmedia->encryption_key_id = stream_private->encryption_key_id;\n\t}\n\n\t// Append extra attributes assigned to the stream.\n\tfor (j = stream_private->extra_sdp; j; j = g_slist_next(j)) {\n\t\tstruct sipnameval *attr = j->data;\n\t\tattributes = sipe_utils_nameval_add(attributes,\n\t\t\t\t\t\t    attr->name, attr->value);\n\t}\n\n\tsdpmedia->attributes = attributes;\n\n\treturn sdpmedia;\n}\n\nstatic struct sdpmsg *\nsipe_media_to_sdpmsg(struct sipe_media_call_private *call_private)\n{\n\tstruct sdpmsg *msg = g_new0(struct sdpmsg, 1);\n\tGSList *streams = call_private->streams;\n\n\tfor (; streams; streams = streams->next) {\n\t\tstruct sdpmedia *media = media_stream_to_sdpmedia(call_private,\n\t\t\t\t\t\t\t\t  streams->data);\n\t\tif (media) {\n\t\t\tmsg->media = g_slist_append(msg->media, media);\n\n\t\t\tif (msg->ip == NULL)\n\t\t\t\tmsg->ip = g_strdup(media->ip);\n\t\t}\n\t}\n\n\tmsg->media = g_slist_concat(msg->media, call_private->failed_media);\n\tcall_private->failed_media = NULL;\n\n\tmsg->ice_version = call_private->ice_version;\n\n\treturn msg;\n}\n\nstatic void\nsipe_invite_call(struct sipe_media_call_private *call_private, TransCallback tc)\n{\n\tstruct sipe_core_private *sipe_private = call_private->sipe_private;\n\tgchar *hdr;\n\tgchar *contact;\n\tgchar *p_preferred_identity = NULL;\n\tgchar *body;\n\tstruct sip_dialog *dialog;\n\tstruct sdpmsg *msg;\n\n\tdialog = sipe_media_get_sip_dialog(SIPE_MEDIA_CALL);\n\n\tcontact = get_contact(sipe_private);\n\n\tif (sipe_private->uc_line_uri) {\n\t\tgchar *self = sip_uri_self(sipe_private);\n\t\tp_preferred_identity = g_strdup_printf(\n\t\t\t\"P-Preferred-Identity: <%s>, <%s>\\r\\n\",\n\t\t\tself, sipe_private->uc_line_uri);\n\t\tg_free(self);\n\t}\n\n\thdr = g_strdup_printf(\n\t\t\"ms-keep-alive: UAC;hop-hop=yes\\r\\n\"\n\t\t\"Contact: %s\\r\\n\"\n\t\t\"%s\"\n\t\t\"Content-Type: %s%s\\r\\n\",\n\t\tcontact,\n\t\tp_preferred_identity ? p_preferred_identity : \"\",\n\t\tcall_private->invite_content_type ?\n\t\t\t  call_private->invite_content_type : \"application/sdp\",\n\t\tcall_private->invite_content_type ?\n\t\t\t\";boundary=\\\"----=_NextPart_000_001E_01CB4397.0B5EB570\\\"\" : \"\");\n\n\tg_free(contact);\n\tg_free(p_preferred_identity);\n\n\tmsg = sipe_media_to_sdpmsg(call_private);\n\tbody = sdpmsg_to_string(msg);\n\n\tif (call_private->extra_invite_section) {\n\t\tgchar *tmp;\n\t\ttmp = g_strdup_printf(\n\t\t\t\"------=_NextPart_000_001E_01CB4397.0B5EB570\\r\\n\"\n\t\t\t\"%s\"\n\t\t\t\"\\r\\n\"\n\t\t\t\"------=_NextPart_000_001E_01CB4397.0B5EB570\\r\\n\"\n\t\t\t\"Content-Type: application/sdp\\r\\n\"\n\t\t\t\"Content-Transfer-Encoding: 7bit\\r\\n\"\n\t\t\t\"Content-Disposition: session; handling=optional\\r\\n\"\n\t\t\t\"\\r\\n\"\n\t\t\t\"%s\"\n\t\t\t\"\\r\\n\"\n\t\t\t\"------=_NextPart_000_001E_01CB4397.0B5EB570--\\r\\n\",\n\t\t\tcall_private->extra_invite_section, body);\n\t\tg_free(body);\n\t\tbody = tmp;\n\t\tsipe_media_add_extra_invite_section(SIPE_MEDIA_CALL, NULL, NULL);\n\t}\n\n\tsdpmsg_free(msg);\n\n\tdialog->outgoing_invite = sip_transport_invite(sipe_private,\n\t\t\t\t\t\t       hdr,\n\t\t\t\t\t\t       body,\n\t\t\t\t\t\t       dialog,\n\t\t\t\t\t\t       tc);\n\n\tg_free(body);\n\tg_free(hdr);\n}\n\nstatic void\nsend_response_with_session_description(struct sipe_media_call_private *call_private, int code, const gchar *text)\n{\n\tstruct sdpmsg *msg = sipe_media_to_sdpmsg(call_private);\n\tgchar *body = sdpmsg_to_string(msg);\n\tsdpmsg_free(msg);\n\tsipmsg_add_header(call_private->invitation, \"Content-Type\", \"application/sdp\");\n\tsip_transport_response(call_private->sipe_private, call_private->invitation, code, text, body);\n\tg_free(body);\n}\n\nstatic gboolean\nprocess_invite_call_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t\t\t   struct sipmsg *msg,\n\t\t\t\t\t\t\t\t   struct transaction *trans);\n\nstruct sipe_media_stream *\nsipe_core_media_get_stream_by_id(struct sipe_media_call *call, const gchar *id)\n{\n\tGSList *i;\n\tfor (i = SIPE_MEDIA_CALL_PRIVATE->streams; i; i = i->next) {\n\t\tstruct sipe_media_stream *stream = i->data;\n\t\tif (sipe_strequal(stream->id, id))\n\t\t\treturn stream;\n\t}\n\treturn NULL;\n}\n\nstatic gboolean\nupdate_call_from_remote_sdp(struct sipe_media_call_private* call_private,\n\t\t\t    struct sdpmedia *media)\n{\n\tstruct sipe_media_stream *stream;\n\tGList *backend_candidates = NULL;\n\tGList *backend_codecs = NULL;\n\tGSList *i;\n\tgboolean result = TRUE;\n\n\tstream = sipe_core_media_get_stream_by_id(SIPE_MEDIA_CALL, media->name);\n\tif (media->port == 0) {\n\t\tif (stream) {\n\t\t\tsipe_backend_media_stream_end(SIPE_MEDIA_CALL, stream);\n\t\t}\n\t\treturn FALSE;\n\t}\n\n\tif (!stream)\n\t\treturn FALSE;\n\n\tif (sipe_utils_nameval_find(media->attributes, \"inactive\")) {\n\t\tsipe_backend_stream_hold(SIPE_MEDIA_CALL, stream, FALSE);\n\t} else if (sipe_backend_stream_is_held(stream)) {\n\t\tsipe_backend_stream_unhold(SIPE_MEDIA_CALL, stream, FALSE);\n\t}\n\n\tif (SIPE_MEDIA_STREAM_PRIVATE->remote_candidates_and_codecs_set) {\n\t\treturn TRUE;\n\t}\n\n\tfor (i = media->codecs; i; i = i->next) {\n\t\tstruct sdpcodec *c = i->data;\n\t\tstruct sipe_backend_codec *codec;\n\t\tGSList *j;\n\n\t\tcodec = sipe_backend_codec_new(c->id,\n\t\t\t\t\t       c->name,\n\t\t\t\t\t       c->type,\n\t\t\t\t\t       c->clock_rate,\n\t\t\t\t\t       c->channels);\n\n\t\tfor (j = c->parameters; j; j = j->next) {\n\t\t\tstruct sipnameval *attr = j->data;\n\n\t\t\tsipe_backend_codec_add_optional_parameter(codec,\n\t\t\t\t\t\t\t\t  attr->name,\n\t\t\t\t\t\t\t\t  attr->value);\n\t\t}\n\n\t\tbackend_codecs = g_list_append(backend_codecs, codec);\n\t}\n\n\tif (media->encryption_key && SIPE_MEDIA_STREAM_PRIVATE->encryption_key) {\n\t\tsipe_backend_media_set_encryption_keys(SIPE_MEDIA_CALL, stream,\n\t\t\t\tSIPE_MEDIA_STREAM_PRIVATE->encryption_key,\n\t\t\t\tmedia->encryption_key);\n\t\tSIPE_MEDIA_STREAM_PRIVATE->encryption_key_id = media->encryption_key_id;\n\t} else {\n\t\t// We now know that the stream won't be encrypted.\n\t\t// Allow unencrypted data to pass srtpdec freely\n\t\tsipe_backend_media_set_require_encryption(SIPE_MEDIA_CALL,\n\t\t\t\t\t\t\t  stream,\n\t\t\t\t\t\t\t  FALSE);\n\t}\n\n\tresult = sipe_backend_set_remote_codecs(SIPE_MEDIA_CALL, stream,\n\t\t\t\t\t\tbackend_codecs);\n\tsipe_media_codec_list_free(backend_codecs);\n\n\tif (result == FALSE) {\n\t\tsipe_backend_media_stream_end(SIPE_MEDIA_CALL, stream);\n\t\treturn FALSE;\n\t}\n\n\tfor (i = media->candidates; i; i = i->next) {\n\t\tstruct sdpcandidate *c = i->data;\n\t\tstruct sipe_backend_candidate *candidate;\n\t\tcandidate = sipe_backend_candidate_new(c->foundation,\n\t\t\t\t\t\t       c->component,\n\t\t\t\t\t\t       c->type,\n\t\t\t\t\t\t       c->protocol,\n\t\t\t\t\t\t       c->ip,\n\t\t\t\t\t\t       c->port,\n\t\t\t\t\t\t       c->username,\n\t\t\t\t\t\t       c->password);\n\t\tsipe_backend_candidate_set_priority(candidate, c->priority);\n\n\t\tbackend_candidates = g_list_append(backend_candidates, candidate);\n\t}\n\n\tsipe_backend_media_add_remote_candidates(SIPE_MEDIA_CALL, stream,\n\t\t\t\t\t\t backend_candidates);\n\tsipe_media_candidate_list_free(backend_candidates);\n\n\tif (sipe_strequal(stream->id, \"video\") && call_private->conference_session) {\n\t\tstream->media_source_id = call_private->conference_session->video_media_source_id;\n\t}\n\n\tSIPE_MEDIA_STREAM_PRIVATE->remote_candidates_and_codecs_set = TRUE;\n\n\treturn TRUE;\n}\n\nstatic void\napply_remote_message(struct sipe_media_call_private* call_private,\n\t\t     struct sdpmsg* msg)\n{\n\tGSList *i;\n\n\tsipe_utils_slist_free_full(call_private->failed_media, (GDestroyNotify)sdpmedia_free);\n\tcall_private->failed_media = NULL;\n\tcall_private->encryption_compatible = TRUE;\n\n\tfor (i = msg->media; i; i = i->next) {\n\t\tstruct sdpmedia *media = i->data;\n\t\tconst gchar *enc_level =\n\t\t\t\tsipe_utils_nameval_find(media->attributes, \"encryption\");\n\t\tif (sipe_strequal(enc_level, \"rejected\") &&\n\t\t    get_encryption_policy(call_private->sipe_private) == SIPE_ENCRYPTION_POLICY_REQUIRED) {\n\t\t\tcall_private->encryption_compatible = FALSE;\n\t\t}\n\n\t\tif (!update_call_from_remote_sdp(call_private, media)) {\n\t\t\tmedia->port = 0;\n\t\t\tcall_private->failed_media =\n\t\t\t\tg_slist_append(call_private->failed_media, media);\n\t\t}\n\t}\n\n\t/* We need to keep failed medias until response is sent, remove them\n\t * from sdpmsg that is to be freed. */\n\tfor (i = call_private->failed_media; i; i = i->next) {\n\t\tmsg->media = g_slist_remove(msg->media, i->data);\n\t}\n}\n\nstatic gboolean\ncall_initialized(struct sipe_media_call *call)\n{\n\tGSList *streams = SIPE_MEDIA_CALL_PRIVATE->streams;\n\tfor (; streams; streams = streams->next) {\n\t\tif (!sipe_backend_stream_initialized(call, streams->data)) {\n\t\t\treturn FALSE;\n\t\t}\n\t}\n\n\treturn TRUE;\n}\n\nstatic void\nstream_connection_timeout_cb(struct sipe_core_private *sipe_private,\n\t\t\t    gpointer data)\n{\n\tstruct sipe_media_call_private *call_private = data;\n\n\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t  _(\"Couldn't create stream\"),\n\t\t\t\t  _(\"Connection timed out\"));\n\tsipe_backend_media_hangup(SIPE_MEDIA_CALL->backend_private, TRUE);\n}\n\nstatic void\nstream_schedule_timeout(struct sipe_media_call *call)\n{\n\tGSList *i;\n\tfor (i = SIPE_MEDIA_CALL_PRIVATE->streams; i; i = i->next) {\n\t\tstruct sipe_media_stream_private *stream_private = i->data;\n\n                if (stream_private->established)\n\t\t\t\tcontinue;\n\t\tstream_private->timeout_key =\n\t\t\tg_strdup_printf(\"<media-stream-connect><%s><%s>\",\n\t\t\t\t\tsipe_media_get_sip_dialog(call)->callid,\n\t\t\t\t\tSIPE_MEDIA_STREAM->id);\n\n\t\tsipe_schedule_seconds(SIPE_MEDIA_CALL_PRIVATE->sipe_private,\n\t\t\t\t      stream_private->timeout_key,\n\t\t\t\t      SIPE_MEDIA_CALL_PRIVATE,\n\t\t\t\t      SIPE_MEDIA_STREAM_CONNECTION_TIMEOUT_SECONDS,\n\t\t\t\t      stream_connection_timeout_cb,\n\t\t\t\t      NULL);\n\t}\n}\n\nstatic void\nstream_schedule_cancel_timeout(struct sipe_media_call *call,\n\t\t\t       struct sipe_media_stream_private *stream_private)\n{\n\tif (stream_private->timeout_key) {\n\t\tsipe_schedule_cancel(SIPE_MEDIA_CALL_PRIVATE->sipe_private,\n\t\t\t\t     stream_private->timeout_key);\n\t\tg_free(stream_private->timeout_key);\n\t}\n\tstream_private->timeout_key = NULL;\n}\n\nstatic void\ncall_request_timeout_cb(struct sipe_core_private *sipe_private,\n\t\t\t    gpointer data)\n{\n\tstruct sipe_media_call_private *call_private = data;\n\n\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t  _(\"Request timed out\"),\n\t\t\t\t  _(\"Call could not be answered\"));\n\tsipe_backend_media_hangup(SIPE_MEDIA_CALL->backend_private, TRUE);\n}\n\nstatic void\ncall_schedule_request_timeout(struct sipe_media_call *call)\n{\n\tSIPE_MEDIA_CALL_PRIVATE->timeout_key =\n\t\tg_strdup_printf(\"<media-call-request><%s>\", sipe_media_get_sip_dialog(call)->callid);\n\n\tsipe_schedule_seconds(SIPE_MEDIA_CALL_PRIVATE->sipe_private,\n\t\t\t      SIPE_MEDIA_CALL_PRIVATE->timeout_key,\n\t\t\t      SIPE_MEDIA_CALL_PRIVATE,\n\t\t\t      SIPE_MEDIA_CALL_TIMEOUT_SECONDS,\n\t\t\t      call_request_timeout_cb,\n\t\t\t      NULL);\n}\n\nstatic void\ncall_schedule_cancel_request_timeout(struct sipe_media_call *call)\n{\n\tif (SIPE_MEDIA_CALL_PRIVATE->timeout_key) {\n\t\tsipe_schedule_cancel(SIPE_MEDIA_CALL_PRIVATE->sipe_private,\n\t\t\t\t     SIPE_MEDIA_CALL_PRIVATE->timeout_key);\n\t\tg_free(SIPE_MEDIA_CALL_PRIVATE->timeout_key);\n\t}\n\tSIPE_MEDIA_CALL_PRIVATE->timeout_key = NULL;\n}\n\n\nstatic void\ncall_ringing_timeout_cb(struct sipe_core_private *sipe_private,\n\t\t\t    gpointer data)\n{\n\tstruct sipe_media_call_private *call_private = data;\n\n\tsip_transport_response(sipe_private, call_private->invitation,\n\t\t\t\t       408, \"Request Timeout\", NULL);\n\tsipe_backend_media_hangup(SIPE_MEDIA_CALL->backend_private, FALSE);\n}\n\nstatic void\ncall_schedule_ringing_timeout(struct sipe_media_call *call)\n{\n\tSIPE_MEDIA_CALL_PRIVATE->ringing_key =\n\t\tg_strdup_printf(\"<media-call-ringing><%s>\", sipe_media_get_sip_dialog(call)->callid);\n\n\tsipe_schedule_seconds(SIPE_MEDIA_CALL_PRIVATE->sipe_private,\n\t\t\t      SIPE_MEDIA_CALL_PRIVATE->ringing_key,\n\t\t\t      SIPE_MEDIA_CALL_PRIVATE,\n\t\t\t      SIPE_MEDIA_CALL_RINGING_TIMEOUT_SECONDS,\n\t\t\t      call_ringing_timeout_cb,\n\t\t\t      NULL);\n}\n\nstatic void\ncall_schedule_cancel_ringing_timeout(struct sipe_media_call *call)\n{\n\tif (SIPE_MEDIA_CALL_PRIVATE->ringing_key) {\n\t\tsipe_schedule_cancel(SIPE_MEDIA_CALL_PRIVATE->sipe_private,\n\t\t\t\t     SIPE_MEDIA_CALL_PRIVATE->ringing_key);\n\t\tg_free(SIPE_MEDIA_CALL_PRIVATE->ringing_key);\n\t}\n\tSIPE_MEDIA_CALL_PRIVATE->ringing_key = NULL;\n}\n\n// Sends an invite response when the call is accepted and local candidates were\n// prepared, otherwise does nothing. If error response is sent, call_private is\n// disposed before function returns.\nstatic void\nmaybe_send_first_invite_response(struct sipe_media_call_private *call_private)\n{\n\tstruct sipe_backend_media *backend_media;\n\n\tbackend_media = call_private->public.backend_private;\n\n\tif (!sipe_backend_media_accepted(backend_media) ||\n\t    !call_initialized(&call_private->public))\n\t\treturn;\n\n\tif (!call_private->encryption_compatible) {\n\t\tstruct sipe_core_private *sipe_private = call_private->sipe_private;\n\n\t\tsipmsg_add_header(call_private->invitation, \"Warning\",\n\t\t\t\"308 lcs.microsoft.com \\\"Encryption Levels not compatible\\\"\");\n\t\tsip_transport_response(sipe_private,\n\t\t\tcall_private->invitation,\n\t\t\t488, \"Encryption Levels not compatible\",\n\t\t\tNULL);\n\t\tsipe_backend_media_reject(backend_media, FALSE);\n\t\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t  _(\"Unable to establish a call\"),\n\t\t\t\t\t  _(\"Encryption settings of peer are incompatible with ours.\"));\n\t} else {\n\t\tsend_response_with_session_description(call_private, 200, \"OK\");\n\t\tstream_schedule_timeout(SIPE_MEDIA_CALL);\n\t\tcall_schedule_cancel_ringing_timeout(SIPE_MEDIA_CALL);\n\t\tsipmsg_free(call_private->invitation);\n\t\tcall_private->invitation = NULL;\n\t}\n}\n\nstatic void\nstream_initialized_cb(struct sipe_media_call *call,\n\t\t      struct sipe_media_stream *stream)\n{\n\tif (call_initialized(call)) {\n\t\tstruct sipe_media_call_private *call_private = SIPE_MEDIA_CALL_PRIVATE;\n\n\t\tif (sipe_backend_media_is_initiator(call, stream)) {\n\t\t\tsipe_invite_call(call_private,\n\t\t\t\t\t process_invite_call_response);\n\t\t} else if (call_private->smsg) {\n\t\t\tstruct sdpmsg *smsg = call_private->smsg;\n\t\t\tcall_private->smsg = NULL;\n\n\t\t\tapply_remote_message(call_private, smsg);\n\t\t\tmaybe_send_first_invite_response(call_private);\n\t\t\tsdpmsg_free(smsg);\n\t\t}\n\t}\n}\n\nstatic void phone_state_publish(struct sipe_core_private *sipe_private)\n{\n\tif (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {\n\t\tsipe_ocs2007_phone_state_publish(sipe_private);\n\t} else {\n\t\t// TODO: OCS 2005 support. Is anyone still using it at all?\n\t}\n}\n\nvoid\nsipe_core_media_stream_end(struct sipe_media_stream *stream)\n{\n\tsipe_media_stream_free(SIPE_MEDIA_STREAM_PRIVATE);\n}\n\nstatic void\nmedia_end_cb(struct sipe_media_call *call)\n{\n\tstruct sipe_core_private *sipe_private;\n\n\tg_return_if_fail(call);\n\n\tsipe_private = SIPE_MEDIA_CALL_PRIVATE->sipe_private;\n\n\tsipe_media_call_free(SIPE_MEDIA_CALL_PRIVATE);\n\tphone_state_publish(sipe_private);\n}\n\nstatic void\ncall_accept_cb(struct sipe_media_call *call, gboolean local)\n{\n\tif (local) {\n\t\tmaybe_send_first_invite_response(SIPE_MEDIA_CALL_PRIVATE);\n\t}\n\tphone_state_publish(SIPE_MEDIA_CALL_PRIVATE->sipe_private);\n}\n\nstatic void\ncall_reject_cb(struct sipe_media_call *call, gboolean local)\n{\n\tif (local) {\n\t\tstruct sipe_media_call_private *call_private = SIPE_MEDIA_CALL_PRIVATE;\n\n\t\tsip_transport_response(call_private->sipe_private,\n\t\t\t\t       call_private->invitation,\n\t\t\t\t       603, \"Decline\", NULL);\n\n\t\tif (call_private->session) {\n\t\t\tsipe_session_remove(call_private->sipe_private,\n\t\t\t\t\t    call_private->session);\n\t\t\tcall_private->session = NULL;\n\t\t}\n\t}\n}\n\nstatic void\nav_call_reject_cb(struct sipe_media_call *call, gboolean local)\n{\n\tif (!local) {\n\t\tstruct sipe_core_private *sipe_private;\n\t\tgchar *desc;\n\n\t\tsipe_private = SIPE_MEDIA_CALL_PRIVATE->sipe_private;\n\n\t\tdesc = g_strdup_printf(_(\"User %s rejected call\"), call->with);\n\t\tsipe_backend_notify_error(SIPE_CORE_PUBLIC, _(\"Call rejected\"),\n\t\t\t\t\t  desc);\n\t\tg_free(desc);\n\t}\n\n\tcall_reject_cb(call, local);\n}\n\nstatic gboolean\nsipe_media_send_ack(struct sipe_core_private *sipe_private, struct sipmsg *msg,\n\t\t\t\t\tstruct transaction *trans);\n\nstatic void call_hold_cb(struct sipe_media_call *call,\n\t\t\t gboolean local,\n\t\t\t SIPE_UNUSED_PARAMETER gboolean state)\n{\n\tif (local) {\n\t\tsipe_invite_call(SIPE_MEDIA_CALL_PRIVATE, sipe_media_send_ack);\n\t}\n}\n\nstatic void call_hangup_cb(struct sipe_media_call *call, gboolean local)\n{\n\tif (local) {\n\t\tstruct sipe_media_call_private *call_private = SIPE_MEDIA_CALL_PRIVATE;\n\n\t\tif (call_private->session) {\n\t\t\tsipe_session_close(call_private->sipe_private,\n\t\t\t\t\t   call_private->session);\n\t\t\tcall_private->session = NULL;\n\t\t}\n\t}\n}\n\nstatic void\nerror_cb(struct sipe_media_call *call, gchar *message)\n{\n\tstruct sipe_media_call_private *call_private = SIPE_MEDIA_CALL_PRIVATE;\n\tstruct sipe_core_private *sipe_private = call_private->sipe_private;\n\tgboolean initiator = sipe_backend_media_is_initiator(call, NULL);\n\tgboolean accepted = sipe_backend_media_accepted(call->backend_private);\n\n\tgchar *title = g_strdup_printf(\"Call with %s failed\", call->with);\n\tsipe_backend_notify_error(SIPE_CORE_PUBLIC, title, message);\n\tg_free(title);\n\n\tif (!initiator && !accepted && call_private->invitation) {\n\t\tsip_transport_response(sipe_private,\n\t\t\t\t       call_private->invitation,\n\t\t\t\t       488, \"Not Acceptable Here\", NULL);\n\t}\n}\n\nstruct sipe_media_call *\nsipe_media_call_new(struct sipe_core_private *sipe_private, const gchar* with,\n\t\t    struct sipmsg *msg, SipeIceVersion ice_version,\n\t\t    SipeMediaCallFlags flags)\n{\n\tstruct sipe_media_call_private *call_private;\n\tstruct sip_session *session;\n\tstruct sip_dialog *dialog;\n\tgchar *cname;\n\n\tsession = sipe_session_add_call(sipe_private, with);\n\n\tdialog = sipe_dialog_add(session);\n\tdialog->with = g_strdup(with);\n\n\tif (msg) {\n\t\tsipmsg_update_to_header_tag(msg);\n\t\tdialog->callid = g_strdup(sipmsg_find_call_id_header(msg));\n\t\tsipe_dialog_parse(dialog, msg, FALSE);\n\t} else {\n\t\tdialog->callid = gencallid();\n\t\tdialog->ourtag = gentag();\n\t\tflags |= SIPE_MEDIA_CALL_INITIATOR;\n\t}\n\n\tif (g_hash_table_lookup(sipe_private->media_calls, dialog->callid)) {\n\t\tSIPE_DEBUG_ERROR(\"sipe_media_call_new: call already exists for \"\n\t\t\t\t \"Call-ID %s\", dialog->callid);\n\t\tsipe_session_remove(sipe_private, session);\n\t\treturn NULL;\n\t}\n\n\tcall_private = g_new0(struct sipe_media_call_private, 1);\n\tcall_private->sipe_private = sipe_private;\n\tcall_private->session = session;\n\tSIPE_MEDIA_CALL->with = g_strdup(with);\n\n\tg_hash_table_insert(sipe_private->media_calls,\n\t\t\t    g_strdup(dialog->callid), call_private);\n\n\tcname = g_strdup(sipe_private->contact + 1);\n\tcname[strlen(cname) - 1] = '\\0';\n\n\tcall_private->public.backend_private = sipe_backend_media_new(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t      SIPE_MEDIA_CALL,\n\t\t\t\t\t\t\t\t      with,\n\t\t\t\t\t\t\t\t      flags);\n\tsipe_backend_media_set_cname(call_private->public.backend_private, cname);\n\n\tcall_private->ice_version = ice_version;\n\tcall_private->encryption_compatible = TRUE;\n\n\tcall_private->public.stream_initialized_cb  = stream_initialized_cb;\n\tcall_private->public.media_end_cb           = media_end_cb;\n\tcall_private->public.call_accept_cb         = call_accept_cb;\n\tcall_private->public.call_reject_cb         = call_reject_cb;\n\tcall_private->public.call_hold_cb           = call_hold_cb;\n\tcall_private->public.call_hangup_cb         = call_hangup_cb;\n\tcall_private->public.error_cb               = error_cb;\n\n\tg_free(cname);\n\n\treturn SIPE_MEDIA_CALL;\n}\n\nstatic gboolean\nfind_call_cb(SIPE_UNUSED_PARAMETER const gchar *callid,\n\t     struct sipe_media_call *call,\n\t     const gchar *with)\n{\n\treturn sipe_strequal(call->with, with);\n}\n\nstruct sipe_media_call *\nsipe_media_call_find(struct sipe_core_private *sipe_private, const gchar *with)\n{\n\treturn g_hash_table_find(sipe_private->media_calls,\n\t\t\t\t (GHRFunc)find_call_cb,\n\t\t\t\t (gpointer)with);\n}\n\nvoid sipe_media_hangup(struct sipe_media_call_private *call_private)\n{\n\tif (call_private) {\n\t\tsipe_backend_media_hangup(call_private->public.backend_private,\n\t\t\t\t\t  FALSE);\n\t}\n}\n\nstatic gint\nssrc_range_compare(const struct ssrc_range *a, const struct ssrc_range *b)\n{\n\tif (a->begin < b->begin) {\n\t\treturn -1;\n\t}\n\tif (a->begin > b->begin) {\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nstatic void\nssrc_range_update(GSList **ranges, GSList *media)\n{\n\tfor (; media; media = media->next) {\n\t\tstruct sdpmedia *m;\n\t\tconst char *ssrc_range;\n\t\tgchar **parts;\n\n\t\tm = media->data;\n\t\tssrc_range = sipe_utils_nameval_find(m->attributes,\n\t\t\t\t\t\t     \"x-ssrc-range\");\n\t\tif (!ssrc_range) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tparts = g_strsplit(ssrc_range, \"-\", 2);\n\n\t\tif (parts[0] && parts[1]) {\n\t\t\tstruct ssrc_range *range;\n\n\t\t\trange = g_new0(struct ssrc_range, 1);\n\t\t\trange->begin = atoi(parts[0]);\n\t\t\trange->end = atoi(parts[1]);\n\n\t\t\t*ranges = sipe_utils_slist_insert_unique_sorted(\n\t\t\t\t\t*ranges, range,\n\t\t\t\t\t(GCompareFunc)ssrc_range_compare,\n\t\t\t\t\tg_free);\n\t\t}\n\n\t\tg_strfreev(parts);\n\t}\n}\n\nstatic struct ssrc_range *\nssrc_range_allocate(GSList **ranges, guint32 len)\n{\n\tstruct ssrc_range *range;\n\tGSList *i;\n\n\trange = g_new0(struct ssrc_range, 1);\n\trange->begin = 1;\n\trange->end = range->begin + (len - 1);\n\n\tfor (i = *ranges; i; i = i->next) {\n\t\tstruct ssrc_range *r = i->data;\n\n\t\tif (range->begin < r->begin && range->end < r->begin) {\n\t\t\tbreak;\n\t\t}\n\n\t\trange->begin = r->end + 1;\n\t\trange->end = range->begin + (len - 1);\n\t}\n\n\t/* As per [MS-SDPEXT] 3.1.5.31.1, a SSRC MUST be from 1 to 4294967040\n\t * inclusive. */\n\tif (range->begin > range->end || range->end > 0xFFFFFF00) {\n\t\tg_free(range);\n\t\tSIPE_DEBUG_ERROR(\"Couldn't allocate SSRC range of %u\", len);\n\t\treturn NULL;\n\t}\n\n\t*ranges = g_slist_insert_sorted(*ranges, range,\n\t\t\t\t\t(GCompareFunc)ssrc_range_compare);\n\n\treturn range;\n}\n\nstruct sipe_media_stream *\nsipe_media_stream_add(struct sipe_media_call *call, const gchar *id,\n\t\t      SipeMediaType type, SipeIceVersion ice_version,\n\t\t      gboolean initiator, guint32 ssrc_count)\n{\n\tstruct sipe_core_private *sipe_private;\n\tstruct sipe_media_stream_private *stream_private;\n\tstruct sipe_backend_media_relays *backend_media_relays;\n\tguint min_port;\n\tguint max_port;\n\n\tsipe_private = SIPE_MEDIA_CALL_PRIVATE->sipe_private;\n\n\tbackend_media_relays = sipe_backend_media_relays_convert(\n\t\t\t\t\t\tsipe_private->media_relays,\n\t\t\t\t\t\tsipe_private->media_relay_username,\n\t\t\t\t\t\tsipe_private->media_relay_password);\n\n\tmin_port = sipe_private->min_media_port;\n\tmax_port = sipe_private->max_media_port;\n\tswitch (type) {\n\t\tcase SIPE_MEDIA_AUDIO:\n\t\t\tmin_port = sipe_private->min_audio_port;\n\t\t\tmax_port = sipe_private->max_audio_port;\n\t\t\tbreak;\n\t\tcase SIPE_MEDIA_VIDEO:\n\t\t\tmin_port = sipe_private->min_video_port;\n\t\t\tmax_port = sipe_private->max_audio_port;\n\t\t\tbreak;\n\t\tcase SIPE_MEDIA_APPLICATION:\n\t\t\tif (sipe_strequal(id, \"data\")) {\n\t\t\t\tmin_port = sipe_private->min_filetransfer_port;\n\t\t\t\tmax_port = sipe_private->max_filetransfer_port;\n\t\t\t} else if (sipe_strequal(id, \"applicationsharing\")) {\n\t\t\t\tmin_port = sipe_private->min_appsharing_port;\n\t\t\t\tmax_port = sipe_private->max_appsharing_port;\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n\tstream_private = g_new0(struct sipe_media_stream_private, 1);\n\tSIPE_MEDIA_STREAM->call = call;\n\tSIPE_MEDIA_STREAM->id = g_strdup(id);\n\tstream_private->write_queue = g_queue_new();\n\tstream_private->async_reads = g_queue_new();\n\n\tif (ssrc_count > 0) {\n\t\tSIPE_MEDIA_STREAM->ssrc_range =\n\t\t\tssrc_range_allocate(&SIPE_MEDIA_CALL_PRIVATE->ssrc_ranges,\n\t\t\t\t\t    ssrc_count);\n\t}\n\n\tSIPE_MEDIA_STREAM->media_source_id = SIPE_MSRTP_VSR_SOURCE_ANY;\n\n\tSIPE_MEDIA_STREAM->backend_private =\n\t\t\tsipe_backend_media_add_stream(SIPE_MEDIA_STREAM,\n\t\t\t\t\t\t      type, ice_version,\n\t\t\t\t\t\t      initiator,\n\t\t\t\t\t\t      backend_media_relays,\n\t\t\t\t\t\t      min_port, max_port);\n\n\tsipe_backend_media_relays_free(backend_media_relays);\n\n\tif (!SIPE_MEDIA_STREAM->backend_private) {\n\t\tsipe_media_stream_free(stream_private);\n\t\treturn NULL;\n\t}\n\n\tif (type == SIPE_MEDIA_VIDEO) {\n\t\t/* Declare that we can send and receive Video Source Requests\n\t\t * as per [MS-SDPEXT] 3.1.5.30.2. */\n\t\tsipe_media_stream_add_extra_attribute(SIPE_MEDIA_STREAM,\n\t\t\t\t\"rtcp-fb\", \"* x-message app send:src recv:src\");\n\n\t\tsipe_media_stream_add_extra_attribute(SIPE_MEDIA_STREAM,\n\t\t\t\t\"rtcp-rsize\", NULL);\n\t\tsipe_media_stream_add_extra_attribute(SIPE_MEDIA_STREAM,\n\t\t\t\t\"label\", \"main-video\");\n\t\tsipe_media_stream_add_extra_attribute(SIPE_MEDIA_STREAM,\n\t\t\t\t\"x-source\", \"main-video\");\n\t}\n\n#ifdef HAVE_SRTP\n\tif (get_encryption_policy(sipe_private) != SIPE_ENCRYPTION_POLICY_REJECTED) {\n\t\tint i;\n\t\tstream_private->encryption_key = g_new0(guchar, SIPE_SRTP_KEY_LEN);\n\t\tfor (i = 0; i != SIPE_SRTP_KEY_LEN; ++i) {\n\t\t\tstream_private->encryption_key[i] = rand() & 0xff;\n\t\t}\n\t\tstream_private->encryption_key_id = 1;\n\t\t// We don't know yet whether the stream will be\n\t\t// encrypted or not. Enable the require-encryption\n\t\t// property at stream creation time anyway, we may\n\t\t// disable it later if we don't receive encryption keys.\n\t\tsipe_backend_media_set_require_encryption(call,\n\t\t\t\t\t\t\t  SIPE_MEDIA_STREAM,\n\t\t\t\t\t\t\t  TRUE);\n\t}\n#endif\n\n\tSIPE_MEDIA_CALL_PRIVATE->streams =\n\t\t\tg_slist_append(SIPE_MEDIA_CALL_PRIVATE->streams,\n\t\t\t\t       stream_private);\n\n\treturn SIPE_MEDIA_STREAM;\n}\n\nstatic void\nappend_2007_fallback_if_needed(struct sipe_media_call_private *call_private)\n{\n\tstruct sipe_core_private *sipe_private = call_private->sipe_private;\n\tconst gchar *marker = sip_transport_sdp_address_marker(sipe_private);\n\tconst gchar *ip = sip_transport_ip_address(sipe_private);\n\tgchar *body;\n\n\tif (SIPE_CORE_PRIVATE_FLAG_IS(SFB) ||\n\t    sipe_media_get_sip_dialog(SIPE_MEDIA_CALL)->cseq != 0 ||\n\t    call_private->ice_version != SIPE_ICE_RFC_5245 ||\n\t    sipe_strequal(SIPE_MEDIA_CALL->with, sipe_private->test_call_bot_uri)) {\n\t\treturn;\n\t}\n\n\tbody = g_strdup_printf(\"Content-Type: application/sdp\\r\\n\"\n\t\t\t       \"Content-Transfer-Encoding: 7bit\\r\\n\"\n\t\t\t       \"Content-Disposition: session; handling=optional; ms-proxy-2007fallback\\r\\n\"\n\t\t\t       \"\\r\\n\"\n\t\t\t       \"o=- 0 0 IN %s %s\\r\\n\"\n\t\t\t       \"s=session\\r\\n\"\n\t\t\t       \"c=IN %s %s\\r\\n\"\n\t\t\t       \"m=audio 0 RTP/AVP\\r\\n\",\n\t\t\t       marker, ip,\n\t\t\t       marker, ip);\n\tsipe_media_add_extra_invite_section(SIPE_MEDIA_CALL,\n\t\t\t\t\t    \"multipart/alternative\", body);\n}\n\nstatic void\nsipe_media_initiate_call(struct sipe_core_private *sipe_private,\n\t\t\t const char *with, SipeIceVersion ice_version,\n\t\t\t gboolean with_video)\n{\n\tstruct sipe_media_call_private *call_private;\n\n\tif (sipe_core_media_get_call(SIPE_CORE_PUBLIC)) {\n\t\treturn;\n\t}\n\n\tcall_private = (struct sipe_media_call_private *)\n\t\t\t\tsipe_media_call_new(sipe_private, with, NULL,\n\t\t\t\t\t\t    ice_version, 0);\n\n\tSIPE_MEDIA_CALL->call_reject_cb = av_call_reject_cb;\n\n\tif (!sipe_media_stream_add(SIPE_MEDIA_CALL, \"audio\", SIPE_MEDIA_AUDIO,\n\t\t\t\t   call_private->ice_version,\n\t\t\t\t   TRUE, 0)) {\n\t\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t  _(\"Error occurred\"),\n\t\t\t\t\t  _(\"Error creating audio stream\"));\n\t\tsipe_media_hangup(call_private);\n\t\treturn;\n\t}\n\n\tif (with_video &&\n\t    !sipe_media_stream_add(SIPE_MEDIA_CALL, \"video\", SIPE_MEDIA_VIDEO,\n\t\t\t\t   call_private->ice_version,\n\t\t\t\t   TRUE, VIDEO_SSRC_COUNT)) {\n\t\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t  _(\"Error occurred\"),\n\t\t\t\t\t  _(\"Error creating video stream\"));\n\t\tsipe_media_hangup(call_private);\n\t\treturn;\n\t}\n\n\tappend_2007_fallback_if_needed(call_private);\n\n\tcall_schedule_request_timeout(SIPE_MEDIA_CALL);\n\t// Processing continues in stream_initialized_cb\n}\n\nvoid\nsipe_core_media_initiate_call(struct sipe_core_public *sipe_public,\n\t\t\t      const char *with,\n\t\t\t      gboolean with_video)\n{\n\tsipe_media_initiate_call(SIPE_CORE_PRIVATE, with,\n\t\t\t\t SIPE_ICE_RFC_5245, with_video);\n}\n\nstatic void\nconference_audio_muted_cb(struct sipe_media_stream *stream, gboolean is_muted)\n{\n\tstruct sipe_media_call *call = stream->call;\n\n\tif (!SIPE_MEDIA_CALL_PRIVATE->conference_session) {\n\t\treturn;\n\t}\n\n\tsipe_conf_announce_audio_mute_state(SIPE_MEDIA_CALL_PRIVATE->sipe_private,\n\t\t\t\t\t    SIPE_MEDIA_CALL_PRIVATE->conference_session,\n\t\t\t\t\t    is_muted);\n}\n\nvoid sipe_core_media_connect_conference(struct sipe_core_public *sipe_public,\n\t\t\t\t\tstruct sipe_chat_session *chat_session,\n\t\t\t\t\tgboolean with_video)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tstruct sipe_media_call_private *call_private;\n\tstruct sipe_media_stream *stream;\n\tstruct sip_session *session;\n\tSipeIceVersion ice_version;\n\tgchar *av_uri;\n\n\tif (!sipe_conf_supports_mcu_type(sipe_private, \"audio-video\")) {\n\t\tsipe_backend_notify_error(sipe_public, _(\"Join conference call\"),\n\t\t\t\t_(\"Conference calls are not supported on this server.\"));\n\t\treturn;\n\t}\n\n\tsession = sipe_session_find_chat(sipe_private, chat_session);\n\n\tif (sipe_core_media_get_call(sipe_public) || !session) {\n\t\treturn;\n\t}\n\n\tav_uri = sipe_conf_build_uri(sipe_core_chat_id(sipe_public, chat_session),\n\t\t\t\t     \"audio-video\");\n\tif (!av_uri) {\n\t\treturn;\n\t}\n\n\tsession->is_call = TRUE;\n\n\tice_version = SIPE_CORE_PRIVATE_FLAG_IS(LYNC2013) ? SIPE_ICE_RFC_5245 :\n\t\t\t\t\t\t\t    SIPE_ICE_DRAFT_6;\n\n\tcall_private = (struct sipe_media_call_private *)\n\t\t\t\tsipe_media_call_new(sipe_private, av_uri, NULL,\n\t\t\t\t\t\t    ice_version, 0);\n\tcall_private->conference_session = session;\n\tSIPE_MEDIA_CALL->call_reject_cb = av_call_reject_cb;\n\n\tg_free(av_uri);\n\n\tstream = sipe_media_stream_add(SIPE_MEDIA_CALL, \"audio\",\n\t\t\t\t       SIPE_MEDIA_AUDIO,\n\t\t\t\t       call_private->ice_version,\n\t\t\t\t       TRUE, 0);\n\tif (!stream) {\n\t\tsipe_backend_notify_error(sipe_public,\n\t\t\t\t\t  _(\"Error occurred\"),\n\t\t\t\t\t  _(\"Error creating audio stream\"));\n\n\t\tsipe_media_hangup(call_private);\n\t\treturn;\n\t}\n\n\tstream->mute_cb = conference_audio_muted_cb;\n\n\tif (with_video) {\n\t\tstream = sipe_media_stream_add(SIPE_MEDIA_CALL, \"video\",\n\t\t\t\t\t       SIPE_MEDIA_VIDEO,\n\t\t\t\t\t       call_private->ice_version,\n\t\t\t\t\t       TRUE, VIDEO_SSRC_COUNT);\n\t\tif (!stream) {\n\t\t\tsipe_backend_notify_error(sipe_public,\n\t\t\t\t\t\t  _(\"Error occurred\"),\n\t\t\t\t\t\t  _(\"Error creating video stream\"));\n\t\t\tsipe_media_hangup(call_private);\n\t\t}\n\t}\n\n\t// Processing continues in stream_initialized_cb\n}\n\nstruct sipe_media_call *\nsipe_core_media_get_call(struct sipe_core_public *sipe_public)\n{\n\tstruct sipe_media_call * result = NULL;\n\tGList *calls = g_hash_table_get_values(SIPE_CORE_PRIVATE->media_calls);\n\tGList *entry = calls;\n\n\twhile (entry) {\n\t\tif (sipe_core_media_get_stream_by_id(entry->data, \"audio\")) {\n\t\t\tresult = entry->data;\n\t\t\tbreak;\n\t\t}\n\t\tentry = entry->next;\n\t}\n\tg_list_free(calls);\n\n\treturn result;\n}\n\nstatic gboolean phone_number_is_valid(const gchar *phone_number)\n{\n\tif (!phone_number || sipe_strequal(phone_number, \"\")) {\n\t\treturn FALSE;\n\t}\n\n\tif (*phone_number == '+') {\n\t\t++phone_number;\n\t}\n\n\twhile (*phone_number != '\\0') {\n\t\tif (!g_ascii_isdigit(*phone_number)) {\n\t\t\treturn FALSE;\n\t\t}\n\t\t++phone_number;\n\t}\n\n\treturn TRUE;\n}\n\nvoid sipe_core_media_phone_call(struct sipe_core_public *sipe_public,\n\t\t\t\tconst gchar *phone_number)\n{\n\tg_return_if_fail(sipe_public);\n\n\tSIPE_DEBUG_INFO(\"sipe_core_media_phone_call: %s\", phone_number ? phone_number : \"(null)\");\n\n\tif (phone_number_is_valid(phone_number)) {\n\t\tgchar *phone_uri = g_strdup_printf(\"sip:%s@%s;user=phone\",\n\t\t\t\tphone_number, sipe_public->sip_domain);\n\n\t\tsipe_core_media_initiate_call(sipe_public, phone_uri, FALSE);\n\n\t\tg_free(phone_uri);\n\t} else {\n\t\tsipe_backend_notify_error(sipe_public,\n\t\t\t\t\t  _(\"Unable to establish a call\"),\n\t\t\t\t\t  _(\"Invalid phone number\"));\n\t}\n}\n\nvoid sipe_core_media_test_call(struct sipe_core_public *sipe_public)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tif (!sipe_private->test_call_bot_uri) {\n\t\tsipe_backend_notify_error(sipe_public,\n\t\t\t\t\t  _(\"Unable to establish a call\"),\n\t\t\t\t\t  _(\"Audio Test Service is not available.\"));\n\t\treturn;\n\t}\n\n\tsipe_core_media_initiate_call(sipe_public,\n\t\t\t\t      sipe_private->test_call_bot_uri, FALSE);\n}\n\nstatic struct sipe_media_call_private *\nsipe_media_from_sipmsg(struct sipe_core_private *sipe_private,\n\t\t       struct sipmsg *msg)\n{\n\treturn g_hash_table_lookup(sipe_private->media_calls,\n\t\t\t\t   sipmsg_find_call_id_header(msg));\n}\n\nstatic void\ntransport_response_unsupported_sdp(struct sipe_core_private *sipe_private,\n\t\t\t\t   struct sipmsg *msg)\n{\n\tsipmsg_add_header(msg, \"ms-client-diagnostics\",\n\t\t\t  \"52063;reason=\\\"Unsupported session description\\\"\");\n\tsip_transport_response(sipe_private, msg,\n\t\t\t       488, \"Not Acceptable Here\", NULL);\n}\n\nstatic void\nmaybe_send_second_invite_response(struct sipe_media_call_private *call_private)\n{\n\tGSList *it;\n\n\t/* Second INVITE request had to be received and all streams must have\n\t * established candidate pairs before the response can be sent. */\n\n\tif (!call_private->invitation) {\n\t\treturn;\n\t}\n\n\tfor (it = call_private->streams; it; it = it->next) {\n\t\tstruct sipe_media_stream_private *stream_private = it->data;\n\t\tif (!stream_private->established) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\tsend_response_with_session_description(call_private, 200, \"OK\");\n\n#ifdef HAVE_XDATA\n\tfor (it = call_private->streams; it; it = it->next) {\n\t\tstruct sipe_media_stream_private *stream_private = it->data;\n\n\t\tstream_private->sdp_negotiation_concluded = TRUE;\n\t\tif (stream_private->writable) {\n\t\t\t// We've become writable.\n\t\t\tsipe_core_media_stream_writable(SIPE_MEDIA_STREAM, TRUE);\n\t\t}\n\t}\n#endif\n}\n\nstruct sipe_media_call *\nprocess_incoming_invite_call(struct sipe_core_private *sipe_private,\n\t\t\t     struct sipmsg *msg,\n\t\t\t     const gchar *sdp)\n{\n\treturn(process_incoming_invite_call_parsed_sdp(sipe_private,\n\t\t\t\t\t\t       msg,\n\t\t\t\t\t\t       sdpmsg_parse_msg(sdp)));\n}\n\nstruct sipe_media_call *\nprocess_incoming_invite_call_parsed_sdp(struct sipe_core_private *sipe_private,\n\t\t\t\t\tstruct sipmsg *msg,\n\t\t\t\t\tstruct sdpmsg *smsg)\n{\n\tstruct sipe_media_call_private *call_private;\n\tgboolean has_new_media = FALSE;\n\tGSList *i;\n\n\t// Don't allow two voice calls in parallel.\n\tif (!strstr(msg->body, \"m=data\") &&\n\t    !strstr(msg->body, \"m=applicationsharing\")) {\n\t\tstruct sipe_media_call *call =\n\t\t\t\tsipe_core_media_get_call(SIPE_CORE_PUBLIC);\n\t\tif (call && !is_media_session_msg(SIPE_MEDIA_CALL_PRIVATE, msg)) {\n\t\t\tsip_transport_response(sipe_private, msg,\n\t\t\t\t\t       486, \"Busy Here\", NULL);\n\t\t\tsdpmsg_free(smsg);\n\t\t\treturn NULL;\n\t\t}\n\t}\n\n\tcall_private = sipe_media_from_sipmsg(sipe_private, msg);\n\n\tif (call_private) {\n\t\tchar *self = sip_uri_self(sipe_private);\n\t\tif (sipe_strequal(SIPE_MEDIA_CALL->with, self)) {\n\t\t\tg_free(self);\n\t\t\tsip_transport_response(sipe_private, msg, 488, \"Not Acceptable Here\", NULL);\n\t\t\tsdpmsg_free(smsg);\n\t\t\treturn NULL;\n\t\t}\n\t\tg_free(self);\n\t}\n\n\tif (!smsg) {\n\t\ttransport_response_unsupported_sdp(sipe_private, msg);\n\t\tif (call_private) {\n\t\t\tsipe_media_hangup(call_private);\n\t\t}\n\t\treturn NULL;\n\t}\n\n\tif (!call_private) {\n\t\tgchar *with = sipmsg_parse_from_address(msg);\n\t\tSipeMediaCallFlags flags = 0;\n\n\t\tif (strstr(msg->body, \"m=data\") ||\n\t\t    strstr(msg->body, \"m=applicationsharing\")) {\n\t\t\tflags |= SIPE_MEDIA_CALL_NO_UI;\n\t\t}\n\n\t\tcall_private = (struct sipe_media_call_private *)\n\t\t\t\t\tsipe_media_call_new(sipe_private, with,\n\t\t\t\t\t\t\t    msg, smsg->ice_version,\n\t\t\t\t\t\t\t    flags);\n\n\t\tif (!(flags & SIPE_MEDIA_CALL_NO_UI)) {\n\t\t\tSIPE_MEDIA_CALL->call_reject_cb = av_call_reject_cb;\n\t\t}\n\t\tg_free(with);\n\t}\n\n\tif (call_private->invitation)\n\t\tsipmsg_free(call_private->invitation);\n\tcall_private->invitation = sipmsg_copy(msg);\n\n\tssrc_range_update(&call_private->ssrc_ranges, smsg->media);\n\n\t// Create any new media streams\n\tfor (i = smsg->media; i; i = i->next) {\n\t\tstruct sdpmedia *media = i->data;\n\t\tgchar *id = media->name;\n\t\tSipeMediaType type;\n\n\t\tif (   media->port != 0\n\t\t    && !sipe_core_media_get_stream_by_id(SIPE_MEDIA_CALL, id)) {\n\t\t\tguint32 ssrc_count = 0;\n\n\t\t\tif (sipe_strequal(id, \"audio\"))\n\t\t\t\ttype = SIPE_MEDIA_AUDIO;\n\t\t\telse if (sipe_strequal(id, \"video\")) {\n\t\t\t\ttype = SIPE_MEDIA_VIDEO;\n\t\t\t\tssrc_count = VIDEO_SSRC_COUNT;\n\t\t\t} else if (sipe_strequal(id, \"data\"))\n\t\t\t\ttype = SIPE_MEDIA_APPLICATION;\n\t\t\telse if (sipe_strequal(id, \"applicationsharing\"))\n\t\t\t\ttype = SIPE_MEDIA_APPLICATION;\n\t\t\telse\n\t\t\t\tcontinue;\n\n\t\t\tsipe_media_stream_add(SIPE_MEDIA_CALL, id, type,\n\t\t\t\t\t      smsg->ice_version, FALSE,\n\t\t\t\t\t      ssrc_count);\n\t\t\thas_new_media = TRUE;\n\t\t}\n\t}\n\n\tif (has_new_media) {\n\t\tsdpmsg_free(call_private->smsg);\n\t\tcall_private->smsg = smsg;\n\t\tsip_transport_response(sipe_private, call_private->invitation,\n\t\t\t\t       180, \"Ringing\", NULL);\n\t\tcall_schedule_ringing_timeout(SIPE_MEDIA_CALL);\n\t\t// Processing continues in stream_initialized_cb\n\t} else {\n\t\tapply_remote_message(call_private, smsg);\n\t\tsdpmsg_free(smsg);\n\t\tmaybe_send_second_invite_response(call_private);\n\t}\n\n\treturn SIPE_MEDIA_CALL;\n}\n\nvoid process_incoming_cancel_call(struct sipe_media_call_private *call_private,\n\t\t\t\t  struct sipmsg *msg)\n{\n\t// We respond to the CANCEL request with 200 OK response and\n\t// with 487 Request Terminated to the remote INVITE in progress.\n\tsip_transport_response(call_private->sipe_private, msg, 200, \"OK\", NULL);\n\n\tif (call_private->invitation) {\n\t\tsip_transport_response(call_private->sipe_private,\n\t\t\t\t       call_private->invitation,\n\t\t\t\t       487, \"Request Terminated\", NULL);\n\t}\n\n\tsipe_backend_media_reject(SIPE_MEDIA_CALL->backend_private, FALSE);\n}\n\nstatic gboolean\nsipe_media_send_ack(struct sipe_core_private *sipe_private,\n\t\t    struct sipmsg *msg,\n\t\t    struct transaction *trans)\n{\n\tstruct sipe_media_call_private *call_private;\n\tstruct sip_dialog *dialog;\n\tint tmp_cseq;\n\n\tcall_private = sipe_media_from_sipmsg(sipe_private, msg);\n\n\tif (!is_media_session_msg(call_private, msg))\n\t\treturn FALSE;\n\n\tdialog = sipe_media_get_sip_dialog(SIPE_MEDIA_CALL);\n\tif (!dialog)\n\t\treturn FALSE;\n\n\ttmp_cseq = dialog->cseq;\n\n\tdialog->cseq = sip_transaction_cseq(trans) - 1;\n\tsip_transport_ack(sipe_private, dialog);\n\tdialog->cseq = tmp_cseq;\n\n\tdialog->outgoing_invite = NULL;\n\n\treturn TRUE;\n}\n\nstatic gboolean\nsipe_media_send_final_ack(struct sipe_core_private *sipe_private,\n\t\t\t  struct sipmsg *msg,\n\t\t\t  struct transaction *trans)\n{\n\tstruct sipe_media_call_private *call_private;\n#ifdef HAVE_XDATA\n\tGSList *it;\n#endif\n\n\tif (!sipe_media_send_ack(sipe_private, msg, trans))\n\t\treturn FALSE;\n\n\tcall_private = sipe_media_from_sipmsg(sipe_private, msg);\n\n\tsipe_backend_media_accept(SIPE_MEDIA_CALL->backend_private, FALSE);\n\n#ifdef HAVE_XDATA\n\tfor (it = call_private->streams; it; it = it->next) {\n\t\tstruct sipe_media_stream_private *stream_private = it->data;\n\n\t\tstream_private->sdp_negotiation_concluded = TRUE;\n\t\tif (stream_private->writable) {\n\t\t\t// We've become writable.\n\t\t\tsipe_core_media_stream_writable(SIPE_MEDIA_STREAM, TRUE);\n\t\t}\n\t}\n#endif\n\n\treturn TRUE;\n}\n\nvoid\nsipe_core_media_stream_candidate_pair_established(struct sipe_media_stream *stream)\n{\n\tstruct sipe_media_call *call = stream->call;\n\n\tGList *active_candidates =\n\t\t\tsipe_backend_media_stream_get_active_local_candidates(stream);\n\tguint ready_components = g_list_length(active_candidates);\n\n\tsipe_media_candidate_list_free(active_candidates);\n\n\tif (ready_components != 2) {\n\t\t// We must have both RTP+RTCP candidate pairs established first.\n\t\treturn;\n\t}\n\n\tif (SIPE_MEDIA_STREAM_PRIVATE->established) {\n\t\treturn;\n\t}\n\tSIPE_MEDIA_STREAM_PRIVATE->established = TRUE;\n\n\tstream_schedule_cancel_timeout(call, SIPE_MEDIA_STREAM_PRIVATE);\n\n\tif (stream->candidate_pairs_established_cb) {\n\t\tstream->candidate_pairs_established_cb(stream);\n\t}\n\n\tif (sipe_backend_media_is_initiator(stream->call, NULL)) {\n\t\tGSList *streams = SIPE_MEDIA_CALL_PRIVATE->streams;\n\t\tfor (; streams; streams = streams->next) {\n\t\t\tstruct sipe_media_stream_private *s = streams->data;\n\t\t\tif (!s->established) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (streams == NULL) {\n\t\t\t// All call streams have been established.\n\t\t\tsipe_invite_call(SIPE_MEDIA_CALL_PRIVATE,\n\t\t\t\t\t sipe_media_send_final_ack);\n\t\t}\n\t} else {\n\t\tmaybe_send_second_invite_response(SIPE_MEDIA_CALL_PRIVATE);\n\t}\n}\n\nstatic gboolean\nmaybe_retry_call_with_ice_version(struct sipe_core_private *sipe_private,\n\t\t\t\t  struct sipe_media_call_private *call_private,\n\t\t\t\t  SipeIceVersion ice_version,\n\t\t\t\t  struct transaction *trans)\n{\n\tif (call_private->ice_version != ice_version &&\n\t    sip_transaction_cseq(trans) == 1) {\n\t\tGSList *i;\n\t\tgchar *with;\n\t\tgboolean with_video = FALSE;\n\n\t\tfor (i = call_private->streams; i; i = i->next) {\n\t\t\tstruct sipe_media_stream *stream = i->data;\n\n\t\t\tif (sipe_strequal(stream->id, \"video\")) {\n\t\t\t\twith_video = TRUE;\n\t\t\t} else if (!sipe_strequal(stream->id, \"audio\")) {\n\t\t\t\t/* Don't retry calls which are neither audio\n\t\t\t\t * nor video. */\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\twith = g_strdup(SIPE_MEDIA_CALL->with);\n\n\t\tsipe_media_hangup(call_private);\n\t\tSIPE_DEBUG_INFO(\"Retrying call with ICEv%d.\",\n\t\t\t\tice_version == SIPE_ICE_DRAFT_6 ? 6 : 19);\n\t\tsipe_media_initiate_call(sipe_private,\n\t\t\t\t\t with,\n\t\t\t\t\t ice_version,\n\t\t\t\t\t with_video);\n\n\t\tg_free(with);\n\t\treturn TRUE;\n\t}\n\n\treturn FALSE;\n}\n\nstatic gboolean\nprocess_invite_call_response(struct sipe_core_private *sipe_private,\n\t\t\t     struct sipmsg *msg,\n\t\t\t     struct transaction *trans)\n{\n\tconst gchar *with;\n\tstruct sipe_media_call_private *call_private;\n\tstruct sip_dialog *dialog;\n\tstruct sdpmsg *smsg;\n\n\tcall_private = sipe_media_from_sipmsg(sipe_private,msg);\n\n\tif (!is_media_session_msg(call_private, msg))\n\t\treturn FALSE;\n\n\tdialog = sipe_media_get_sip_dialog(SIPE_MEDIA_CALL);\n\n\twith = dialog->with;\n\n\tdialog->outgoing_invite = NULL;\n\n\tif (msg->response == 603 || msg->response == 605) {\n\t\t// Call rejected by remote peer\n\t\tsipe_media_send_ack(sipe_private, msg, trans);\n\t\tsipe_backend_media_reject(SIPE_MEDIA_CALL->backend_private, FALSE);\n\n\t\treturn TRUE;\n\t}\n\n\tif (msg->response >= 400) {\n\t\t// An error occurred\n\t\tconst gchar *title;\n\t\tGString *desc = g_string_new(\"\");\n\t\tgboolean append_responsestr = FALSE;\n\n\t\tswitch (msg->response) {\n\t\t\tcase 480: {\n\t\t\t\ttitle = _(\"User unavailable\");\n\n\t\t\t\tif (sipmsg_parse_warning(msg, NULL) == 391) {\n\t\t\t\t\tg_string_append_printf(desc, _(\"%s does not want to be disturbed\"), with);\n\t\t\t\t} else\n\t\t\t\t\tg_string_append_printf(desc, _(\"User %s is not available\"), with);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 415:\n\t\t\t\t// OCS/Lync really sends response string with 'Mutipart' typo.\n\t\t\t\tif (sipe_strequal(msg->responsestr, \"Mutipart mime in content type not supported by Archiving CDR service\") &&\n\t\t\t\t    maybe_retry_call_with_ice_version(sipe_private,\n\t\t\t\t\t\t\t\t      call_private,\n\t\t\t\t\t\t\t\t      SIPE_ICE_DRAFT_6,\n\t\t\t\t\t\t\t\t      trans)) {\n\t\t\t\t\treturn TRUE;\n\t\t\t\t}\n\t\t\t\ttitle = _(\"Unsupported media type\");\n\t\t\t\tbreak;\n\t\t\tcase 488: {\n\t\t\t\t/* Check for incompatible encryption levels error.\n\t\t\t\t *\n\t\t\t\t * MS Lync 2010:\n\t\t\t\t * 488 Not Acceptable Here\n\t\t\t\t * ms-client-diagnostics: 52017;reason=\"Encryption levels dont match\"\n\t\t\t\t *\n\t\t\t\t * older clients (and SIPE itself):\n\t\t\t\t * 488 Encryption Levels not compatible\n\t\t\t\t */\n\t\t\t\tconst gchar *ms_diag = sipmsg_find_header(msg, \"ms-client-diagnostics\");\n\t\t\t\tSipeIceVersion retry_ice_version = SIPE_ICE_DRAFT_6;\n\n\t\t\t\tif (sipe_strequal(msg->responsestr, \"Encryption Levels not compatible\") ||\n\t\t\t\t    (ms_diag && g_str_has_prefix(ms_diag, \"52017;\"))) {\n\t\t\t\t\ttitle = _(\"Unable to establish a call\");\n\t\t\t\t\tg_string_append(desc, _(\"Encryption settings of peer are incompatible with ours.\"));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/* Check if this is failed conference using\n\t\t\t\t * ICEv6 with reason \"Error parsing SDP\" and\n\t\t\t\t * retry using ICEv19. */\n\t\t\t\tms_diag = sipmsg_find_header(msg, \"ms-diagnostics\");\n\t\t\t\tif (ms_diag && g_str_has_prefix(ms_diag, \"7008;\")) {\n\t\t\t\t\tretry_ice_version = SIPE_ICE_RFC_5245;\n\t\t\t\t}\n\n\t\t\t\tif (maybe_retry_call_with_ice_version(sipe_private,\n\t\t\t\t\t\t\t\t      call_private,\n\t\t\t\t\t\t\t\t      retry_ice_version,\n\t\t\t\t\t\t\t\t      trans)) {\n\t\t\t\t\treturn TRUE;\n\t\t\t\t}\n\t\t\t\tSIPE_FALLTHROUGH\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\ttitle = _(\"Error occurred\");\n\t\t\t\tg_string_append(desc, _(\"Unable to establish a call\"));\n\t\t\t\tappend_responsestr = TRUE;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (append_responsestr) {\n\t\t\tgchar *reason = sipmsg_get_ms_diagnostics_reason(msg);\n\n\t\t\tg_string_append_printf(desc, \"\\n%d %s\",\n\t\t\t\t\t       msg->response, msg->responsestr);\n\t\t\tif (reason) {\n\t\t\t\tg_string_append_printf(desc, \"\\n\\n%s\", reason);\n\t\t\t\tg_free(reason);\n\t\t\t}\n\t\t}\n\n\t\tsipe_backend_notify_error(SIPE_CORE_PUBLIC, title, desc->str);\n\t\tg_string_free(desc, TRUE);\n\n\t\tsipe_media_send_ack(sipe_private, msg, trans);\n\t\tsipe_media_hangup(call_private);\n\n\t\treturn TRUE;\n\t}\n\n\tsipe_dialog_parse(dialog, msg, TRUE);\n\tsmsg = sdpmsg_parse_msg(msg->body);\n\tif (!smsg) {\n\t\ttransport_response_unsupported_sdp(sipe_private, msg);\n\t\tsipe_media_hangup(call_private);\n\t\treturn FALSE;\n\t}\n\n\tssrc_range_update(&call_private->ssrc_ranges, smsg->media);\n\tapply_remote_message(call_private, smsg);\n\tsdpmsg_free(smsg);\n\n\tstream_schedule_timeout(SIPE_MEDIA_CALL);\n\tcall_schedule_cancel_request_timeout(SIPE_MEDIA_CALL);\n\tsipe_media_send_ack(sipe_private, msg, trans);\n\n\treturn TRUE;\n\n\t// Waits until sipe_core_media_candidate_pair_established() is invoked.\n}\n\ngboolean is_media_session_msg(struct sipe_media_call_private *call_private,\n\t\t\t      struct sipmsg *msg)\n{\n\tif (!call_private) {\n\t\treturn FALSE;\n\t}\n\n\treturn sipe_media_from_sipmsg(call_private->sipe_private, msg) == call_private;\n}\n\nstatic void\nend_call(SIPE_UNUSED_PARAMETER gpointer key,\n\t struct sipe_media_call_private *call_private,\n\t SIPE_UNUSED_PARAMETER gpointer user_data)\n{\n\tstruct sipe_backend_media *backend_private;\n\n\tbackend_private = call_private->public.backend_private;\n\n\tif (!sipe_backend_media_is_initiator(SIPE_MEDIA_CALL, NULL) &&\n\t    !sipe_backend_media_accepted(backend_private)) {\n\t\tsip_transport_response(call_private->sipe_private,\n\t\t\t\t       call_private->invitation,\n\t\t\t\t       480, \"Temporarily Unavailable\", NULL);\n\t} else if (call_private->session) {\n\t\tsipe_session_close(call_private->sipe_private,\n\t\t\t\t   call_private->session);\n\t\tcall_private->session = NULL;\n\t}\n\n\tsipe_media_hangup(call_private);\n}\n\nvoid\nsipe_media_handle_going_offline(struct sipe_core_private *sipe_private)\n{\n\tg_hash_table_foreach(sipe_private->media_calls, (GHFunc) end_call, NULL);\n}\n\ngboolean sipe_media_is_conference_call(struct sipe_media_call_private *call_private)\n{\n\treturn g_strstr_len(SIPE_MEDIA_CALL->with, -1, \"app:conf:audio-video:\") != NULL;\n}\n\nstruct sipe_core_private *\nsipe_media_get_sipe_core_private(struct sipe_media_call *call)\n{\n\tg_return_val_if_fail(call, NULL);\n\n\treturn SIPE_MEDIA_CALL_PRIVATE->sipe_private;\n}\n\nstruct sip_dialog *\nsipe_media_get_sip_dialog(struct sipe_media_call *call)\n{\n\tstruct sip_session *session;\n\n\tg_return_val_if_fail(call, NULL);\n\n\tsession = SIPE_MEDIA_CALL_PRIVATE->session;\n\n\tif (!session || !session->dialogs) {\n\t\treturn NULL;\n\t}\n\n\treturn session->dialogs->data;\n}\n\nstatic void\nsipe_media_relay_free(struct sipe_media_relay *relay)\n{\n\tg_free(relay->hostname);\n\tif (relay->dns_query)\n\t\tsipe_backend_dns_query_cancel(relay->dns_query);\n\tg_free(relay);\n}\n\nvoid\nsipe_media_relay_list_free(GSList *list)\n{\n\tfor (; list; list = g_slist_delete_link(list, list))\n\t\tsipe_media_relay_free(list->data);\n}\n\nstatic void\nrelay_ip_resolved_cb(struct sipe_media_relay* relay,\n\t\t     const gchar *ip, SIPE_UNUSED_PARAMETER guint port)\n{\n\tgchar *hostname = relay->hostname;\n\trelay->dns_query = NULL;\n\n\tif (ip && port) {\n\t\trelay->hostname = g_strdup(ip);\n\t\tSIPE_DEBUG_INFO(\"Media relay %s resolved to %s.\", hostname, ip);\n\t} else {\n\t\trelay->hostname = NULL;\n\t\tSIPE_DEBUG_INFO(\"Unable to resolve media relay %s.\", hostname);\n\t}\n\n\tg_free(hostname);\n}\n\nstatic gboolean\nprocess_get_av_edge_credentials_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\t struct sipmsg *msg,\n\t\t\t\t\t SIPE_UNUSED_PARAMETER struct transaction *trans)\n{\n\tg_free(sipe_private->media_relay_username);\n\tg_free(sipe_private->media_relay_password);\n\tsipe_media_relay_list_free(sipe_private->media_relays);\n\tsipe_private->media_relay_username = NULL;\n\tsipe_private->media_relay_password = NULL;\n\tsipe_private->media_relays = NULL;\n\n\tif (msg->response >= 400) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_get_av_edge_credentials_response: SERVICE response is not 200. \"\n\t\t\t\t\t \"Failed to obtain A/V Edge credentials.\");\n\t\treturn FALSE;\n\t}\n\n\tif (msg->response == 200) {\n\t\tsipe_xml *xn_response = sipe_xml_parse(msg->body, msg->bodylen);\n\n\t\tif (sipe_strequal(\"OK\", sipe_xml_attribute(xn_response, \"reasonPhrase\"))) {\n\t\t\tconst sipe_xml *xn_credentials = sipe_xml_child(xn_response, \"credentialsResponse/credentials\");\n\t\t\tconst sipe_xml *xn_relays = sipe_xml_child(xn_response, \"credentialsResponse/mediaRelayList\");\n\t\t\tconst sipe_xml *item;\n\t\t\tGSList *relays = NULL;\n\n\t\t\titem = sipe_xml_child(xn_credentials, \"username\");\n\t\t\tsipe_private->media_relay_username = sipe_xml_data(item);\n\t\t\titem = sipe_xml_child(xn_credentials, \"password\");\n\t\t\tsipe_private->media_relay_password = sipe_xml_data(item);\n\n\t\t\tfor (item = sipe_xml_child(xn_relays, \"mediaRelay\"); item; item = sipe_xml_twin(item)) {\n\t\t\t\tstruct sipe_media_relay *relay = g_new0(struct sipe_media_relay, 1);\n\t\t\t\tconst sipe_xml *node;\n\t\t\t\tgchar *tmp;\n\n\t\t\t\tnode = sipe_xml_child(item, \"hostName\");\n\t\t\t\trelay->hostname = sipe_xml_data(node);\n\n\t\t\t\tnode = sipe_xml_child(item, \"udpPort\");\n\t\t\t\tif (node) {\n\t\t\t\t\ttmp = sipe_xml_data(node);\n\t\t\t\t\tif (tmp) {\n\t\t\t\t\t\trelay->udp_port = atoi(tmp);\n\t\t\t\t\t\tg_free(tmp);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tnode = sipe_xml_child(item, \"tcpPort\");\n\t\t\t\tif (node) {\n\t\t\t\t\ttmp = sipe_xml_data(node);\n\t\t\t\t\tif (tmp) {\n\t\t\t\t\t\trelay->tcp_port = atoi(tmp);\n\t\t\t\t\t\tg_free(tmp);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\trelays = g_slist_append(relays, relay);\n\n\t\t\t\trelay->dns_query = sipe_backend_dns_query_a(\n\t\t\t\t\t\t\tSIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\trelay->hostname,\n\t\t\t\t\t\t\trelay->udp_port,\n\t\t\t\t\t\t\t(sipe_dns_resolved_cb) relay_ip_resolved_cb,\n\t\t\t\t\t\t\trelay);\n\n\t\t\t\tSIPE_DEBUG_INFO(\"Media relay: %s TCP: %d UDP: %d\",\n\t\t\t\t\t\trelay->hostname,\n\t\t\t\t\t\trelay->tcp_port, relay->udp_port);\n\t\t\t}\n\n\t\t\tsipe_private->media_relays = relays;\n\t\t}\n\n\t\tsipe_xml_free(xn_response);\n\t}\n\n\treturn TRUE;\n}\n\nvoid\nsipe_media_get_av_edge_credentials(struct sipe_core_private *sipe_private)\n{\n\t// TODO: re-request credentials after duration expires?\n\tstatic const char CRED_REQUEST_XML[] =\n\t\t\"<request requestID=\\\"%d\\\" \"\n\t\t         \"from=\\\"%s\\\" \"\n\t\t\t \"version=\\\"1.0\\\" \"\n\t\t\t \"to=\\\"%s\\\" \"\n\t\t\t \"xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/mrasp\\\" \"\n\t\t\t \"xmlns:xsi=\\\"http://www.w3.org/2001/XMLSchema-instance\\\">\"\n\t\t\t\"<credentialsRequest credentialsRequestID=\\\"%d\\\">\"\n\t\t\t\t\"<identity>%s</identity>\"\n\t\t\t\t\"<location>%s</location>\"\n\t\t\t\t\"<duration>480</duration>\"\n\t\t\t\"</credentialsRequest>\"\n\t\t\"</request>\";\n\n\tint request_id = rand();\n\tgchar *self;\n\tgchar *body;\n\n\tif (!sipe_private->mras_uri)\n\t\treturn;\n\n\tself = sip_uri_self(sipe_private);\n\n\tbody = g_strdup_printf(\n\t\tCRED_REQUEST_XML,\n\t\trequest_id,\n\t\tself,\n\t\tsipe_private->mras_uri,\n\t\trequest_id,\n\t\tself,\n\t\tSIPE_CORE_PRIVATE_FLAG_IS(REMOTE_USER) ? \"internet\" : \"intranet\");\n\tg_free(self);\n\n\tsip_transport_service(sipe_private,\n\t\t\t      sipe_private->mras_uri,\n\t\t\t      \"Content-Type: application/msrtc-media-relay-auth+xml\\r\\n\",\n\t\t\t      body,\n\t\t\t      process_get_av_edge_credentials_response);\n\n\tg_free(body);\n}\n\nvoid\nsipe_media_add_extra_invite_section(struct sipe_media_call *call,\n\t\t\t\t    const gchar *invite_content_type,\n\t\t\t\t    gchar *body)\n{\n\tg_free(SIPE_MEDIA_CALL_PRIVATE->extra_invite_section);\n\tg_free(SIPE_MEDIA_CALL_PRIVATE->invite_content_type);\n\tSIPE_MEDIA_CALL_PRIVATE->extra_invite_section = body;\n\tSIPE_MEDIA_CALL_PRIVATE->invite_content_type =\n\t\t\tg_strdup(invite_content_type);\n}\n\nvoid\nsipe_media_stream_add_extra_attribute(struct sipe_media_stream *stream,\n\t\t\t\t      const gchar *name, const gchar *value)\n{\n\tSIPE_MEDIA_STREAM_PRIVATE->extra_sdp =\n\t\t\tsipe_utils_nameval_add(SIPE_MEDIA_STREAM_PRIVATE->extra_sdp,\n\t\t\t\t\t       name, value);\n}\n\n#ifdef HAVE_XDATA\nvoid\nsipe_core_media_stream_readable(struct sipe_media_stream *stream)\n{\n\tg_return_if_fail(stream);\n\n\tif (g_queue_is_empty(SIPE_MEDIA_STREAM_PRIVATE->async_reads) &&\n\t    stream->read_cb) {\n\t\tstream->read_cb(stream);\n\t}\n\n\twhile (!g_queue_is_empty(SIPE_MEDIA_STREAM_PRIVATE->async_reads)) {\n\t\tstruct async_read_data *data;\n\t\tguint8 *pos;\n\t\tgssize len;\n\t\tgssize bytes_read;\n\n\t\tdata = g_queue_peek_head(SIPE_MEDIA_STREAM_PRIVATE->async_reads);\n\t\tpos = data->buffer + SIPE_MEDIA_STREAM_PRIVATE->read_pos;\n\t\tlen = data->len - SIPE_MEDIA_STREAM_PRIVATE->read_pos;\n\n\t\tbytes_read = sipe_backend_media_stream_read(stream, pos, len);\n\t\tif (bytes_read == -1) {\n\t\t\tstruct sipe_media_call *call = stream->call;\n\t\t\tstruct sipe_core_private *sipe_private =\n\t\t\t\t\tSIPE_MEDIA_CALL_PRIVATE->sipe_private;\n\n\t\t\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t  _(\"Media error\"),\n\t\t\t\t\t\t  _(\"Error while reading from stream\"));\n\t\t\tsipe_media_hangup(SIPE_MEDIA_CALL_PRIVATE);\n\t\t\treturn;\n\t\t}\n\n\t\tSIPE_MEDIA_STREAM_PRIVATE->read_pos += bytes_read;\n\n\t\tif (SIPE_MEDIA_STREAM_PRIVATE->read_pos == data->len) {\n\t\t\tdata->callback(stream, data->buffer, data->len);\n\t\t\tSIPE_MEDIA_STREAM_PRIVATE->read_pos = 0;\n\t\t\tg_queue_pop_head(SIPE_MEDIA_STREAM_PRIVATE->async_reads);\n\t\t\tg_free(data);\n\t\t} else {\n\t\t\t// Still not enough data to finish the read.\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nvoid\nsipe_media_stream_read_async(struct sipe_media_stream *stream,\n\t\t\t     gpointer buffer, gsize len,\n\t\t\t     sipe_media_stream_read_callback callback)\n{\n\tstruct async_read_data *data;\n\n\tg_return_if_fail(stream && buffer && callback);\n\n\tdata = g_new0(struct async_read_data, 1);\n\tdata->buffer = buffer;\n\tdata->len = len;\n\tdata->callback = callback;\n\n\tg_queue_push_tail(SIPE_MEDIA_STREAM_PRIVATE->async_reads, data);\n}\n\nstatic void\nstream_append_buffer(struct sipe_media_stream *stream,\n\t\t     guint8 *buffer, guint len)\n{\n\tGByteArray *b = g_byte_array_sized_new(len);\n\tg_byte_array_append(b, buffer, len);\n\tg_queue_push_tail(SIPE_MEDIA_STREAM_PRIVATE->write_queue, b);\n}\n\ngboolean\nsipe_media_stream_write(struct sipe_media_stream *stream,\n\t\t\tgpointer buffer, gsize len)\n{\n\tif (!sipe_media_stream_is_writable(stream)) {\n\t\tstream_append_buffer(stream, buffer, len);\n\t\treturn FALSE;\n\t} else {\n\t\tguint written;\n\n\t\twritten = sipe_backend_media_stream_write(stream, buffer, len);\n\t\tif (written == len) {\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tstream_append_buffer(stream,\n\t\t\t\t     (guint8 *)buffer + written, len - written);\n\t\treturn FALSE;\n\t}\n}\n\nvoid\nsipe_core_media_stream_writable(struct sipe_media_stream *stream,\n\t\t\t\tgboolean writable)\n{\n\tSIPE_MEDIA_STREAM_PRIVATE->writable = writable;\n\n\tif (!writable) {\n\t\treturn;\n\t}\n\n\twhile (!g_queue_is_empty(SIPE_MEDIA_STREAM_PRIVATE->write_queue)) {\n\t\tGByteArray *b;\n\t\tguint written;\n\n\t\tb = g_queue_peek_head(SIPE_MEDIA_STREAM_PRIVATE->write_queue);\n\n\t\twritten = sipe_backend_media_stream_write(stream, b->data, b->len);\n\t\tif (written != b->len) {\n\t\t\tg_byte_array_remove_range(b, 0, written);\n\t\t\treturn;\n\t\t}\n\n\t\tg_byte_array_unref(b);\n\t\tg_queue_pop_head(SIPE_MEDIA_STREAM_PRIVATE->write_queue);\n\t}\n\n\tif (sipe_media_stream_is_writable(stream) && stream->writable_cb) {\n\t\tstream->writable_cb(stream);\n\t}\n}\n\ngboolean\nsipe_media_stream_is_writable(struct sipe_media_stream *stream)\n{\n\treturn SIPE_MEDIA_STREAM_PRIVATE->writable &&\n\t       SIPE_MEDIA_STREAM_PRIVATE->sdp_negotiation_concluded &&\n\t       g_queue_is_empty(SIPE_MEDIA_STREAM_PRIVATE->write_queue);\n}\n#endif\n\nvoid\nsipe_media_stream_set_data(struct sipe_media_stream *stream, gpointer data,\n\t\t\t   GDestroyNotify free_func)\n{\n\tstruct sipe_media_stream_private *stream_private =\n\t\t\tSIPE_MEDIA_STREAM_PRIVATE;\n\n\tg_return_if_fail(stream_private);\n\n\tif (stream_private->data && stream_private->data_free_func) {\n\t\tstream_private->data_free_func(stream_private->data);\n\t}\n\n\tstream_private->data = data;\n\tstream_private->data_free_func = free_func;\n}\n\ngpointer\nsipe_media_stream_get_data(struct sipe_media_stream *stream)\n{\n\tg_return_val_if_fail(stream, NULL);\n\n\treturn SIPE_MEDIA_STREAM_PRIVATE->data;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-media.h",
    "content": "/**\n * @file sipe-media.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010 Jakub Adam <jakub.adam@ktknet.cz>\n * Copyright (C) 2016-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sdpmsg;\nstruct sipmsg;\nstruct sipe_core_private;\nstruct sipe_media_call_private;\nstruct sipe_media_stream;\n\ntypedef void (* sipe_media_stream_read_callback)(struct sipe_media_stream *stream,\n\t\t\t\t\t\t guint8 *buffer, gsize len);\n\n/**\n * Creates a new media call.\n *\n * @param sipe_private (in) SIPE core data.\n * @param with (in) SIP URI of the second participant.\n * @param msg (in) SIP INVITE message from the second participant or NULL if we\n *            are the call initiator.\n * @param ice_version (in) version of ICE protocol to use when establishing the\n *                    connection path.\n * @param flags (in) bitwise-or'd media call flags.\n *\n * @return a new @c sipe_media_call structure or @c NULL on error.\n */\nstruct sipe_media_call *\nsipe_media_call_new(struct sipe_core_private *sipe_private, const gchar* with,\n\t\t    struct sipmsg *msg, SipeIceVersion ice_version,\n\t\t    SipeMediaCallFlags flags);\n\n/**\n * Retrieves the @c sipe_media_call structure representing the ongoing call with\n * the given participant.\n *\n * @param sipe_private (in) SIPE core data.\n * @param with (in) SIP URI of the call participant.\n *\n * @return a @c sipe_media_call structure or @c NULL if there isn't a call going\n * on with @c with.\n */\nstruct sipe_media_call *\nsipe_media_call_find(struct sipe_core_private *sipe_private, const gchar *with);\n\n/**\n * Adds a new media stream to a call.\n *\n * @param call (in) a media call.\n * @param id (in) a string identifier for the media stream.\n * @param type (in) a type of stream's content (audio, video, data, ...).\n * @param ice_version (in) a version of ICE to use when negotiating the\n *                    connection.\n * @param initiator (in) @c TRUE if our client is the initiator of the stream.\n * @param ssrc_count (in) number of RTP Synchronization source identifiers to\n *                   allocate for the stream.\n *\n * @return a new @c sipe_media_stream structure or @c NULL on error.\n */\nstruct sipe_media_stream *\nsipe_media_stream_add(struct sipe_media_call *call, const gchar *id,\n\t\t      SipeMediaType type, SipeIceVersion ice_version,\n\t\t      gboolean initiator, guint32 ssrc_count);\n\n/**\n * Handles incoming SIP INVITE message to start a media session.\n *\n * @param sipe_private (in) SIPE core data.\n * @param msg (in) a SIP INVITE message\n * @param sdp (in) media session description string\n *\n * @return @c sipe_media_call structure created or updated by @c msg.\n *         The function returns @c NULL on error or if the call was rejected.\n */\nstruct sipe_media_call *\nprocess_incoming_invite_call(struct sipe_core_private *sipe_private,\n\t\t\t     struct sipmsg *msg,\n\t\t\t     const gchar *sdp);\n\n/**\n * Handles incoming SIP INVITE message to start a media session.\n *\n * @param sipe_private (in) SIPE core data.\n * @param msg (in) a SIP INVITE message\n * @param smsg (in) parsed media session description; the function takes\n *             ownership of the sdpmsg structure and will free it when no longer\n *             needed.\n *\n * @return @c sipe_media_call structure created or updated by @c msg.\n *         The function returns @c NULL on error or if the call was rejected.\n */\nstruct sipe_media_call *\nprocess_incoming_invite_call_parsed_sdp(struct sipe_core_private *sipe_private,\n\t\t\t\t\tstruct sipmsg *msg,\n\t\t\t\t\tstruct sdpmsg *smsg);\n\n/**\n * Handles incoming SIP CANCEL message.\n *\n * @param call_private (in) SIPE media call data.\n * @param msg (in) a SIP CANCEL message\n */\nvoid process_incoming_cancel_call(struct sipe_media_call_private *call_private,\n\t\t\t\t  struct sipmsg *msg);\n\n/**\n * Hangs up a media session and closes all allocated resources.\n *\n * @param sipe_private (in) media call data.\n */\nvoid sipe_media_hangup(struct sipe_media_call_private *call_private);\n\n/**\n * Call before SIP account logs of the server. Function hangs up the call and\n * notifies remote participant according to the actual state of call\n * negotiation.\n *\n * @param sipe_private (in) SIPE core data.\n */\nvoid sipe_media_handle_going_offline(struct sipe_core_private *sipe_private);\n\n/**\n * Checks whether the given media is a conference call.\n *\n * @return @c TRUE if call is a conference, @c FALSE when it is a PC2PC call.\n */\ngboolean sipe_media_is_conference_call(struct sipe_media_call_private *call_private);\n\n/**\n * Retrieves the sipe core structure the given call is associated to.\n *\n * @param call (in) media call data\n *\n * @return @c sipe_core_private structure.\n */\nstruct sipe_core_private *\nsipe_media_get_sipe_core_private(struct sipe_media_call *call);\n\n/**\n * Retrieves a SIP dialog associated with the call.\n *\n * @param call (in) media call data\n *\n * @return a @c sip_dialog structure associated with @c call.\n */\nstruct sip_dialog *\nsipe_media_get_sip_dialog(struct sipe_media_call *call);\n\n/**\n * Checks whether SIP message belongs to the session of the given media call.\n *\n * Test is done on the basis of the Call-ID of the message.\n *\n * @param call_private (in) media call data\n * @param msg (in) a SIP message\n *\n * @return @c TRUE if the SIP message belongs to the media session.\n */\ngboolean is_media_session_msg(struct sipe_media_call_private *call_private,\n\t\t\t      struct sipmsg *msg);\n\n/**\n * Sends a request to mras URI for the credentials to the A/V edge server.\n * Given @c sipe_core_private must have non-NULL mras_uri. When the valid\n * response is received, media_relay_username, media_relay_password and\n * media_relays attributes of the sipe core are filled.\n *\n * @param sipe_private (in) SIPE core data.\n */\nvoid sipe_media_get_av_edge_credentials(struct sipe_core_private *sipe_private);\n\n/**\n * Turns @c call's next INVITE into a MIME multipart message with @c body as\n * the extra part.\n *\n * @param call (in) media call data\n * @param invite_content_type (in) MIME media type of the resulting message,\n *                            e.g. \"multipart/alternative\" or \"multipart/mixed\"\n * @param body (in) content to add as the second part of the INVITE message;\n *             @c call takes ownership of @c body and will free it after use\n */\nvoid\nsipe_media_add_extra_invite_section(struct sipe_media_call *call,\n\t\t\t\t    const gchar *invite_content_type,\n\t\t\t\t    gchar *body);\n\n/**\n * Adds application-specific SDP attribute to the stream. This will be sent as\n * a part of our SIP INVITE alongside standard media description, formatted as:\n *\n *  a=name[:value]\n *\n * @param stream (in) media stream data\n * @param name (in) attribute name\n * @param value (in) optional value of the attribute\n */\nvoid\nsipe_media_stream_add_extra_attribute(struct sipe_media_stream *stream,\n\t\t\t\t      const gchar *name, const gchar *value);\n\n/**\n * Schedules asynchronous read of @c len bytes from @c stream into @c buffer.\n * When enough data becomes available in the stream, the buffer is filled and\n * @c callback gets invoked.\n *\n * It's possible to call sipe_media_stream_read_async() multiple times; every\n * request is placed into a FIFO queue. Media core does not call @c read_cb of\n * @c stream while there is some asynchronous read in progress.\n *\n * @param stream (in) media stream data\n * @param buffer (in) an empty data buffer\n * @param len (in) length of @c buffer\n * @param callback (in) a function to call when @c buffer gets filled with\n *                 input data\n */\nvoid\nsipe_media_stream_read_async(struct sipe_media_stream *stream,\n\t\t\t     gpointer buffer, gsize len,\n\t\t\t     sipe_media_stream_read_callback callback);\n\n/**\n * Writes @c len bytes from @c buffer into @c stream.\n *\n * If @c stream is not in writable state, Sipe will store the data in\n * an internal queue which gets emptied once the stream becomes writable again.\n * Users should check the stream state using sipe_media_stream_is_writable()\n * before sending excessive data into the stream.\n *\n * @param stream (in) media stream data\n * @param buffer (in) data to send\n * @param len (in) length of @c buffer\n *\n * @return @c TRUE when @c buffer was written into the stream as a whole,\n *         @c FALSE when some data had to be queued for later (and thus\n *         the stream is now in unwritable state).\n */\ngboolean\nsipe_media_stream_write(struct sipe_media_stream *stream,\n\t\t\tgpointer buffer, gsize len);\n\n/**\n * Checks whether a @c SIPE_MEDIA_APPLICATION stream is in writable state.\n *\n * @param stream (in) media stream data\n *\n * @return @c TRUE if @c stream is writable, otherwise @c FALSE.\n */\ngboolean\nsipe_media_stream_is_writable(struct sipe_media_stream *stream);\n\n/**\n * Associates user data with the media stream.\n *\n * @param stream (in) media stream data\n * @param data (in) user data\n * @param free_func (in) function to free @c data when @c stream is destroyed\n */\nvoid\nsipe_media_stream_set_data(struct sipe_media_stream *stream, gpointer data,\n\t\t\t   GDestroyNotify free_func);\n\n/**\n * Returns user data associated with the media stream.\n *\n * @param stream (in) media stream data\n *\n * @return user data\n */\ngpointer\nsipe_media_stream_get_data(struct sipe_media_stream *stream);\n\n/**\n * Deallocates the opaque list of media relay structures\n *\n * @param list (in) GSList to free\n */\nvoid sipe_media_relay_list_free(GSList *list);\n"
  },
  {
    "path": "src/core/sipe-mime-common.c",
    "content": "/**\n * @file sipe-mime.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2015 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipe-mime.h\"\n#include \"sipe-utils.h\"\n\nstruct parts_contain_cb_data {\n\tconst gchar * type;\n\tgboolean result;\n};\n\nstatic void\nparts_contain_cb(gpointer user_data, const GSList *fields,\n\t\t SIPE_UNUSED_PARAMETER const gchar *body,\n\t\t SIPE_UNUSED_PARAMETER gsize length)\n{\n\tstruct parts_contain_cb_data *data = user_data;\n\n\tif (!data->result &&\n\t    sipe_strequal(data->type, sipe_utils_nameval_find(fields, \"Content-Type\"))) {\n\t\tdata->result = TRUE;\n\t}\n}\n\ngboolean\nsipe_mime_parts_contain(const gchar *type,\n\t\t\tconst gchar *body,\n\t\t\tconst gchar *part_type)\n{\n\tstruct parts_contain_cb_data data;\n\tdata.type = part_type;\n\tdata.result = FALSE;\n\n\tsipe_mime_parts_foreach(type, body, parts_contain_cb, &data);\n\treturn data.result;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-mime.c",
    "content": "/**\n * @file sipe-mime.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2017 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <string.h>\n\n#include \"sipe-common.h\"\n\n#include <glib.h>\n\n/*\n * GMIME interfaces fail to compile on ARM architecture with -Wcast-align\n *\n * Diagnostic #pragma was added in GCC 4.2.0\n */\n#if defined(__GNUC__)\n#if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) || (__GNUC__ >= 5)\n#if defined(__ARMEL__) || defined(__ARMEB__) || defined(__mips__) || defined(__sparc__) || (defined(__powerpc__) && defined(__NO_FPRS__))\n#pragma GCC diagnostic ignored \"-Wcast-align\"\n#endif\n#endif\n#endif\n\n#include <gmime/gmime.h>\n\n#if !GMIME_CHECK_VERSION(2,6,0)\n#error GMime >= 2.6.0 is required to build SIPE\n#endif\n\n#if !GMIME_CHECK_VERSION(3,0,0)\n#define g_mime_part_get_content(p)         g_mime_part_get_content_object(p)\n#define g_mime_parser_construct_part(p, o) g_mime_parser_construct_part(p)\n#endif\n\n#include \"sipe-mime.h\"\n\n#include \"sipe-backend.h\"\n#include \"sipe-utils.h\"\n\nvoid sipe_mime_init(void)\n{\n\tg_mime_init(\n#if !GMIME_CHECK_VERSION(3,0,0)\n\t\t0\n#endif\n\t);\n}\n\nvoid sipe_mime_shutdown(void)\n{\n\tg_mime_shutdown();\n}\n\nstruct gmime_callback_data {\n\tsipe_mime_parts_cb callback;\n\tgpointer user_data;\n};\n\nstatic GSList *gmime_fields_to_nameval(GMimeObject *part)\n{\n\tGMimeHeaderList *headers = g_mime_object_get_header_list(part);\n\tGSList *fields = NULL;\n#if GMIME_CHECK_VERSION(3,0,0)\n\tguint count = g_mime_header_list_get_count(headers);\n\tguint index;\n\n\tfor (index = 0; index < count; index++) {\n\t\tGMimeHeader *header = g_mime_header_list_get_header_at(headers,\n\t\t\t\t\t\t\t\t       index);\n\t\tfields = sipe_utils_nameval_add(fields,\n\t\t\t\t\t\tg_mime_header_get_name(header),\n\t\t\t\t\t\tg_mime_header_get_value(header));\n\t}\n#else\n\tGMimeHeaderIter *iter = g_mime_header_iter_new();\n\n\tif (g_mime_header_list_get_iter(headers, iter)) {\n\t\tdo {\n\t\t\tfields = sipe_utils_nameval_add(fields,\n\t\t\t\t\t\t\tg_mime_header_iter_get_name(iter),\n\t\t\t\t\t\t\tg_mime_header_iter_get_value(iter));\n\t\t} while (g_mime_header_iter_next(iter));\n\t}\n\tg_mime_header_iter_free(iter);\n#endif\n\n\treturn fields;\n}\n\nstatic void gmime_callback(SIPE_UNUSED_PARAMETER GMimeObject *parent,\n\t\t\t   GMimeObject *part,\n\t\t\t   gpointer user_data)\n{\n\tGMimeDataWrapper *data = g_mime_part_get_content((GMimePart *)part);\n\n\tif (data) {\n\t\tGMimeStream *stream = g_mime_data_wrapper_get_stream(data);\n\n\t\tif (stream) {\n\t\t\tssize_t length = 0;\n\t\t\tconst char *encoding;\n\t\t\tgchar *buffer;\n\t\t\tGString *content;\n\n\t\t\tencoding = g_mime_object_get_header(part,\n\t\t\t\t\t\"Content-Transfer-Encoding\");\n\t\t\tif (encoding) {\n\t\t\t\tGMimeFilter *filter = g_mime_filter_basic_new(\n\t\t\t\t\t\tg_mime_content_encoding_from_string(encoding), FALSE);\n\t\t\t\tstream = g_mime_stream_filter_new (stream);\n\t\t\t\tg_mime_stream_filter_add(GMIME_STREAM_FILTER(stream), filter);\n\t\t\t\tg_object_unref (filter);\n\t\t\t}\n\n\t\t\t/* g_mime_stream_read() might not read everything in one call */\n\t\t\tcontent = g_string_new(NULL);\n\t\t\tbuffer = g_malloc(4096);\n\t\t\twhile ((length = g_mime_stream_read(stream, buffer, 4096)) > 0) {\n\t\t\t\tg_string_append_len(content, buffer, length);\n\t\t\t}\n\t\t\tg_free(buffer);\n\n\t\t\tif (length == 0) {\n\t\t\t\tstruct gmime_callback_data *cd = user_data;\n\t\t\t\tGSList *fields = gmime_fields_to_nameval(part);\n\n\t\t\t\tcd->callback(cd->user_data, fields,\n\t\t\t\t\t\tcontent->str, content->len);\n\n\t\t\t\tsipe_utils_nameval_free(fields);\n\t\t\t}\n\n\t\t\tg_string_free(content, TRUE);\n\n\t\t\tif (encoding) {\n\t\t\t\t// Unref GMimeStreamFilter wrapping GMimeStream.\n\t\t\t\tg_object_unref(stream);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid sipe_mime_parts_foreach(const gchar *type,\n\t\t\t     const gchar *body,\n\t\t\t     sipe_mime_parts_cb callback,\n\t\t\t     gpointer user_data)\n{\n\tgchar *doc = g_strdup_printf(\"Content-Type: %s\\r\\n\\r\\n%s\", type, body);\n\tGMimeStream *stream = g_mime_stream_mem_new_with_buffer(doc, strlen(doc));\n\n\tif (stream) {\n\t\tGMimeParser *parser = g_mime_parser_new_with_stream(stream);\n\t\tGMimeMultipart *multipart = (GMimeMultipart *)g_mime_parser_construct_part(parser,\n\t\t\t\t\t\t\t\t\t\t\t   NULL);\n\n\t\tif (multipart) {\n\t\t\tstruct gmime_callback_data cd = {callback, user_data};\n\n\t\t\tSIPE_DEBUG_INFO(\"sipe_mime_parts_foreach: %d parts\", g_mime_multipart_get_count(multipart));\n\n\t\t\tg_mime_multipart_foreach(multipart, gmime_callback, &cd);\n\t\t\tg_object_unref(multipart);\n\t\t}\n\n\t\tg_object_unref(parser);\n\t\tg_object_unref(stream);\n\t}\n\tg_free(doc);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-msrtp.c",
    "content": "/**\n * @file sipe-msrtp.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipe-core.h\"\n\n#define _SIPE_WRITE(where, idx, size, shift, value) \\\n    ((guint8 *) where)[idx] = (((guint##size)value) >> shift) & 0xff\n\n#define SIPE_WRITE_UINT8(where, value) \\\n\t_SIPE_WRITE(where++, 0, 8, 0, value);\n\n#define SIPE_WRITE_UINT16_BE(where, value) \\\n\t_SIPE_WRITE(where, 0, 16, 8, value); \\\n\t_SIPE_WRITE(where, 1, 16, 0, value); \\\n\twhere += 2;\n\n#define SIPE_WRITE_UINT32_BE(where, value) \\\n\t_SIPE_WRITE(where, 0, 32, 24, value); \\\n\t_SIPE_WRITE(where, 1, 32, 16, value); \\\n\t_SIPE_WRITE(where, 2, 32,  8, value); \\\n\t_SIPE_WRITE(where, 3, 32,  0, value); \\\n\twhere += 4;\n\n#define SIPE_WRITE_UINT64_BE(where, value) \\\n\t_SIPE_WRITE(where, 0, 64, 56, value); \\\n\t_SIPE_WRITE(where, 1, 64, 48, value); \\\n\t_SIPE_WRITE(where, 2, 64, 40, value); \\\n\t_SIPE_WRITE(where, 3, 64, 32, value); \\\n\t_SIPE_WRITE(where, 4, 64, 24, value); \\\n\t_SIPE_WRITE(where, 5, 64, 16, value); \\\n\t_SIPE_WRITE(where, 6, 64,  8, value); \\\n\t_SIPE_WRITE(where, 7, 64,  0, value); \\\n\twhere += 8;\n\nenum\n{\n\tVSR_FLAG_NONE = 0,\n\tVSR_FLAG_H264_CGS_REWRITE = 1,\n\tVSR_FLAG_H264_CONSTRAINED_PROFILE_ONLY = 2,\n\tVSR_FLAG_RT_NO_SP_FRAMES = 4,\n\tVSR_FLAG_H264_NO_SEAMLESS_RESOLUTION_CHANGE = 8\n};\n\nenum\n{\n\tVSR_ASPECT_4_BY_3 = 1,\n\tVSR_ASPECT_16_BY_9 = 2,\n\tVSR_ASPECT_1_BY_1 = 4,\n\tVSR_ASPECT_3_BY_4 = 8,\n\tVSR_ASPECT_9_BY_16 = 16,\n\tVSR_ASPECT_20_BY_3 = 32,\n};\n\nenum\n{\n\tVSR_FPS_7_5 = 1,\n\tVSR_FPS_12_5 = 2,\n\tVSR_FPS_15 = 4,\n\tVSR_FPS_25 = 8,\n\tVSR_FPS_30 = 16,\n\tVSR_FPS_50 = 32,\n\tVSR_FPS_60 = 64\n};\n\nenum\n{\n\tNAL_UNIT_TYPE_SEI = 6,\n\tNAL_UNIT_TYPE_PACSI = 30\n};\n\nenum\n{\n\tMS_LD_FPS_IDX_7_5 = 0,\n\tMS_LD_FPS_IDX_12_5 = 1,\n\tMS_LD_FPS_IDX_15 = 2,\n\tMS_LD_FPS_IDX_25 = 3,\n\tMS_LD_FPS_IDX_30 = 4,\n\tMS_LD_FPS_IDX_50 = 5,\n\tMS_LD_FPS_IDX_60 = 6\n};\n\nvoid\nsipe_core_msrtp_write_video_source_request(guint8 *buffer,\n\t\t\t\t\t   guint8 payload_type,\n\t\t\t\t\t   guint32 media_source_id)\n{\n\tstatic guint8 bit_rate_histogram[] = {\n\t\t0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n\t};\n\n\tstatic guint8 quality_report_histogram[] = {\n\t\t0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n\t};\n\n\t/* VSR FCI field - from [MS-RTP] 2.2.12.2 */\n\n\t/* Header */\n\n\tSIPE_WRITE_UINT16_BE(buffer, 0x1); // AFB Type\n\t// Length\n\tSIPE_WRITE_UINT16_BE(buffer, SIPE_MSRTP_VSR_HEADER_LEN +\n\t\t\t     SIPE_MSRTP_VSR_ENTRY_LEN);\n\t// Requested Media Source ID\n\tSIPE_WRITE_UINT32_BE(buffer, media_source_id);\n\tSIPE_WRITE_UINT16_BE(buffer, 1); // Request Id\n\tSIPE_WRITE_UINT16_BE(buffer, 0); // Reserve1\n\tSIPE_WRITE_UINT8(buffer, 0); // Version\n\tSIPE_WRITE_UINT8(buffer, 0 << 7); // Keyframe (1bit) + Reserve2\n\tSIPE_WRITE_UINT8(buffer, 1); // Number of Entries\n\tSIPE_WRITE_UINT8(buffer, SIPE_MSRTP_VSR_ENTRY_LEN); // Entry Length\n\tSIPE_WRITE_UINT32_BE(buffer, 0x0); // Reserve3\n\n\t/* Entry */\n\n\tSIPE_WRITE_UINT8(buffer, payload_type); // Payload Type\n\tSIPE_WRITE_UINT8(buffer, 1); // UCConfig Mode\n\tSIPE_WRITE_UINT8(buffer, VSR_FLAG_NONE); // Flags\n\tSIPE_WRITE_UINT8(buffer, VSR_ASPECT_4_BY_3); // Aspect Ratio Bit Mask\n\tSIPE_WRITE_UINT16_BE(buffer, 432); // Maximum Width\n\tSIPE_WRITE_UINT16_BE(buffer, 432); // Maximum Height\n\tSIPE_WRITE_UINT32_BE(buffer, 350000); // Minimum bit rate\n\tSIPE_WRITE_UINT32_BE(buffer, 0); // Reserve\n\tSIPE_WRITE_UINT32_BE(buffer, 10000); // Bit rate per level\n\t// Bit rate Histogram\n\tmemcpy(buffer, bit_rate_histogram, sizeof (bit_rate_histogram));\n\tbuffer += sizeof (bit_rate_histogram);\n\tSIPE_WRITE_UINT32_BE(buffer, VSR_FPS_15); // Frame rate bit mask\n\tSIPE_WRITE_UINT16_BE(buffer, 0); // Number of MUST instances\n\tSIPE_WRITE_UINT16_BE(buffer, 1); // Number of MAY instances\n\t// Quality Report Histogram\n\tmemcpy(buffer, quality_report_histogram,\n\t       sizeof (quality_report_histogram));\n\tbuffer += sizeof (quality_report_histogram);\n\tSIPE_WRITE_UINT32_BE(buffer, 103680); // Maximum number of pixels\n}\n\nstatic void\nwrite_nal_unit_header(guint8 *dest, gboolean f_bit, guint8 nal_ref_idc,\n\t\t      guint8 type)\n{\n\t*dest = f_bit ? 0x80 : 0x00;\n\t*dest |= nal_ref_idc << 5;\n\t*dest |= type;\n}\n\nstatic void\nwrite_ms_layer_description(guint8 *buffer, guint16 width, guint16 height,\n\t\t\t   guint32 bitrate, guint8 framerate_idx,\n\t\t\t   gboolean base_layer, guint16 prid,\n\t\t\t   gboolean constrained_baseline)\n{\n\t// Coded width and height\n\tSIPE_WRITE_UINT16_BE(buffer, width);\n\tSIPE_WRITE_UINT16_BE(buffer, height);\n\n\t// Display width and height\n\tSIPE_WRITE_UINT16_BE(buffer, width);\n\tSIPE_WRITE_UINT16_BE(buffer, height);\n\n\tSIPE_WRITE_UINT32_BE(buffer, bitrate);\n\n\t*buffer = framerate_idx << 3;\n\t*buffer |= base_layer ? 0 : 1;\n\t++buffer;\n\n\t*buffer = prid << 2;\n\t*buffer |= (constrained_baseline ? 1 : 0) << 1;\n}\n\ngsize\nsipe_core_msrtp_write_video_scalability_info(guint8 *buffer, guint8 nal_count)\n{\n\tstatic const guint8 MS_STREAM_LAYOUT_SEI_UUID[] = {\n\t\t0x13, 0x9f, 0xb1, 0xa9, 0x44, 0x6a, 0x4d, 0xec, 0x8c, 0xbf,\n\t\t0x65, 0xb1, 0xe1, 0x2d, 0x2c, 0xfd\n\t};\n\n\tstatic const guint8 MS_BITSTREAM_INFO_SEI_UUID[] = {\n\t\t0x05, 0xfb, 0xc6, 0xb9, 0x5a, 0x80, 0x40, 0xe5, 0xa2, 0x2a,\n\t\t0xab, 0x40, 0x20, 0x26, 0x7e, 0x26\n\t};\n\n\tguint8 *ptr = buffer;\n\n\t// Write PACSI (RFC6190 section 4.9)\n\tSIPE_WRITE_UINT32_BE(ptr, 77); // Length of the NAL\n\n\twrite_nal_unit_header(ptr++, FALSE, 3, NAL_UNIT_TYPE_PACSI);\n\n\t*ptr = 1 << 7; // Reserved bit = 1\n\t*ptr |= 1 << 6; // I-bit = 1 if any aggregated unit has it set to 1\n\t*ptr |= 0; // Priority = 0\n\t++ptr;\n\n\t*ptr = 1 << 7; // No Inter Layer Prediction = True\n\t*ptr |= 0 << 4; // Dependency ID = 0\n\t*ptr |= 0; // Quality ID\n\t++ptr;\n\n\t*ptr = 0; // Temporal ID\n\t*ptr |= 0 << 4; // Use Ref Base Picture = False\n\t*ptr |= 0 << 3; // Discardable = False\n\t*ptr |= 1 << 2; // Output = True\n\t*ptr |= 3; // Reserved\n\t++ptr;\n\n\t// X|Y|T|A|P|C|S|E flags: DONC & First NAL = True\n\tSIPE_WRITE_UINT8(ptr, 0x22);\n\n\tSIPE_WRITE_UINT16_BE(ptr, 1); // Cross Session Decoder Order Number\n\n\t// Stream Layout SEI Message (MS-H264PF section 2.2.5)\n\tSIPE_WRITE_UINT16_BE(ptr, 45); // Size of the NAL\n\n\twrite_nal_unit_header(ptr++, FALSE, 0, NAL_UNIT_TYPE_SEI);\n\n\tSIPE_WRITE_UINT8(ptr, 5); // Payload type (user data unregistered)\n\tSIPE_WRITE_UINT8(ptr, 42); // Payload size\n\n\tmemcpy(ptr, MS_STREAM_LAYOUT_SEI_UUID,\n\t       sizeof (MS_STREAM_LAYOUT_SEI_UUID));\n\tptr += sizeof (MS_STREAM_LAYOUT_SEI_UUID);\n\n\t// Layer Presence - layer with PRID 0 present\n\tSIPE_WRITE_UINT64_BE(ptr, 0x0100000000000000);\n\n\tSIPE_WRITE_UINT8(ptr, 1); // Layer Description Present = True\n\tSIPE_WRITE_UINT8(ptr, 16); // Layer Description Size\n\n\twrite_ms_layer_description(ptr, 212, 160, 50250, MS_LD_FPS_IDX_7_5,\n\t\t\t\t   TRUE, 0, TRUE);\n\tptr += 16;\n\n\t// MS Bitstream Info SEI Message ([MS-H264PF] section 2.2.7)\n\tSIPE_WRITE_UINT16_BE(ptr, 21); // Size of the NAL\n\n\twrite_nal_unit_header(ptr++, FALSE, 0, NAL_UNIT_TYPE_SEI);\n\n\tSIPE_WRITE_UINT8(ptr, 5); // Payload type (user data unregistered)\n\tSIPE_WRITE_UINT8(ptr, 18); // Payload size\n\n\tmemcpy(ptr, MS_BITSTREAM_INFO_SEI_UUID,\n\t       sizeof (MS_BITSTREAM_INFO_SEI_UUID));\n\tptr += sizeof (MS_BITSTREAM_INFO_SEI_UUID);\n\n\t/* Reference frame count. This should increment with each reference\n\t * frame, but clients apparently don't care about the value. */\n\tSIPE_WRITE_UINT8(ptr, 1);\n\t// Number of NAL units described by this PACSI NAL unit.\n\tSIPE_WRITE_UINT8(ptr, nal_count);\n\n\treturn ptr - buffer;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-notify.c",
    "content": "/**\n * @file sipe-notify.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * Process incoming SIP NOTIFY/BENOTIFY messages\n *\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipmsg.h\"\n#include \"sip-csta.h\"\n#include \"sip-soap.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-buddy.h\"\n#include \"sipe-cal.h\"\n#include \"sipe-conf.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-group.h\"\n#include \"sipe-groupchat.h\"\n#include \"sipe-media.h\"\n#include \"sipe-mime.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-notify.h\"\n#include \"sipe-ocs2005.h\"\n#include \"sipe-ocs2007.h\"\n#include \"sipe-status.h\"\n#include \"sipe-subscriptions.h\"\n#include \"sipe-ucs.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n\n/* OCS2005 */\nstatic void sipe_process_provisioning(struct sipe_core_private *sipe_private,\n\t\t\t\t      struct sipmsg *msg)\n{\n\tsipe_xml *xn_provision;\n\tconst sipe_xml *node;\n\n\txn_provision = sipe_xml_parse(msg->body, msg->bodylen);\n\tif ((node = sipe_xml_child(xn_provision, \"user\"))) {\n\t\tSIPE_DEBUG_INFO(\"sipe_process_provisioning: uri=%s\", sipe_xml_attribute(node, \"uri\"));\n\t\tif ((node = sipe_xml_child(node, \"line\"))) {\n\t\t\tconst gchar *line_uri = sipe_xml_attribute(node, \"uri\");\n\t\t\tconst gchar *server = sipe_xml_attribute(node, \"server\");\n\t\t\tSIPE_DEBUG_INFO(\"sipe_process_provisioning: line_uri=%s server=%s\", line_uri, server);\n\t\t\tsip_csta_open(sipe_private, line_uri, server);\n\t\t}\n\t}\n\tsipe_xml_free(xn_provision);\n}\n\n/* OCS2007+ */\nstatic void sipe_process_provisioning_v2(struct sipe_core_private *sipe_private,\n\t\t\t\t\t struct sipmsg *msg)\n{\n#define READ_INT_FROM_NODE(node_name, field) { \\\n\tgchar *s = g_strstrip(sipe_xml_data(sipe_xml_child(node, node_name))); \\\n\tsipe_private->field = s ? atoi(s) : 0; \\\n\tg_free(s); }\n\n\tsipe_xml *xn_provision_group_list;\n\tconst sipe_xml *node;\n\n\txn_provision_group_list = sipe_xml_parse(msg->body, msg->bodylen);\n\n\t/* provisionGroup */\n\tfor (node = sipe_xml_child(xn_provision_group_list, \"provisionGroup\");\n\t     node;\n\t     node = sipe_xml_twin(node)) {\n\t\tconst gchar *node_name = sipe_xml_attribute(node, \"name\");\n\n\t\t/* ServerConfiguration */\n\t\tif (sipe_strequal(\"ServerConfiguration\", node_name)) {\n\t\t\tconst gchar *dlx_uri_str = SIPE_CORE_PRIVATE_FLAG_IS(REMOTE_USER) ?\n\t\t\t\t\t\"dlxExternalUrl\" : \"dlxInternalUrl\";\n\t\t\tconst gchar *addressbook_uri_str = SIPE_CORE_PRIVATE_FLAG_IS(REMOTE_USER) ?\n\t\t\t\t\t\"absExternalServerUrl\" : \"absInternalServerUrl\";\n\t\t\tgchar *ucPC2PCAVEncryption = NULL;\n\t\t\tgchar *ucPortRangeEnabled = NULL;\n\n\t\t\tg_free(sipe_private->focus_factory_uri);\n\t\t\tsipe_private->focus_factory_uri = sipe_xml_data(sipe_xml_child(node, \"focusFactoryUri\"));\n\t\t\tSIPE_DEBUG_INFO(\"sipe_process_provisioning_v2: sipe_private->focus_factory_uri=%s\",\n\t\t\t\t\tsipe_private->focus_factory_uri ? sipe_private->focus_factory_uri : \"\");\n\n\t\t\tg_free(sipe_private->dlx_uri);\n\t\t\tsipe_private->dlx_uri = sipe_xml_data(sipe_xml_child(node, dlx_uri_str));\n\t\t\tSIPE_DEBUG_INFO(\"sipe_process_provisioning_v2: sipe_private->dlx_uri=%s\",\n\t\t\t\t\tsipe_private->dlx_uri ? sipe_private->dlx_uri : \"\");\n\n\t\t\tg_free(sipe_private->addressbook_uri);\n\t\t\tsipe_private->addressbook_uri = sipe_xml_data(sipe_xml_child(node, addressbook_uri_str));\n\t\t\tSIPE_DEBUG_INFO(\"sipe_process_provisioning_v2: sipe_private->addressbook_uri=%s\",\n\t\t\t\t\tsipe_private->addressbook_uri ? sipe_private->addressbook_uri : \"\");\n\n#ifdef HAVE_VV\n\t\t\tg_free(sipe_private->test_call_bot_uri);\n\t\t\tsipe_private->test_call_bot_uri = sipe_xml_data(sipe_xml_child(node, \"botSipUriForTestCall\"));\n\t\t\tSIPE_DEBUG_INFO(\"sipe_process_provisioning_v2: sipe_private->test_call_bot_uri=%s\",\n\t\t\t\t\tsipe_private->test_call_bot_uri ? sipe_private->test_call_bot_uri : \"\");\n\n\t\t\tg_free(sipe_private->mras_uri);\n\t\t\tsipe_private->mras_uri = g_strstrip(sipe_xml_data(sipe_xml_child(node, \"mrasUri\")));\n\t\t\tSIPE_DEBUG_INFO(\"sipe_process_provisioning_v2: sipe_private->mras_uri=%s\",\n\t\t\t\t\tsipe_private->mras_uri ? sipe_private->mras_uri : \"\");\n\n\t\t\tif (sipe_private->mras_uri)\n\t\t\t\t\tsipe_media_get_av_edge_credentials(sipe_private);\n#endif\n\n\t\t\tucPC2PCAVEncryption = g_strstrip(sipe_xml_data(sipe_xml_child(node, \"ucPC2PCAVEncryption\")));\n\t\t\tif (sipe_strequal(ucPC2PCAVEncryption, \"SupportEncryption\")) {\n\t\t\t\tsipe_private->server_av_encryption_policy = SIPE_ENCRYPTION_POLICY_OPTIONAL;\n\t\t\t} else if (sipe_strequal(ucPC2PCAVEncryption, \"DoNotSupportEncryption\")) {\n\t\t\t\tsipe_private->server_av_encryption_policy = SIPE_ENCRYPTION_POLICY_REJECTED;\n\t\t\t} else {\n\t\t\t\t// \"RequireEncryption\" or any unknown value.\n\t\t\t\tsipe_private->server_av_encryption_policy = SIPE_ENCRYPTION_POLICY_REQUIRED;\n\t\t\t}\n\t\t\tg_free(ucPC2PCAVEncryption);\n\n\t\t\tucPortRangeEnabled = g_strstrip(sipe_xml_data(sipe_xml_child(node, \"ucPortRangeEnabled\")));\n\t\t\tif (sipe_strequal(ucPortRangeEnabled, \"true\")) {\n\t\t\t\tREAD_INT_FROM_NODE(\"ucMinMediaPort\", min_media_port)\n\t\t\t\tREAD_INT_FROM_NODE(\"ucMaxMediaPort\", max_media_port)\n\t\t\t\tREAD_INT_FROM_NODE(\"ucMinAudioPort\", min_audio_port)\n\t\t\t\tREAD_INT_FROM_NODE(\"ucMaxAudioPort\", max_audio_port)\n\t\t\t\tREAD_INT_FROM_NODE(\"ucMinVideoPort\", min_video_port)\n\t\t\t\tREAD_INT_FROM_NODE(\"ucMaxVideoPort\", max_video_port)\n\t\t\t\tREAD_INT_FROM_NODE(\"ucMinAppSharingPort\", min_appsharing_port)\n\t\t\t\tREAD_INT_FROM_NODE(\"ucMaxAppSharingPort\", max_appsharing_port)\n\t\t\t\tREAD_INT_FROM_NODE(\"ucMinFileTransferPort\", min_filetransfer_port)\n\t\t\t\tREAD_INT_FROM_NODE(\"ucMaxFileTransferPort\", max_filetransfer_port)\n\t\t\t} else {\n\t\t\t\tsipe_private->min_media_port = 0;\n\t\t\t\tsipe_private->max_media_port = 0;\n\t\t\t\tsipe_private->min_audio_port = 0;\n\t\t\t\tsipe_private->max_audio_port = 0;\n\t\t\t\tsipe_private->min_video_port = 0;\n\t\t\t\tsipe_private->max_video_port = 0;\n\t\t\t\tsipe_private->min_appsharing_port = 0;\n\t\t\t\tsipe_private->max_appsharing_port = 0;\n\t\t\t\tsipe_private->min_filetransfer_port = 0;\n\t\t\t\tsipe_private->max_filetransfer_port = 0;\n\t\t\t}\n\t\t\tg_free(ucPortRangeEnabled);\n\n\t\t/* persistentChatConfiguration */\n\t\t} else if (sipe_strequal(\"persistentChatConfiguration\", node_name)) {\n\t\t\tconst sipe_xml *property;\n\t\t\tgboolean enabled = FALSE;\n\t\t\tgchar *uri = NULL;\n\n\t\t\tfor (property = sipe_xml_child(node, \"propertyEntryList/property\");\n\t\t\t     property;\n\t\t\t     property = sipe_xml_twin(property)) {\n\t\t\t\tconst gchar *name = sipe_xml_attribute(property, \"name\");\n\t\t\t\tgchar *value = sipe_xml_data(property);\n\n\t\t\t\tif (sipe_strequal(name, \"EnablePersistentChat\")) {\n\t\t\t\t\tenabled = sipe_strequal(value, \"true\");\n\n\t\t\t\t} else if (sipe_strequal(name, \"DefaultPersistentChatPoolUri\")) {\n\t\t\t\t\tg_free(uri);\n\t\t\t\t\turi = value;\n\t\t\t\t\tvalue = NULL;\n\t\t\t\t}\n\t\t\t\tg_free(value);\n\t\t\t}\n\n\t\t\tif (enabled) {\n\t\t\t\tg_free(sipe_private->persistentChatPool_uri);\n\t\t\t\tsipe_private->persistentChatPool_uri = g_strdup(sipe_get_no_sip_uri(uri));\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_process_provisioning_v2: sipe_private->persistentChatPool_uri=%s\",\n\t\t\t\t\t\tsipe_private->persistentChatPool_uri ? sipe_private->persistentChatPool_uri : \"\");\n\t\t\t}\n\t\t\tg_free(uri);\n\t\t}\n\n\t}\n\tsipe_xml_free(xn_provision_group_list);\n\n\tif (sipe_private->dlx_uri && sipe_private->addressbook_uri) {\n\t\t/* Some buddies might have been added before we received this\n\t\t * provisioning notify with DLX and addressbook URIs. Now we can\n\t\t * trigger an update of their photos. */\n\t\tsipe_buddy_refresh_photos(sipe_private);\n\t}\n\n\tif (sipe_private->focus_factory_uri) {\n\t\t/* Fill the list of conferencing capabilities enabled on\n\t\t * the server. */\n\t\tsipe_conf_get_capabilities(sipe_private);\n\t}\n\n\tif (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007))\n\t\t/* persistentChatPool_uri has been set at this point */\n\t\tsipe_groupchat_init(sipe_private);\n}\n\nstatic void process_incoming_notify_rlmi_resub(struct sipe_core_private *sipe_private,\n\t\t\t\t\t       const gchar *data, unsigned len)\n{\n\tsipe_xml *xn_list;\n\tconst sipe_xml *xn_resource;\n\tGHashTable *servers = g_hash_table_new_full(g_str_hash, g_str_equal,\n\t\t\t\t\t\t    g_free, NULL);\n\n\txn_list = sipe_xml_parse(data, len);\n\n        for (xn_resource = sipe_xml_child(xn_list, \"resource\");\n\t     xn_resource;\n\t     xn_resource = sipe_xml_twin(xn_resource) )\n\t{\n\t\tconst char *uri, *state;\n\t\tconst sipe_xml *xn_instance;\n\n\t\txn_instance = sipe_xml_child(xn_resource, \"instance\");\n                if (!xn_instance) continue;\n\n                uri = sipe_xml_attribute(xn_resource, \"uri\");\n                state = sipe_xml_attribute(xn_instance, \"state\");\n                SIPE_DEBUG_INFO(\"process_incoming_notify_rlmi_resub: uri(%s),state(%s)\", uri, state);\n\n                if (strstr(state, \"resubscribe\")) {\n\t\t\tconst char *poolFqdn = sipe_xml_attribute(xn_instance, \"poolFqdn\");\n\n\t\t\tif (poolFqdn) { //[MS-PRES] Section 3.4.5.1.3 Processing Details\n\t\t\t\tgchar *user    = g_strdup(uri);\n\t\t\t\tgchar *host    = g_strdup(poolFqdn);\n\t\t\t\tGSList *server = g_hash_table_lookup(servers,\n\t\t\t\t\t\t\t\t     host);\n\t\t\t\tserver = g_slist_append(server, user);\n\t\t\t\tg_hash_table_insert(servers, host, server);\n\t\t\t} else {\n\t\t\t\tsipe_subscribe_presence_single(sipe_private,\n\t\t\t\t\t\t\t       uri,\n\t\t\t\t\t\t\t       uri);\n\t\t\t}\n                }\n\t}\n\n\t/* Send out any deferred poolFqdn subscriptions */\n\tg_hash_table_foreach(servers, (GHFunc) sipe_subscribe_poolfqdn_resource_uri, sipe_private);\n\tg_hash_table_destroy(servers);\n\n\tsipe_xml_free(xn_list);\n}\n\n/**\n * Update user phone\n * Suitable for both 2005 and 2007 systems.\n *\n * @param uri                   buddy SIP URI with 'sip:' prefix whose info we want to change.\n * @param phone_type\n * @param phone                 may be modified to strip white space\n * @param phone_display_string  may be modified to strip white space\n */\nstatic void\nsipe_update_user_phone(struct sipe_core_private *sipe_private,\n\t\t       const gchar *uri,\n\t\t       const gchar *phone_type,\n\t\t       gchar *phone,\n\t\t       gchar *phone_display_string)\n{\n\tsipe_buddy_info_fields phone_node = SIPE_BUDDY_INFO_WORK_PHONE; /* work phone by default */\n\tsipe_buddy_info_fields phone_display_node = SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY; /* work phone by default */\n\n\tif(!phone || strlen(phone) == 0) return;\n\n\tif ((sipe_strequal(phone_type, \"mobile\") ||  sipe_strequal(phone_type, \"cell\"))) {\n\t\tphone_node = SIPE_BUDDY_INFO_MOBILE_PHONE;\n\t\tphone_display_node = SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY;\n\t} else if (sipe_strequal(phone_type, \"home\")) {\n\t\tphone_node = SIPE_BUDDY_INFO_HOME_PHONE;\n\t\tphone_display_node = SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY;\n\t} else if (sipe_strequal(phone_type, \"other\")) {\n\t\tphone_node = SIPE_BUDDY_INFO_OTHER_PHONE;\n\t\tphone_display_node = SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY;\n\t} else if (sipe_strequal(phone_type, \"custom1\")) {\n\t\tphone_node = SIPE_BUDDY_INFO_CUSTOM1_PHONE;\n\t\tphone_display_node = SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY;\n\t}\n\n\tsipe_buddy_update_property(sipe_private, uri, phone_node, phone);\n\tif (phone_display_string) {\n\t\tsipe_buddy_update_property(sipe_private, uri, phone_display_node, phone_display_string);\n\t}\n}\n\nstatic void process_incoming_notify_msrtc(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  const gchar *data,\n\t\t\t\t\t  unsigned len)\n{\n\tchar *activity = NULL;\n\tconst char *epid;\n\tconst char *status_id = NULL;\n\tconst char *name;\n\tchar *uri;\n\tchar *self_uri = sip_uri_self(sipe_private);\n\tint avl;\n\tint act;\n\tconst char *device_name = NULL;\n\tconst char *cal_start_time = NULL;\n\tconst char *cal_granularity = NULL;\n\tchar *cal_free_busy_base64 = NULL;\n\tstruct sipe_buddy *sbuddy;\n\tconst sipe_xml *node;\n\tsipe_xml *xn_presentity;\n\tconst sipe_xml *xn_availability;\n\tconst sipe_xml *xn_activity;\n\tconst sipe_xml *xn_display_name;\n\tconst sipe_xml *xn_email;\n\tconst sipe_xml *xn_phone_number;\n\tconst sipe_xml *xn_userinfo;\n\tconst sipe_xml *xn_note;\n\tconst sipe_xml *xn_oof;\n\tconst sipe_xml *xn_state;\n\tconst sipe_xml *xn_contact;\n\tchar *note;\n\tint user_avail;\n\tconst char *user_avail_nil;\n\tint res_avail;\n\ttime_t user_avail_since = 0;\n\ttime_t activity_since = 0;\n\n\t/* fix for Reuters environment on Linux */\n\tif (data && strstr(data, \"encoding=\\\"utf-16\\\"\")) {\n\t\tchar *tmp_data;\n\t\ttmp_data = sipe_utils_str_replace(data, \"encoding=\\\"utf-16\\\"\", \"encoding=\\\"utf-8\\\"\");\n\t\txn_presentity = sipe_xml_parse(tmp_data, strlen(tmp_data));\n\t\tg_free(tmp_data);\n\t} else {\n\t\txn_presentity = sipe_xml_parse(data, len);\n\t}\n\n\txn_availability = sipe_xml_child(xn_presentity, \"availability\");\n\txn_activity = sipe_xml_child(xn_presentity, \"activity\");\n\txn_display_name = sipe_xml_child(xn_presentity, \"displayName\");\n\txn_email = sipe_xml_child(xn_presentity, \"email\");\n\txn_phone_number = sipe_xml_child(xn_presentity, \"phoneNumber\");\n\txn_userinfo = sipe_xml_child(xn_presentity, \"userInfo\");\n\txn_oof = xn_userinfo ? sipe_xml_child(xn_userinfo, \"oof\") : NULL;\n\txn_state = xn_userinfo ? sipe_xml_child(xn_userinfo, \"states/state\"): NULL;\n\tuser_avail = xn_state ? sipe_xml_int_attribute(xn_state, \"avail\", 0) : 0;\n\tuser_avail_since = xn_state ? sipe_utils_str_to_time(sipe_xml_attribute(xn_state, \"since\")) : 0;\n\tuser_avail_nil = xn_state ? sipe_xml_attribute(xn_state, \"nil\") : NULL;\n\txn_contact = xn_userinfo ? sipe_xml_child(xn_userinfo, \"contact\") : NULL;\n\txn_note = xn_userinfo ? sipe_xml_child(xn_userinfo, \"note\") : NULL;\n\tnote = xn_note ? sipe_xml_data(xn_note) : NULL;\n\n\tif (sipe_strequal(user_avail_nil, \"true\")) {\t/* null-ed */\n\t\tuser_avail = 0;\n\t\tuser_avail_since = 0;\n\t}\n\n\tname = sipe_xml_attribute(xn_presentity, \"uri\"); /* without 'sip:' prefix */\n\turi = sip_uri_from_name(name);\n\tavl = sipe_xml_int_attribute(xn_availability, \"aggregate\", 0);\n\tepid = sipe_xml_attribute(xn_availability, \"epid\");\n\tact = sipe_xml_int_attribute(xn_activity, \"aggregate\", 0);\n\n\tstatus_id = sipe_ocs2005_status_from_activity_availability(act, avl);\n\tactivity = g_strdup(sipe_ocs2005_activity_description(act));\n\tres_avail = sipe_ocs2007_availability_from_status(status_id, NULL);\n\tif (user_avail > res_avail) {\n\t\tres_avail = user_avail;\n\t\tstatus_id = sipe_ocs2007_status_from_legacy_availability(user_avail, NULL);\n\t}\n\n\tif (xn_display_name) {\n\t\tchar *display_name = g_strdup(sipe_xml_attribute(xn_display_name, \"displayName\"));\n\t\tchar *email        = xn_email ? g_strdup(sipe_xml_attribute(xn_email, \"email\")) : NULL;\n\t\tchar *phone_label  = xn_phone_number ? g_strdup(sipe_xml_attribute(xn_phone_number, \"label\")) : NULL;\n\t\tchar *phone_number = xn_phone_number ? g_strdup(sipe_xml_attribute(xn_phone_number, \"number\")) : NULL;\n\t\tchar *tel_uri      = sip_to_tel_uri(phone_number);\n\n\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_DISPLAY_NAME, display_name);\n\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_EMAIL, email);\n\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_WORK_PHONE, tel_uri);\n\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY, !is_empty(phone_label) ? phone_label : phone_number);\n\n\t\tg_free(tel_uri);\n\t\tg_free(phone_label);\n\t\tg_free(phone_number);\n\t\tg_free(email);\n\t\tg_free(display_name);\n\t}\n\n\tif (xn_contact) {\n\t\t/* tel */\n\t\tfor (node = sipe_xml_child(xn_contact, \"tel\"); node; node = sipe_xml_twin(node))\n\t\t{\n\t\t\t/* Ex.: <tel type=\"work\">tel:+3222220000</tel> */\n\t\t\tconst char *phone_type = sipe_xml_attribute(node, \"type\");\n\t\t\tchar* phone = sipe_xml_data(node);\n\n\t\t\tsipe_update_user_phone(sipe_private, uri, phone_type, phone, NULL);\n\n\t\t\tg_free(phone);\n\t\t}\n\t}\n\n\tif (xn_display_name || xn_contact)\n\t\tsipe_backend_buddy_refresh_properties(SIPE_CORE_PUBLIC, uri);\n\n\t/* devicePresence */\n\tfor (node = sipe_xml_child(xn_presentity, \"devices/devicePresence\"); node; node = sipe_xml_twin(node)) {\n\t\tconst sipe_xml *xn_device_name;\n\t\tconst sipe_xml *xn_calendar_info;\n\t\tconst sipe_xml *xn_state;\n\t\tchar *state;\n\n\t\t/* deviceName */\n\t\tif (sipe_strequal(sipe_xml_attribute(node, \"epid\"), epid)) {\n\t\t\txn_device_name = sipe_xml_child(node, \"deviceName\");\n\t\t\tdevice_name = xn_device_name ? sipe_xml_attribute(xn_device_name, \"name\") : NULL;\n\t\t}\n\n\t\t/* calendarInfo */\n\t\txn_calendar_info = sipe_xml_child(node, \"calendarInfo\");\n\t\tif (xn_calendar_info) {\n\t\t\tconst char *cal_start_time_tmp = sipe_xml_attribute(xn_calendar_info, \"startTime\");\n\n\t\t\tif (cal_start_time) {\n\t\t\t\ttime_t cal_start_time_t     = sipe_utils_str_to_time(cal_start_time);\n\t\t\t\ttime_t cal_start_time_t_tmp = sipe_utils_str_to_time(cal_start_time_tmp);\n\n\t\t\t\tif (cal_start_time_t_tmp > cal_start_time_t) {\n\t\t\t\t\tcal_start_time = cal_start_time_tmp;\n\t\t\t\t\tcal_granularity = sipe_xml_attribute(xn_calendar_info, \"granularity\");\n\t\t\t\t\tg_free(cal_free_busy_base64);\n\t\t\t\t\tcal_free_busy_base64 = sipe_xml_data(xn_calendar_info);\n\n\t\t\t\t\tSIPE_DEBUG_INFO(\"process_incoming_notify_msrtc: startTime=%s granularity=%s cal_free_busy_base64=\\n%s\", cal_start_time, cal_granularity, cal_free_busy_base64);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcal_start_time = cal_start_time_tmp;\n\t\t\t\tcal_granularity = sipe_xml_attribute(xn_calendar_info, \"granularity\");\n\t\t\t\tg_free(cal_free_busy_base64);\n\t\t\t\tcal_free_busy_base64 = sipe_xml_data(xn_calendar_info);\n\n\t\t\t\tSIPE_DEBUG_INFO(\"process_incoming_notify_msrtc: startTime=%s granularity=%s cal_free_busy_base64=\\n%s\", cal_start_time, cal_granularity, cal_free_busy_base64);\n\t\t\t}\n\t\t}\n\n\t\t/* state */\n\t\txn_state = sipe_xml_child(node, \"states/state\");\n\t\tif (xn_state) {\n\t\t\tint dev_avail = sipe_xml_int_attribute(xn_state, \"avail\", 0);\n\t\t\ttime_t dev_avail_since = sipe_utils_str_to_time(sipe_xml_attribute(xn_state, \"since\"));\n\n\t\t\tstate = sipe_xml_data(xn_state);\n\t\t\tif (dev_avail_since > user_avail_since &&\n\t\t\t    dev_avail >= res_avail)\n\t\t\t{\n\t\t\t\tconst gchar *new_desc;\n\t\t\t\tres_avail = dev_avail;\n\t\t\t\tif (!is_empty(state)) {\n\t\t\t\t\tif (sipe_strequal(state, sipe_status_activity_to_token(SIPE_ACTIVITY_ON_PHONE))) {\n\t\t\t\t\t\tg_free(activity);\n\t\t\t\t\t\tactivity = g_strdup(sipe_core_activity_description(SIPE_ACTIVITY_ON_PHONE));\n\t\t\t\t\t} else if (sipe_strequal(state, \"presenting\")) {\n\t\t\t\t\t\tg_free(activity);\n\t\t\t\t\t\tactivity = g_strdup(sipe_core_activity_description(SIPE_ACTIVITY_IN_CONF));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tactivity = state;\n\t\t\t\t\t\tstate = NULL;\n\t\t\t\t\t}\n\t\t\t\t\tactivity_since = dev_avail_since;\n\t\t\t\t}\n\t\t\t\tstatus_id = sipe_ocs2007_status_from_legacy_availability(res_avail, NULL);\n\t\t\t\tnew_desc  = sipe_ocs2007_legacy_activity_description(res_avail);\n\t\t\t\tif (new_desc) {\n\t\t\t\t\tg_free(activity);\n\t\t\t\t\tactivity = g_strdup(new_desc);\n\t\t\t\t}\n\t\t\t}\n\t\t\tg_free(state);\n\t\t}\n\t}\n\n\t/* oof */\n\tif (xn_oof && res_avail >= 15000) { /* 12000 in 2007 */\n\t\tg_free(activity);\n\t\tactivity = g_strdup(sipe_core_activity_description(SIPE_ACTIVITY_OOF));\n\t\tactivity_since = 0;\n\t}\n\n\tsbuddy = sipe_buddy_find_by_uri(sipe_private, uri);\n\tif (sbuddy)\n\t{\n\t\tg_free(sbuddy->activity);\n\t\tsbuddy->activity = activity;\n\t\tactivity = NULL;\n\n\t\tsbuddy->activity_since = activity_since;\n\n\t\tsbuddy->user_avail = user_avail;\n\t\tsbuddy->user_avail_since = user_avail_since;\n\n\t\tg_free(sbuddy->note);\n\t\tsbuddy->note = NULL;\n\t\tif (!is_empty(note)) { sbuddy->note = g_markup_escape_text(note, -1); }\n\n\t\tsbuddy->is_oof_note = (xn_oof != NULL);\n\n\t\tg_free(sbuddy->device_name);\n\t\tsbuddy->device_name = NULL;\n\t\tif (!is_empty(device_name)) { sbuddy->device_name = g_strdup(device_name); }\n\n\t\tif (!is_empty(cal_free_busy_base64)) {\n\t\t\tg_free(sbuddy->cal_start_time);\n\t\t\tsbuddy->cal_start_time = g_strdup(cal_start_time);\n\n\t\t\tsbuddy->cal_granularity = sipe_strcase_equal(cal_granularity, \"PT15M\") ? 15 : 0;\n\n\t\t\tg_free(sbuddy->cal_free_busy_base64);\n\t\t\tsbuddy->cal_free_busy_base64 = cal_free_busy_base64;\n\t\t\tcal_free_busy_base64 = NULL;\n\n\t\t\tg_free(sbuddy->cal_free_busy);\n\t\t\tsbuddy->cal_free_busy = NULL;\n\t\t}\n\n\t\tsbuddy->last_non_cal_status_id = status_id;\n\t\tg_free(sbuddy->last_non_cal_activity);\n\t\tsbuddy->last_non_cal_activity = g_strdup(sbuddy->activity);\n\n\t\tif (sipe_strcase_equal(sbuddy->name, self_uri)) {\n\t\t\tif (!sipe_strequal(sbuddy->note, sipe_private->note)) /* not same */\n\t\t\t{\n\t\t\t\tif (sbuddy->is_oof_note)\n\t\t\t\t\tSIPE_CORE_PRIVATE_FLAG_SET(OOF_NOTE);\n\t\t\t\telse\n\t\t\t\t\tSIPE_CORE_PRIVATE_FLAG_UNSET(OOF_NOTE);\n\n\t\t\t\tg_free(sipe_private->note);\n\t\t\t\tsipe_private->note = g_strdup(sbuddy->note);\n\n\t\t\t\tsipe_private->note_since = time(NULL);\n\t\t\t}\n\n\t\t\tsipe_status_set_token(sipe_private,\n\t\t\t\t\t      sbuddy->last_non_cal_status_id);\n\t\t}\n\t}\n\tg_free(cal_free_busy_base64);\n\tg_free(activity);\n\n\tSIPE_DEBUG_INFO(\"process_incoming_notify_msrtc: status(%s)\", status_id);\n\tsipe_core_buddy_got_status(SIPE_CORE_PUBLIC,\n\t\t\t\t   uri,\n\t\t\t\t   sipe_status_token_to_activity(status_id),\n\t\t\t\t   0);\n\n\tif (!SIPE_CORE_PRIVATE_FLAG_IS(OCS2007) && sipe_strcase_equal(self_uri, uri)) {\n\t\tsipe_ocs2005_user_info_has_updated(sipe_private, xn_userinfo);\n\t}\n\n\tg_free(note);\n\tsipe_xml_free(xn_presentity);\n\tg_free(uri);\n\tg_free(self_uri);\n}\n\nstatic void process_incoming_notify_rlmi(struct sipe_core_private *sipe_private,\n\t\t\t\t\t const gchar *data,\n\t\t\t\t\t unsigned len)\n{\n\tconst char *uri;\n\tstruct sipe_buddy *sbuddy = NULL;\n\tsipe_xml *xn_categories;\n\tconst sipe_xml *xn_category;\n\tconst char *status = NULL;\n\tgboolean do_update_status = FALSE;\n\tgboolean has_note_cleaned = FALSE;\n\tgboolean has_free_busy_cleaned = FALSE;\n\ttime_t last_active = 0;\n\n\txn_categories = sipe_xml_parse(data, len);\n\turi = sipe_xml_attribute(xn_categories, \"uri\"); /* with 'sip:' prefix */\n\tif (uri) {\n\t\tsbuddy = sipe_buddy_find_by_uri(sipe_private, uri);\n\t}\n\n\tif (!sbuddy) {\n\t\t/* Got presence of a buddy not in our contact list, ignore. */\n\t\tsipe_xml_free(xn_categories);\n\t\treturn;\n\t}\n\n\tfor (xn_category = sipe_xml_child(xn_categories, \"category\");\n\t\t xn_category ;\n\t\t xn_category = sipe_xml_twin(xn_category) )\n\t{\n\t\tconst sipe_xml *xn_node;\n\t\tconst char *tmp;\n\t\tconst char *attrVar = sipe_xml_attribute(xn_category, \"name\");\n\t\ttime_t publish_time = (tmp = sipe_xml_attribute(xn_category, \"publishTime\")) ?\n\t\t\tsipe_utils_str_to_time(tmp) : 0;\n\n\t\t/* contactCard */\n\t\tif (sipe_strequal(attrVar, \"contactCard\"))\n\t\t{\n\t\t\tconst sipe_xml *card = sipe_xml_child(xn_category, \"contactCard\");\n\n\t\t\tif (card) {\n\t\t\t\tconst sipe_xml *node;\n\t\t\t\t/* identity - Display Name and email */\n\t\t\t\tnode = sipe_xml_child(card, \"identity\");\n\t\t\t\tif (node) {\n\t\t\t\t\tchar* display_name = sipe_xml_data(\n\t\t\t\t\t\tsipe_xml_child(node, \"name/displayName\"));\n\t\t\t\t\tchar* email = sipe_xml_data(\n\t\t\t\t\t\tsipe_xml_child(node, \"email\"));\n\n\t\t\t\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_DISPLAY_NAME, display_name);\n\t\t\t\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_EMAIL, email);\n\n\t\t\t\t\tg_free(display_name);\n\t\t\t\t\tg_free(email);\n\t\t\t\t}\n\t\t\t\t/* company */\n\t\t\t\tnode = sipe_xml_child(card, \"company\");\n\t\t\t\tif (node) {\n\t\t\t\t\tchar* company = sipe_xml_data(node);\n\t\t\t\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_COMPANY, company);\n\t\t\t\t\tg_free(company);\n\t\t\t\t}\n\t\t\t\t/* department */\n\t\t\t\tnode = sipe_xml_child(card, \"department\");\n\t\t\t\tif (node) {\n\t\t\t\t\tchar* department = sipe_xml_data(node);\n\t\t\t\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_DEPARTMENT, department);\n\t\t\t\t\tg_free(department);\n\t\t\t\t}\n\t\t\t\t/* title */\n\t\t\t\tnode = sipe_xml_child(card, \"title\");\n\t\t\t\tif (node) {\n\t\t\t\t\tchar* title = sipe_xml_data(node);\n\t\t\t\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_JOB_TITLE, title);\n\t\t\t\t\tg_free(title);\n\t\t\t\t}\n\t\t\t\t/* office */\n\t\t\t\tnode = sipe_xml_child(card, \"office\");\n\t\t\t\tif (node) {\n\t\t\t\t\tchar* office = sipe_xml_data(node);\n\t\t\t\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_OFFICE, office);\n\t\t\t\t\tg_free(office);\n\t\t\t\t}\n\t\t\t\t/* site (url) */\n\t\t\t\tnode = sipe_xml_child(card, \"url\");\n\t\t\t\tif (node) {\n\t\t\t\t\tchar* site = sipe_xml_data(node);\n\t\t\t\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_SITE, site);\n\t\t\t\t\tg_free(site);\n\t\t\t\t}\n\t\t\t\t/* phone */\n\t\t\t\tfor (node = sipe_xml_child(card, \"phone\");\n\t\t\t\t     node;\n\t\t\t\t     node = sipe_xml_twin(node))\n\t\t\t\t{\n\t\t\t\t\tconst char *phone_type = sipe_xml_attribute(node, \"type\");\n\t\t\t\t\tchar* phone = sipe_xml_data(sipe_xml_child(node, \"uri\"));\n\t\t\t\t\tchar* phone_display_string = sipe_xml_data(sipe_xml_child(node, \"displayString\"));\n\n\t\t\t\t\tsipe_update_user_phone(sipe_private, uri, phone_type, phone, phone_display_string);\n\n\t\t\t\t\tg_free(phone);\n\t\t\t\t\tg_free(phone_display_string);\n\t\t\t\t}\n\t\t\t\t/* address */\n\t\t\t\tfor (node = sipe_xml_child(card, \"address\");\n\t\t\t\t     node;\n\t\t\t\t     node = sipe_xml_twin(node))\n\t\t\t\t{\n\t\t\t\t\tif (sipe_strequal(sipe_xml_attribute(node, \"type\"), \"work\")) {\n\t\t\t\t\t\tchar* street = sipe_xml_data(sipe_xml_child(node, \"street\"));\n\t\t\t\t\t\tchar* city = sipe_xml_data(sipe_xml_child(node, \"city\"));\n\t\t\t\t\t\tchar* state = sipe_xml_data(sipe_xml_child(node, \"state\"));\n\t\t\t\t\t\tchar* zipcode = sipe_xml_data(sipe_xml_child(node, \"zipcode\"));\n\t\t\t\t\t\tchar* country_code = sipe_xml_data(sipe_xml_child(node, \"countryCode\"));\n\n\t\t\t\t\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_STREET, street);\n\t\t\t\t\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_CITY, city);\n\t\t\t\t\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_STATE, state);\n\t\t\t\t\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_ZIPCODE, zipcode);\n\t\t\t\t\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_COUNTRY, country_code);\n\n\t\t\t\t\t\tg_free(street);\n\t\t\t\t\t\tg_free(city);\n\t\t\t\t\t\tg_free(state);\n\t\t\t\t\t\tg_free(zipcode);\n\t\t\t\t\t\tg_free(country_code);\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t/* photo */\n\t\t\t\tfor (node = sipe_xml_child(card, \"photo\");\n\t\t\t\t     node;\n\t\t\t\t     node = sipe_xml_twin(node)) {\n\t\t\t\t\tconst gchar *type = sipe_xml_attribute(node, \"type\");\n\t\t\t\t\tgchar *photo_url;\n\t\t\t\t\tgchar *hash;\n\t\t\t\t\tgboolean found = FALSE;\n\n\t\t\t\t\tif (sipe_strequal(type, \"default\") &&\n\t\t\t\t\t    !SIPE_CORE_PUBLIC_FLAG_IS(ALLOW_WEB_PHOTO)) {\n\t\t\t\t\t\tSIPE_DEBUG_INFO(\"process_incoming_notify_rlmi: skipping download of web profile picture for %s\", uri);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tphoto_url = sipe_xml_data(sipe_xml_child(node, \"uri\"));\n\t\t\t\t\thash = sipe_xml_data(sipe_xml_child(node, \"hash\"));\n\n\t\t\t\t\tif (!is_empty(photo_url) && !is_empty(hash)) {\n\t\t\t\t\t\tsipe_buddy_update_photo(sipe_private,\n\t\t\t\t\t\t\t\t\turi,\n\t\t\t\t\t\t\t\t\thash,\n\t\t\t\t\t\t\t\t\tphoto_url,\n\t\t\t\t\t\t\t\t\tNULL);\n\t\t\t\t\t\tfound = TRUE;\n\t\t\t\t\t}\n\n\t\t\t\t\tg_free(hash);\n\t\t\t\t\tg_free(photo_url);\n\n\t\t\t\t\tif (found)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t/* note */\n\t\telse if (sipe_strequal(attrVar, \"note\"))\n\t\t{\n\t\t\tif (!has_note_cleaned) {\n\t\t\t\thas_note_cleaned = TRUE;\n\n\t\t\t\tg_free(sbuddy->note);\n\t\t\t\tsbuddy->note = NULL;\n\t\t\t\tsbuddy->is_oof_note = FALSE;\n\t\t\t\tsbuddy->note_since = publish_time;\n\n\t\t\t\tdo_update_status = TRUE;\n\t\t\t}\n\t\t\tif (publish_time >= sbuddy->note_since) {\n\t\t\t\t/* clean up in case no 'note' element is supplied\n\t\t\t\t * which indicate note removal in client\n\t\t\t\t */\n\t\t\t\tg_free(sbuddy->note);\n\t\t\t\tsbuddy->note = NULL;\n\t\t\t\tsbuddy->is_oof_note = FALSE;\n\t\t\t\tsbuddy->note_since = publish_time;\n\n\t\t\t\txn_node = sipe_xml_child(xn_category, \"note/body\");\n\t\t\t\tif (xn_node) {\n\t\t\t\t\tchar *tmp;\n\t\t\t\t\tsbuddy->note = g_markup_escape_text((tmp = sipe_xml_data(xn_node)), -1);\n\t\t\t\t\tg_free(tmp);\n\t\t\t\t\tsbuddy->is_oof_note = sipe_strequal(sipe_xml_attribute(xn_node, \"type\"), \"OOF\");\n\t\t\t\t\tsbuddy->note_since = publish_time;\n\n\t\t\t\t\tSIPE_DEBUG_INFO(\"process_incoming_notify_rlmi: uri(%s), note(%s)\",\n\t\t\t\t\t\t\turi, sbuddy->note ? sbuddy->note : \"\");\n\t\t\t\t}\n\t\t\t\t/* to trigger UI refresh in case no status info is supplied in this update */\n\t\t\t\tdo_update_status = TRUE;\n\t\t\t}\n\t\t}\n\t\t/* state */\n\t\telse if(sipe_strequal(attrVar, \"state\"))\n\t\t{\n\t\t\tchar *tmp;\n\t\t\tint availability;\n\t\t\tconst sipe_xml *xn_availability;\n\t\t\tconst sipe_xml *xn_activity;\n\t\t\tconst sipe_xml *xn_device;\n\t\t\tconst sipe_xml *xn_meeting_subject;\n\t\t\tconst sipe_xml *xn_meeting_location;\n\t\t\tconst gchar *legacy_activity;\n\t\t\tconst gchar *last_active_attr;\n\n\t\t\txn_node = sipe_xml_child(xn_category, \"state\");\n\t\t\tif (!xn_node) continue;\n\t\t\txn_availability = sipe_xml_child(xn_node, \"availability\");\n\t\t\tif (!xn_availability) continue;\n\t\t\txn_activity = sipe_xml_child(xn_node, \"activity\");\n\t\t\txn_meeting_subject = sipe_xml_child(xn_node, \"meetingSubject\");\n\t\t\txn_meeting_location = sipe_xml_child(xn_node, \"meetingLocation\");\n\n\t\t\ttmp = sipe_xml_data(xn_availability);\n\t\t\tavailability = atoi(tmp);\n\t\t\tg_free(tmp);\n\n\t\t\tsbuddy->is_mobile = FALSE;\n\t\t\txn_device = sipe_xml_child(xn_node, \"device\");\n\t\t\tif (xn_device) {\n\t\t\t\ttmp = sipe_xml_data(xn_device);\n\t\t\t\tsbuddy->is_mobile = !g_ascii_strcasecmp(tmp, \"Mobile\");\n\t\t\t\tg_free(tmp);\n\t\t\t}\n\n\t\t\t/* activity */\n\t\t\tg_free(sbuddy->activity);\n\t\t\tsbuddy->activity = NULL;\n\t\t\tif (xn_activity) {\n\t\t\t\tconst char *token = sipe_xml_attribute(xn_activity, \"token\");\n\t\t\t\tconst sipe_xml *xn_custom = sipe_xml_child(xn_activity, \"custom\");\n\n\t\t\t\t/* from token */\n\t\t\t\tif (!is_empty(token)) {\n\t\t\t\t\tsbuddy->activity = g_strdup(sipe_core_activity_description(sipe_status_token_to_activity(token)));\n\t\t\t\t}\n\t\t\t\t/* from custom element */\n\t\t\t\tif (xn_custom) {\n\t\t\t\t\tchar *custom = sipe_xml_data(xn_custom);\n\n\t\t\t\t\tif (!is_empty(custom)) {\n\t\t\t\t\t\tg_free(sbuddy->activity);\n\t\t\t\t\t\tsbuddy->activity = custom;\n\t\t\t\t\t\tcustom = NULL;\n\t\t\t\t\t}\n\t\t\t\t\tg_free(custom);\n\t\t\t\t}\n\t\t\t}\n\t\t\t/* meeting_subject */\n\t\t\tg_free(sbuddy->meeting_subject);\n\t\t\tsbuddy->meeting_subject = NULL;\n\t\t\tif (xn_meeting_subject) {\n\t\t\t\tchar *meeting_subject = sipe_xml_data(xn_meeting_subject);\n\n\t\t\t\tif (!is_empty(meeting_subject)) {\n\t\t\t\t\tsbuddy->meeting_subject = meeting_subject;\n\t\t\t\t\tmeeting_subject = NULL;\n\t\t\t\t}\n\t\t\t\tg_free(meeting_subject);\n\t\t\t}\n\t\t\t/* meeting_location */\n\t\t\tg_free(sbuddy->meeting_location);\n\t\t\tsbuddy->meeting_location = NULL;\n\t\t\tif (xn_meeting_location) {\n\t\t\t\tchar *meeting_location = sipe_xml_data(xn_meeting_location);\n\n\t\t\t\tif (!is_empty(meeting_location)) {\n\t\t\t\t\tsbuddy->meeting_location = meeting_location;\n\t\t\t\t\tmeeting_location = NULL;\n\t\t\t\t}\n\t\t\t\tg_free(meeting_location);\n\t\t\t}\n\n\t\t\tstatus = sipe_ocs2007_status_from_legacy_availability(availability, NULL);\n\t\t\tlegacy_activity = sipe_ocs2007_legacy_activity_description(availability);\n\t\t\tif (sbuddy->activity && legacy_activity) {\n\t\t\t\tgchar *tmp2 = sbuddy->activity;\n\n\t\t\t\tsbuddy->activity = g_strdup_printf(\"%s, %s\", sbuddy->activity, legacy_activity);\n\t\t\t\tg_free(tmp2);\n\t\t\t} else if (legacy_activity) {\n\t\t\t\tsbuddy->activity = g_strdup(legacy_activity);\n\t\t\t}\n\n\t\t\t/* lastActive */\n\t\t\tlast_active_attr = sipe_xml_attribute(xn_node, \"lastActive\");\n\t\t\tif (last_active_attr) {\n\t\t\t\tlast_active = sipe_utils_str_to_time(last_active_attr);\n\t\t\t}\n\n\t\t\tdo_update_status = TRUE;\n\t\t}\n\t\t/* calendarData */\n\t\telse if(sipe_strequal(attrVar, \"calendarData\"))\n\t\t{\n\t\t\tconst sipe_xml *xn_free_busy = sipe_xml_child(xn_category, \"calendarData/freeBusy\");\n\t\t\tconst sipe_xml *xn_working_hours = sipe_xml_child(xn_category, \"calendarData/WorkingHours\");\n\n\t\t\tif (xn_free_busy) {\n\t\t\t\tif (!has_free_busy_cleaned) {\n\t\t\t\t\thas_free_busy_cleaned = TRUE;\n\n\t\t\t\t\tg_free(sbuddy->cal_start_time);\n\t\t\t\t\tsbuddy->cal_start_time = NULL;\n\n\t\t\t\t\tg_free(sbuddy->cal_free_busy_base64);\n\t\t\t\t\tsbuddy->cal_free_busy_base64 = NULL;\n\n\t\t\t\t\tg_free(sbuddy->cal_free_busy);\n\t\t\t\t\tsbuddy->cal_free_busy = NULL;\n\n\t\t\t\t\tsbuddy->cal_free_busy_published = publish_time;\n\t\t\t\t}\n\n\t\t\t\tif (publish_time >= sbuddy->cal_free_busy_published) {\n\t\t\t\t\tg_free(sbuddy->cal_start_time);\n\t\t\t\t\tsbuddy->cal_start_time = g_strdup(sipe_xml_attribute(xn_free_busy, \"startTime\"));\n\n\t\t\t\t\tsbuddy->cal_granularity = sipe_strcase_equal(sipe_xml_attribute(xn_free_busy, \"granularity\"), \"PT15M\") ?\n\t\t\t\t\t\t15 : 0;\n\n\t\t\t\t\tg_free(sbuddy->cal_free_busy_base64);\n\t\t\t\t\tsbuddy->cal_free_busy_base64 = sipe_xml_data(xn_free_busy);\n\n\t\t\t\t\tg_free(sbuddy->cal_free_busy);\n\t\t\t\t\tsbuddy->cal_free_busy = NULL;\n\n\t\t\t\t\tsbuddy->cal_free_busy_published = publish_time;\n\n\t\t\t\t\tSIPE_DEBUG_INFO(\"process_incoming_notify_rlmi: startTime=%s granularity=%d cal_free_busy_base64=\\n%s\", sbuddy->cal_start_time, sbuddy->cal_granularity, sbuddy->cal_free_busy_base64);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (xn_working_hours) {\n\t\t\t\tsipe_cal_parse_working_hours(xn_working_hours, sbuddy);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (do_update_status) {\n\t\tguint activity;\n\n\t\tif (status) {\n\t\t\tSIPE_DEBUG_INFO(\"process_incoming_notify_rlmi: %s\", status);\n\t\t\tactivity = sipe_status_token_to_activity(status);\n\t\t} else {\n\t\t\t/* no status category in this update,\n\t\t\t   using contact's current status */\n\t\t\tactivity = sipe_backend_buddy_get_status(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t uri);\n\t\t}\n\n\t\tsipe_core_buddy_got_status(SIPE_CORE_PUBLIC,\n\t\t\t\t\t   uri,\n\t\t\t\t\t   activity,\n\t\t\t\t\t   last_active);\n\t}\n\n\tsipe_backend_buddy_refresh_properties(SIPE_CORE_PUBLIC, uri);\n\n\tsipe_xml_free(xn_categories);\n}\n\nstatic void sipe_buddy_status_from_activity(struct sipe_core_private *sipe_private,\n\t\t\t\t\t    const gchar *uri,\n\t\t\t\t\t    const gchar *activity,\n\t\t\t\t\t    gboolean is_online)\n{\n\tif (is_online) {\n\t\tconst gchar *status_id = NULL;\n\t\tif (activity) {\n\t\t\tif (sipe_strequal(activity,\n\t\t\t\t\t  sipe_status_activity_to_token(SIPE_ACTIVITY_BUSY))) {\n\t\t\t\tstatus_id = sipe_status_activity_to_token(SIPE_ACTIVITY_BUSY);\n\t\t\t} else if (sipe_strequal(activity,\n\t\t\t\t\t\t sipe_status_activity_to_token(SIPE_ACTIVITY_AWAY))) {\n\t\t\t\tstatus_id = sipe_status_activity_to_token(SIPE_ACTIVITY_AWAY);\n\t\t\t}\n\t\t}\n\n\t\tif (!status_id) {\n\t\t\tstatus_id = sipe_status_activity_to_token(SIPE_ACTIVITY_AVAILABLE);\n\t\t}\n\n\t\tSIPE_DEBUG_INFO(\"sipe_buddy_status_from_activity: status_id(%s)\", status_id);\n\t\tsipe_core_buddy_got_status(SIPE_CORE_PUBLIC,\n\t\t\t\t\t   uri,\n\t\t\t\t\t   sipe_status_token_to_activity(status_id),\n\t\t\t                   0);\n\t} else {\n\t\tsipe_core_buddy_got_status(SIPE_CORE_PUBLIC,\n\t\t\t\t\t   uri,\n\t\t\t\t\t   SIPE_ACTIVITY_OFFLINE,\n\t\t\t\t\t   0);\n\t}\n}\n\nstatic void process_incoming_notify_pidf(struct sipe_core_private *sipe_private,\n\t\t\t\t\t const gchar *data,\n\t\t\t\t\t unsigned len)\n{\n\tgchar *uri;\n\tgchar *getbasic;\n\tgchar *activity = NULL;\n\tsipe_xml *pidf;\n\tconst sipe_xml *basicstatus = NULL, *tuple, *status;\n\tgboolean isonline = FALSE;\n\tconst sipe_xml *display_name_node;\n\n\tpidf = sipe_xml_parse(data, len);\n\tif (!pidf) {\n\t\tSIPE_DEBUG_INFO(\"process_incoming_notify_pidf: no parseable pidf:%s\", data);\n\t\treturn;\n\t}\n\n\tif ((tuple = sipe_xml_child(pidf, \"tuple\")))\n\t{\n\t\tif ((status = sipe_xml_child(tuple, \"status\"))) {\n\t\t\tbasicstatus = sipe_xml_child(status, \"basic\");\n\t\t}\n\t}\n\n\tif (!basicstatus) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_incoming_notify_pidf: no basic found\");\n\t\tsipe_xml_free(pidf);\n\t\treturn;\n\t}\n\n\tgetbasic = sipe_xml_data(basicstatus);\n\tif (!getbasic) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"process_incoming_notify_pidf: no basic data found\");\n\t\tsipe_xml_free(pidf);\n\t\treturn;\n\t}\n\n\tSIPE_DEBUG_INFO(\"process_incoming_notify_pidf: basic-status(%s)\", getbasic);\n\tif (strstr(getbasic, \"open\")) {\n\t\tisonline = TRUE;\n\t}\n\tg_free(getbasic);\n\n\turi = sip_uri(sipe_xml_attribute(pidf, \"entity\")); /* with 'sip:' prefix */ /* AOL comes without the prefix */\n\n\tdisplay_name_node = sipe_xml_child(pidf, \"display-name\");\n\tif (display_name_node) {\n\t\tchar * display_name = sipe_xml_data(display_name_node);\n\n\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_DISPLAY_NAME, display_name);\n\t\tg_free(display_name);\n\n\t\tsipe_backend_buddy_refresh_properties(SIPE_CORE_PUBLIC, uri);\n\t}\n\n\tif ((tuple = sipe_xml_child(pidf, \"tuple\"))) {\n\t\tif ((status = sipe_xml_child(tuple, \"status\"))) {\n\t\t\tif ((basicstatus = sipe_xml_child(status, \"activities\"))) {\n\t\t\t\tif ((basicstatus = sipe_xml_child(basicstatus, \"activity\"))) {\n\t\t\t\t\tactivity = sipe_xml_data(basicstatus);\n\t\t\t\t\tSIPE_DEBUG_INFO(\"process_incoming_notify_pidf: activity(%s)\", activity);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tsipe_buddy_status_from_activity(sipe_private,\n\t\t\t\t\turi,\n\t\t\t\t\tactivity,\n\t\t\t\t\tisonline);\n\n\tg_free(activity);\n\tg_free(uri);\n\tsipe_xml_free(pidf);\n}\n\nstatic void sipe_presence_mime_cb(gpointer user_data, /* sipe_core_private */\n\t\t\t\t  const GSList *fields,\n\t\t\t\t  const gchar *body,\n\t\t\t\t  gsize length)\n{\n\tconst gchar *type = sipe_utils_nameval_find(fields, \"Content-Type\");\n\n\tif (strstr(type,\"application/rlmi+xml\")) {\n\t\tprocess_incoming_notify_rlmi_resub(user_data, body, length);\n\t} else if (strstr(type, \"text/xml+msrtc.pidf\")) {\n\t\tprocess_incoming_notify_msrtc(user_data, body, length);\n\t} else {\n\t\tprocess_incoming_notify_rlmi(user_data, body, length);\n\t}\n}\n\nstatic void sipe_process_presence(struct sipe_core_private *sipe_private,\n\t\t\t\t  struct sipmsg *msg)\n{\n\tconst char *ctype = sipmsg_find_content_type_header(msg);\n\n\tSIPE_DEBUG_INFO(\"sipe_process_presence: Content-Type: %s\", ctype ? ctype : \"\");\n\n\tif (ctype &&\n\t    (strstr(ctype, \"application/rlmi+xml\") ||\n\t     strstr(ctype, \"application/msrtc-event-categories+xml\")))\n\t{\n\t\tif (strstr(ctype, \"multipart\"))\n\t\t{\n\t\t\tsipe_mime_parts_foreach(ctype, msg->body, sipe_presence_mime_cb, sipe_private);\n\t\t}\n\t\telse if(strstr(ctype, \"application/msrtc-event-categories+xml\") )\n\t\t{\n\t\t\tprocess_incoming_notify_rlmi(sipe_private, msg->body, msg->bodylen);\n\t\t}\n\t\telse if(strstr(ctype, \"application/rlmi+xml\"))\n\t\t{\n\t\t\tprocess_incoming_notify_rlmi_resub(sipe_private, msg->body, msg->bodylen);\n\t\t}\n\t}\n\telse if(ctype && strstr(ctype, \"text/xml+msrtc.pidf\"))\n\t{\n\t\tprocess_incoming_notify_msrtc(sipe_private, msg->body, msg->bodylen);\n\t}\n\telse\n\t{\n\t\tprocess_incoming_notify_pidf(sipe_private, msg->body, msg->bodylen);\n\t}\n}\n\n/**\n * Fires on deregistration event initiated by server.\n * [MS-SIPREGE] SIP extension.\n *\n *\tOCS2007 Example\n *\n *\tContent-Type: text/registration-event\n *\tsubscription-state: terminated;expires=0\n *\tms-diagnostics-public: 4141;reason=\"User disabled\"\n *\n *\tderegistered;event=rejected\n */\nstatic void sipe_process_registration_notify(struct sipe_core_private *sipe_private,\n\t\t\t\t\t     struct sipmsg *msg)\n{\n\tconst gchar *contenttype = sipmsg_find_content_type_header(msg);\n\tgchar *event = NULL;\n\tgchar *reason = NULL;\n\tgchar *warning;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_process_registration_notify: deregistration received.\");\n\n\tif (!g_ascii_strncasecmp(contenttype, \"text/registration-event\", 23)) {\n\t\tevent = sipmsg_find_part_of_header(msg->body, \"event=\", NULL, NULL);\n\t\t//@TODO have proper parameter extraction _by_name_ func, case insesitive.\n\t\tevent = event ? event : sipmsg_find_part_of_header(msg->body, \"event=\", \";\", NULL);\n\t} else {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_process_registration_notify: unknown content type, exiting.\");\n\t\treturn;\n\t}\n\n\treason = sipmsg_get_ms_diagnostics_reason(msg);\n\treason = reason ? reason : sipmsg_get_ms_diagnostics_public_reason(msg);\n\tif (!reason) { // for LCS2005\n\t\tif (event && sipe_strcase_equal(event, \"unregistered\")) {\n\t\t\t//reason = g_strdup(_(\"User logged out\")); // [MS-OCER]\n\t\t\treason = g_strdup(_(\"you are already signed in at another location\"));\n\t\t} else if (event && sipe_strcase_equal(event, \"rejected\")) {\n\t\t\treason = g_strdup(_(\"user disabled\")); // [MS-OCER]\n\t\t} else if (event && sipe_strcase_equal(event, \"deactivated\")) {\n\t\t\treason = g_strdup(_(\"user moved\")); // [MS-OCER]\n\t\t}\n\t}\n\tg_free(event);\n\twarning = g_strdup_printf(_(\"You have been rejected by the server: %s\"), reason ? reason : _(\"no reason given\"));\n\tg_free(reason);\n\n\tsipe_backend_connection_error(SIPE_CORE_PUBLIC,\n\t\t\t\t      SIPE_CONNECTION_ERROR_INVALID_USERNAME,\n\t\t\t\t      warning);\n\tg_free(warning);\n\n}\n\n/* Replace \"~\" with localized version of \"Other Contacts\" */\nstatic const gchar *get_group_name(const sipe_xml *node)\n{\n\tconst gchar *name = sipe_xml_attribute(node, \"name\");\n\treturn(g_str_has_prefix(name, \"~\") ? _(\"Other Contacts\") : name);\n}\n\nstatic void add_new_group(struct sipe_core_private *sipe_private,\n\t\t\t  const sipe_xml *node)\n{\n\tsipe_group_add(sipe_private,\n\t\t       get_group_name(node),\n\t\t       NULL,\n\t\t       NULL,\n\t\t       sipe_xml_int_attribute(node, \"id\", 0));\n}\n\nstatic void add_new_buddy(struct sipe_core_private *sipe_private,\n\t\t\t  const sipe_xml *node,\n\t\t\t  const gchar *uri)\n{\n\tconst gchar *name = sipe_xml_attribute(node, \"name\");\n\tstruct sipe_buddy *buddy = NULL;\n\tgchar *tmp;\n\tgchar **item_groups;\n\tint i = 0;\n\n\t/* \"name\" attribute is a contact alias which user can manually assign by\n\t * renaming the item in the contact list. Empty string means no alias\n\t * and the display name from the contact card should be used instead. */\n\tif (name && strlen(name) == 0) {\n\t\tname = NULL;\n\t}\n\n\t/* assign to group Other Contacts if nothing else received */\n\ttmp = g_strdup(sipe_xml_attribute(node, \"groups\"));\n\tif (is_empty(tmp)) {\n\t\tstruct sipe_group *group = sipe_group_find_by_name(sipe_private,\n\t\t\t\t\t\t\t\t   _(\"Other Contacts\"));\n\t\tg_free(tmp);\n\t\ttmp = group ? g_strdup_printf(\"%d\", group->id) : g_strdup(\"1\");\n\t}\n\titem_groups = g_strsplit(tmp, \" \", 0);\n\tg_free(tmp);\n\n\twhile (item_groups[i]) {\n\t\tstruct sipe_group *group = sipe_group_find_by_id(sipe_private,\n\t\t\t\t\t\t\t\t g_ascii_strtod(item_groups[i],\n\t\t\t\t\t\t\t\t\t\tNULL));\n\n\t\t/* If couldn't find the right group for this contact, */\n\t\t/* then just put it in the first group we have\t      */\n\t\tif (!group)\n\t\t\tgroup = sipe_group_first(sipe_private);\n\n\t\tif (group) {\n\t\t\tif (!buddy)\n\t\t\t\tbuddy = sipe_buddy_add(sipe_private,\n\t\t\t\t\t\t       uri,\n\t\t\t\t\t\t       NULL,\n\t\t\t\t\t\t       NULL);\n\n\t\t\tsipe_buddy_add_to_group(sipe_private,\n\t\t\t\t\t\tbuddy,\n\t\t\t\t\t\tgroup,\n\t\t\t\t\t\tname);\n\t\t} else {\n\t\t\tSIPE_DEBUG_INFO(\"No group found for contact %s!  Unable to add to buddy list\",\n\t\t\t\t\turi);\n\t\t}\n\n\t\ti++;\n\t}\n\n\tg_strfreev(item_groups);\n}\n\nstatic gboolean sipe_process_roaming_contacts(struct sipe_core_private *sipe_private,\n\t\t\t\t\t      struct sipmsg *msg)\n{\n\tint len = msg->bodylen;\n\n\tconst gchar *tmp = sipmsg_find_event_header(msg);\n\tconst sipe_xml *item;\n\tsipe_xml *isc;\n\tguint delta;\n\tconst sipe_xml *group_node;\n\n\tif (!g_str_has_prefix(tmp, \"vnd-microsoft-roaming-contacts\")) {\n\t\treturn FALSE;\n\t}\n\n\t/* Convert the contact from XML to backend Buddies */\n\tisc = sipe_xml_parse(msg->body, len);\n\tif (!isc) {\n\t\treturn FALSE;\n\t}\n\n\t/* [MS-SIP]: deltaNum MUST be non-zero */\n\tdelta = sipe_xml_int_attribute(isc, \"deltaNum\", 0);\n\tif (delta) {\n\t\tsipe_private->deltanum_contacts = delta;\n\t}\n\n\t/*\n\t * Process whole buddy list\n\t *\n\t *  - Only sent once\n\t *    * up to Lync 2010\n\t *    * Lync 2013 (and later) with buddy list not migrated\n\t *\n\t *  - Lync 2013 with buddy list migrated to Unified Contact Store (UCS)\n\t *    * Notify piggy-backed on SUBSCRIBE response with empty list\n\t *    * NOTIFY send by server with standard list (ignored by us)\n\t */\n\tif (sipe_strequal(sipe_xml_name(isc), \"contactList\")) {\n\t\tconst gchar *ucsmode = sipe_xml_attribute(isc, \"ucsmode\");\n\n\t\tSIPE_CORE_PRIVATE_FLAG_UNSET(LYNC2013);\n\t\tif (ucsmode) {\n\t\t\tgboolean migrated = sipe_strcase_equal(ucsmode,\n\t\t\t\t\t\t\t       \"migrated\");\n\t\t\tSIPE_CORE_PRIVATE_FLAG_SET(LYNC2013);\n\t\t\tSIPE_LOG_INFO_NOFORMAT(\"sipe_process_roaming_contacts: contact list contains 'ucsmode' attribute (indicates Lync 2013+)\");\n\n\t\t\tif (migrated)\n\t\t\t\tSIPE_LOG_INFO_NOFORMAT(\"sipe_process_roaming_contacts: contact list has been migrated to Unified Contact Store (UCS)\");\n\t\t\tsipe_ucs_init(sipe_private, migrated);\n\t\t}\n\n\t\tif (!sipe_ucs_is_migrated(sipe_private)) {\n\t\t\t/* Start processing contact list */\n\t\t\tsipe_backend_buddy_list_processing_start(SIPE_CORE_PUBLIC);\n\n\t\t\t/* Parse groups */\n\t\t\tfor (group_node = sipe_xml_child(isc, \"group\"); group_node; group_node = sipe_xml_twin(group_node))\n\t\t\t\tadd_new_group(sipe_private, group_node);\n\n\t\t\t/* Make sure we have at least one group */\n\t\t\tif (sipe_group_count(sipe_private) == 0) {\n\t\t\t\tsipe_group_create(sipe_private,\n\t\t\t\t\t\t  NULL,\n\t\t\t\t\t\t  _(\"Other Contacts\"),\n\t\t\t\t\t\t  NULL);\n\t\t\t}\n\n\t\t\t/* Parse contacts */\n\t\t\tfor (item = sipe_xml_child(isc, \"contact\"); item; item = sipe_xml_twin(item)) {\n\t\t\t\tconst gchar *name = sipe_xml_attribute(item, \"uri\");\n\t\t\t\tgchar *uri        = sip_uri_from_name(name);\n\t\t\t\tadd_new_buddy(sipe_private, item, uri);\n\t\t\t\tg_free(uri);\n\t\t\t}\n\n\t\t\tsipe_buddy_cleanup_local_list(sipe_private);\n\n\t\t\t/* Add self-contact if not there yet. 2005 systems. */\n\t\t\t/* This will resemble subscription to roaming_self in 2007 systems */\n\t\t\tif (!SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {\n\t\t\t\tgchar *self_uri = sip_uri_self(sipe_private);\n\t\t\t\tsipe_buddy_add(sipe_private,\n\t\t\t\t\t       self_uri,\n\t\t\t\t\t       NULL,\n\t\t\t\t\t       NULL);\n\t\t\t\tg_free(self_uri);\n\t\t\t}\n\n\t\t\t/* Finished processing contact list */\n\t\t\tsipe_backend_buddy_list_processing_finish(SIPE_CORE_PUBLIC);\n\t\t}\n\n\t/* Process buddy list updates */\n\t} else if (sipe_strequal(sipe_xml_name(isc), \"contactDelta\")) {\n\n\t\t/* Process new groups */\n\t\tfor (group_node = sipe_xml_child(isc, \"addedGroup\"); group_node; group_node = sipe_xml_twin(group_node))\n\t\t\tadd_new_group(sipe_private, group_node);\n\n\t\t/* Process modified groups */\n\t\tfor (group_node = sipe_xml_child(isc, \"modifiedGroup\"); group_node; group_node = sipe_xml_twin(group_node)) {\n\t\t\tstruct sipe_group *group = sipe_group_find_by_id(sipe_private,\n\t\t\t\t\t\t\t\t\t (int)g_ascii_strtod(sipe_xml_attribute(group_node, \"id\"),\n\t\t\t\t\t\t\t\t\t\t\t     NULL));\n\t\t\tif (group) {\n\t\t\t\tconst gchar *name = get_group_name(group_node);\n\n\t\t\t\tif (!(is_empty(name) ||\n\t\t\t\t      sipe_strequal(group->name, name)) &&\n\t\t\t\t    sipe_group_rename(sipe_private,\n\t\t\t\t\t\t      group,\n\t\t\t\t\t\t      name))\n\t\t\t\t\tSIPE_DEBUG_INFO(\"Replaced group %d name with %s\", group->id, name);\n\t\t\t}\n\t\t}\n\n\t\t/* Process new buddies */\n\t\tfor (item = sipe_xml_child(isc, \"addedContact\"); item; item = sipe_xml_twin(item)) {\n\t\t\tadd_new_buddy(sipe_private,\n\t\t\t\t      item,\n\t\t\t\t      sipe_xml_attribute(item, \"uri\"));\n\t\t}\n\n\t\t/* Process modified buddies */\n\t\tfor (item = sipe_xml_child(isc, \"modifiedContact\"); item; item = sipe_xml_twin(item)) {\n\t\t\tconst gchar *uri = sipe_xml_attribute(item, \"uri\");\n\t\t\tstruct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private,\n\t\t\t\t\t\t\t\t\t  uri);\n\n\t\t\tif (buddy) {\n\t\t\t\tgchar **item_groups = g_strsplit(sipe_xml_attribute(item,\n\t\t\t\t\t\t\t\t\t\t    \"groups\"),\n\t\t\t\t\t\t\t\t \" \", 0);\n\n\t\t\t\t/* this should be defined. Otherwise we would get \"deletedContact\" */\n\t\t\t\tif (item_groups) {\n\t\t\t\t\tconst gchar *name = sipe_xml_attribute(item, \"name\");\n\t\t\t\t\tgboolean empty_name = is_empty(name);\n\t\t\t\t\tGSList *found = NULL;\n\t\t\t\t\tint i = 0;\n\n\t\t\t\t\twhile (item_groups[i]) {\n\t\t\t\t\t\tstruct sipe_group *group = sipe_group_find_by_id(sipe_private,\n\t\t\t\t\t\t\t\t\t\t\t\t g_ascii_strtod(item_groups[i],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tNULL));\n\t\t\t\t\t\t/* ignore unkown groups */\n\t\t\t\t\t\tif (group) {\n\t\t\t\t\t\t\tsipe_backend_buddy b = sipe_backend_buddy_find(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\t\t\t\t       uri,\n\t\t\t\t\t\t\t\t\t\t\t\t       group->name);\n\n\t\t\t\t\t\t\t/* add group to found list */\n\t\t\t\t\t\t\tfound = g_slist_prepend(found, group);\n\n\t\t\t\t\t\t\tif (b) {\n\t\t\t\t\t\t\t\t/* new alias? */\n\t\t\t\t\t\t\t\tgchar *b_alias = sipe_backend_buddy_get_alias(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\t\t\t\t\t      b);\n\n\t\t\t\t\t\t\t\tif (!(empty_name ||\n\t\t\t\t\t\t\t\t      sipe_strequal(b_alias, name))) {\n\t\t\t\t\t\t\t\t\tsipe_backend_buddy_set_alias(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\t\t\t\t     b,\n\t\t\t\t\t\t\t\t\t\t\t\t     name);\n\t\t\t\t\t\t\t\t\tSIPE_DEBUG_INFO(\"Replaced for buddy %s in group '%s' old alias '%s' with '%s'\",\n\t\t\t\t\t\t\t\t\t\t\turi, group->name, b_alias, name);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tg_free(b_alias);\n\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tconst gchar *alias = empty_name ? uri : name;\n\t\t\t\t\t\t\t\t/* buddy was not in this group */\n\t\t\t\t\t\t\t\tsipe_backend_buddy_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\t\t       uri,\n\t\t\t\t\t\t\t\t\t\t       alias,\n\t\t\t\t\t\t\t\t\t\t       group->name);\n\t\t\t\t\t\t\t\tsipe_buddy_insert_group(buddy, group);\n\t\t\t\t\t\t\t\tSIPE_DEBUG_INFO(\"Added buddy %s (alias '%s' to group '%s'\",\n\t\t\t\t\t\t\t\t\t\turi, alias, group->name);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/* next group */\n\t\t\t\t\t\ti++;\n\t\t\t\t\t}\n\t\t\t\t\tg_strfreev(item_groups);\n\n \t\t\t\t\t/* removed from groups? */\n\t\t\t\t\tsipe_buddy_update_groups(sipe_private,\n\t\t\t\t\t\t\t\t buddy,\n\t\t\t\t\t\t\t\t found);\n\t\t\t\t\tg_slist_free(found);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Process deleted buddies */\n\t\tfor (item = sipe_xml_child(isc, \"deletedContact\"); item; item = sipe_xml_twin(item)) {\n\t\t\tconst gchar *uri = sipe_xml_attribute(item, \"uri\");\n\t\t\tstruct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private,\n\t\t\t\t\t\t\t\t\t  uri);\n\n\t\t\tif (buddy) {\n\t\t\t\tSIPE_DEBUG_INFO(\"Removing buddy %s\", uri);\n\t\t\t\tsipe_buddy_remove(sipe_private, buddy);\n\t\t\t}\n\t\t}\n\n\t\t/* Process deleted groups\n\t\t *\n\t\t * NOTE: all buddies will already have been removed from the\n\t\t *       group prior to this. The log shows that OCS actually\n\t\t *       sends two separate updates when you delete a group:\n\t\t *\n\t\t *         - first one with \"modifiedContact\" removing buddies\n\t\t *           from the group, leaving it empty, and\n\t\t *\n\t\t *         - then one with \"deletedGroup\" removing the group\n\t\t */\n\t\tfor (group_node = sipe_xml_child(isc, \"deletedGroup\"); group_node; group_node = sipe_xml_twin(group_node))\n\t\t\tsipe_group_remove(sipe_private,\n\t\t\t\t\t  sipe_group_find_by_id(sipe_private,\n\t\t\t\t\t\t\t\t(int)g_ascii_strtod(sipe_xml_attribute(group_node, \"id\"),\n\t\t\t\t\t\t\t\t\t\t    NULL)));\n\n\t}\n\tsipe_xml_free(isc);\n\n\t/* Subscribe to buddies, if contact list not migrated to UCS */\n\tif (!sipe_ucs_is_migrated(sipe_private))\n\t\tsipe_subscribe_presence_initial(sipe_private);\n\n\t/* for 2005 systems schedule contacts' status update\n\t * based on their calendar information\n\t */\n\tif (!SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {\n\t\tsipe_ocs2005_schedule_status_update(sipe_private, time(NULL));\n\t}\n\n\treturn 0;\n}\n\nstatic void sipe_process_roaming_acl(struct sipe_core_private *sipe_private,\n\t\t\t\t     struct sipmsg *msg)\n{\n\tguint delta;\n\tsipe_xml *xml;\n\n\txml = sipe_xml_parse(msg->body, msg->bodylen);\n\tif (!xml)\n\t\treturn;\n\n\t/* [MS-SIP]: deltaNum MUST be non-zero */\n\tdelta = sipe_xml_int_attribute(xml, \"deltaNum\", 0);\n\tif (delta) {\n\t\tsipe_private->deltanum_acl = delta;\n\t}\n\n\tsipe_xml_free(xml);\n}\n\nstruct sipe_auth_job {\n\tgchar *who;\n\tstruct sipe_core_private *sipe_private;\n};\n\nvoid sipe_core_contact_allow_deny(struct sipe_core_public *sipe_public,\n\t\t\t\t  const gchar* who,\n\t\t\t\t  gboolean allow)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\n\tif (allow) {\n\t\tSIPE_DEBUG_INFO(\"sipe_core_contact_allow_deny: authorizing contact %s\", who);\n\t} else {\n\t\tSIPE_DEBUG_INFO(\"sipe_core_contact_allow_deny: blocking contact %s\", who);\n\t}\n\n\tif (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {\n\t\tsipe_ocs2007_change_access_level(sipe_private,\n\t\t\t\t\t\t (allow ? -1 : 32000),\n\t\t\t\t\t\t \"user\",\n\t\t\t\t\t\t sipe_get_no_sip_uri(who));\n\t} else {\n\t\tsip_soap_ocs2005_setacl(sipe_private, who, allow);\n\t}\n}\n\n\nstatic void sipe_auth_user_cb(gpointer data)\n{\n\tstruct sipe_auth_job *job = (struct sipe_auth_job *) data;\n\tif (!job) return;\n\n\tsipe_core_contact_allow_deny((struct sipe_core_public *)job->sipe_private,\n\t\t\t\t     job->who,\n\t\t\t\t     TRUE);\n\tg_free(job);\n}\n\nstatic void sipe_deny_user_cb(gpointer data)\n{\n\tstruct sipe_auth_job *job = (struct sipe_auth_job *) data;\n\tif (!job) return;\n\n\tsipe_core_contact_allow_deny((struct sipe_core_public *)job->sipe_private,\n\t\t\t\t     job->who,\n\t\t\t\t     FALSE);\n\tg_free(job);\n}\n\n/* OCS2005- */\nstatic void sipe_process_presence_wpending (struct sipe_core_private *sipe_private,\n\t\t\t\t\t    struct sipmsg * msg)\n{\n\tsipe_xml *watchers;\n\tconst sipe_xml *watcher;\n\t// Ensure it's either not a response (eg it's a BENOTIFY) or that it's a 200 OK response\n\tif (msg->response != 0 && msg->response != 200) return;\n\n\tif (msg->bodylen == 0 || msg->body == NULL || sipe_strequal(sipmsg_find_event_header(msg), \"msrtc.wpending\")) return;\n\n\twatchers = sipe_xml_parse(msg->body, msg->bodylen);\n\tif (!watchers) return;\n\n\tfor (watcher = sipe_xml_child(watchers, \"watcher\"); watcher; watcher = sipe_xml_twin(watcher)) {\n\t\tgchar * remote_user = g_strdup(sipe_xml_attribute(watcher, \"uri\"));\n\t\tgchar * alias = g_strdup(sipe_xml_attribute(watcher, \"displayName\"));\n\t\tgboolean on_list = sipe_buddy_find_by_uri(sipe_private, remote_user) != NULL;\n\n\t\t// TODO pull out optional displayName to pass as alias\n\t\tif (remote_user) {\n\t\t\tstruct sipe_auth_job * job = g_new0(struct sipe_auth_job, 1);\n\t\t\tjob->who = remote_user;\n\t\t\tjob->sipe_private = sipe_private;\n\t\t\tsipe_backend_buddy_request_authorization(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t remote_user,\n\t\t\t\t\t\t\t\t alias,\n\t\t\t\t\t\t\t\t on_list,\n\t\t\t\t\t\t\t\t sipe_auth_user_cb,\n\t\t\t\t\t\t\t\t sipe_deny_user_cb,\n\t\t\t\t\t\t\t\t (gpointer)job);\n\t\t}\n\t}\n\n\n\tsipe_xml_free(watchers);\n\treturn;\n}\n\n/**\n * Dispatcher for all incoming subscription information\n * whether it comes from NOTIFY, BENOTIFY requests or\n * piggy-backed to subscription's OK responce.\n */\nvoid process_incoming_notify(struct sipe_core_private *sipe_private,\n\t\t\t     struct sipmsg *msg)\n{\n\tconst gchar *content_type = sipmsg_find_content_type_header(msg);\n\tconst gchar *event = sipmsg_find_event_header(msg);\n\tconst gchar *subscription_state = sipmsg_find_header(msg, \"subscription-state\");\n\n\tSIPE_DEBUG_INFO(\"process_incoming_notify: subscription_state: %s\", subscription_state ? subscription_state : \"\");\n\n\t/* implicit subscriptions */\n\tif (content_type && g_str_has_prefix(content_type, \"application/ms-imdn+xml\")) {\n\t\tsipe_process_imdn(sipe_private, msg);\n\n\t/* event subscriptions */\n\t} else if (event) {\n\n\t\t/* One-off subscriptions - sent with \"Expires: 0\" */\n\t\tif (sipe_strcase_equal(event, \"vnd-microsoft-provisioning-v2\")) {\n\t\t\tsipe_process_provisioning_v2(sipe_private, msg);\n\t\t} else if (sipe_strcase_equal(event, \"vnd-microsoft-provisioning\")) {\n\t\t\tsipe_process_provisioning(sipe_private, msg);\n\t\t} else if (sipe_strcase_equal(event, \"presence\")) {\n\t\t\tsipe_process_presence(sipe_private, msg);\n\t\t} else if (sipe_strcase_equal(event, \"registration-notify\")) {\n\t\t\tsipe_process_registration_notify(sipe_private, msg);\n\n\t\t/* Subscriptions with timeout */\n\t\t} else if (!subscription_state || strstr(subscription_state, \"active\")) {\n\t\t\tif (sipe_strcase_equal(event, \"vnd-microsoft-roaming-contacts\")) {\n\t\t\t\tsipe_process_roaming_contacts(sipe_private, msg);\n\t\t\t} else if (sipe_strcase_equal(event, \"vnd-microsoft-roaming-self\")) {\n\t\t\t\tsipe_ocs2007_process_roaming_self(sipe_private, msg);\n\t\t\t} else if (sipe_strcase_equal(event, \"vnd-microsoft-roaming-ACL\")) {\n\t\t\t\tsipe_process_roaming_acl(sipe_private, msg);\n\t\t\t} else if (sipe_strcase_equal(event, \"presence.wpending\")) {\n\t\t\t\tsipe_process_presence_wpending(sipe_private, msg);\n\t\t\t} else if (sipe_strcase_equal(event, \"conference\")) {\n\t\t\t\tsipe_process_conference(sipe_private, msg);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-notify.h",
    "content": "/**\n * @file sipe-notify.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2013 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipmsg;\nstruct sipe_core_private;\n\nvoid process_incoming_notify(struct sipe_core_private *sipe_private,\n\t\t\t     struct sipmsg *msg);\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-ocs2005.c",
    "content": "/**\n * @file sipe-ocs2005.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * OCS2005 specific code\n *\n */\n\n#include <time.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sip-soap.h\"\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-buddy.h\"\n#include \"sipe-cal.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-ews.h\"\n#include \"sipe-ocs2005.h\"\n#include \"sipe-ocs2007.h\"\n#include \"sipe-schedule.h\"\n#include \"sipe-status.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n\n/**\n * 2005-style Activity and Availability.\n *\n * [MS-SIP] 2.2.1\n *\n * @param activity\t2005 aggregated activity.    Ex.: 600\n * @param availablity\t2005 aggregated availablity. Ex.: 300\n *\n * The values define the starting point of a range\n */\n#define SIPE_OCS2005_ACTIVITY_UNKNOWN       0\n#define SIPE_OCS2005_ACTIVITY_AWAY        100\n#define SIPE_OCS2005_ACTIVITY_LUNCH       150\n#define SIPE_OCS2005_ACTIVITY_IDLE        200\n#define SIPE_OCS2005_ACTIVITY_BRB         300\n#define SIPE_OCS2005_ACTIVITY_AVAILABLE   400 /* user is active */\n#define SIPE_OCS2005_ACTIVITY_ON_PHONE    500 /* user is participating in a communcation session */\n#define SIPE_OCS2005_ACTIVITY_BUSY        600\n#define SIPE_OCS2005_ACTIVITY_AWAY2       700\n#define SIPE_OCS2005_ACTIVITY_AVAILABLE2  800\n\n#define SIPE_OCS2005_AVAILABILITY_OFFLINE   0\n#define SIPE_OCS2005_AVAILABILITY_MAYBE   100\n#define SIPE_OCS2005_AVAILABILITY_ONLINE  300\nstatic guint sipe_ocs2005_activity_from_status(struct sipe_core_private *sipe_private)\n{\n\tconst gchar *status = sipe_private->status;\n\n\tif (sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_AWAY))) {\n\t\treturn(SIPE_OCS2005_ACTIVITY_AWAY);\n\t/*} else if (sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_LUNCH))) {\n\t\treturn(SIPE_OCS2005_ACTIVITY_LUNCH); */\n\t} else if (sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_BRB))) {\n\t\treturn(SIPE_OCS2005_ACTIVITY_BRB);\n\t} else if (sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_AVAILABLE))) {\n\t\treturn(SIPE_OCS2005_ACTIVITY_AVAILABLE);\n\t/*} else if (sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_ON_PHONE))) {\n\t\treturn(SIPE_OCS2005_ACTIVITY_ON_PHONE); */\n\t} else if (sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_BUSY)) ||\n\t\t   sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_DND))) {\n\t\treturn(SIPE_OCS2005_ACTIVITY_BUSY);\n\t} else if (sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_INVISIBLE)) ||\n\t\t   sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_OFFLINE))) {\n\t\treturn(SIPE_OCS2005_ACTIVITY_AWAY);\n\t} else {\n\t\treturn(SIPE_OCS2005_ACTIVITY_AVAILABLE);\n\t}\n}\n\nstatic guint sipe_ocs2005_availability_from_status(struct sipe_core_private *sipe_private)\n{\n\tconst gchar *status = sipe_private->status;\n\n\tif (sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_INVISIBLE)) ||\n\t    sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_OFFLINE)))\n\t\treturn(SIPE_OCS2005_AVAILABILITY_OFFLINE);\n\telse\n\t\treturn(SIPE_OCS2005_AVAILABILITY_ONLINE);\n}\n\nconst gchar *sipe_ocs2005_status_from_activity_availability(guint activity,\n\t\t\t\t\t\t\t    guint availability)\n{\n\tguint type;\n\n\tif (availability < SIPE_OCS2005_AVAILABILITY_MAYBE) {\n\t\ttype = SIPE_ACTIVITY_OFFLINE;\n\t} else if (activity < SIPE_OCS2005_ACTIVITY_LUNCH) {\n\t\ttype = SIPE_ACTIVITY_AWAY;\n\t} else if (activity < SIPE_OCS2005_ACTIVITY_IDLE) {\n\t\t//type = SIPE_ACTIVITY_LUNCH;\n\t\ttype = SIPE_ACTIVITY_AWAY;\n\t} else if (activity < SIPE_OCS2005_ACTIVITY_BRB) {\n\t\t//type = SIPE_ACTIVITY_IDLE;\n\t\ttype = SIPE_ACTIVITY_AWAY;\n\t} else if (activity < SIPE_OCS2005_ACTIVITY_AVAILABLE) {\n\t\ttype = SIPE_ACTIVITY_BRB;\n\t} else if (activity < SIPE_OCS2005_ACTIVITY_ON_PHONE) {\n\t\ttype = SIPE_ACTIVITY_AVAILABLE;\n\t} else if (activity < SIPE_OCS2005_ACTIVITY_BUSY) {\n\t\t//type = SIPE_ACTIVITY_ON_PHONE;\n\t\ttype = SIPE_ACTIVITY_BUSY;\n\t} else if (activity < SIPE_OCS2005_ACTIVITY_AWAY2) {\n\t\ttype = SIPE_ACTIVITY_BUSY;\n\t} else if (activity < SIPE_OCS2005_ACTIVITY_AVAILABLE2) {\n\t\ttype = SIPE_ACTIVITY_AWAY;\n\t} else {\n\t\ttype = SIPE_ACTIVITY_AVAILABLE;\n\t}\n\n\treturn(sipe_status_activity_to_token(type));\n}\n\nconst gchar *sipe_ocs2005_activity_description(guint activity)\n{\n\tif ((activity >= SIPE_OCS2005_ACTIVITY_LUNCH) &&\n\t    (activity <  SIPE_OCS2005_ACTIVITY_IDLE)) {\n\t\treturn(sipe_core_activity_description(SIPE_ACTIVITY_LUNCH));\n\t} else if ((activity >= SIPE_OCS2005_ACTIVITY_IDLE) &&\n\t\t   (activity <  SIPE_OCS2005_ACTIVITY_BRB)) {\n\t\treturn(sipe_core_activity_description(SIPE_ACTIVITY_INACTIVE));\n\t} else if ((activity >= SIPE_OCS2005_ACTIVITY_ON_PHONE) &&\n\t\t   (activity <  SIPE_OCS2005_ACTIVITY_BUSY)) {\n\t\treturn(sipe_core_activity_description(SIPE_ACTIVITY_ON_PHONE));\n\t} else {\n\t\treturn(NULL);\n\t}\n}\n\nvoid sipe_ocs2005_user_info_has_updated(struct sipe_core_private *sipe_private,\n\t\t\t\t\tconst sipe_xml *xn_userinfo)\n{\n\tconst sipe_xml *xn_states;\n\n\tg_free(sipe_private->ocs2005_user_states);\n\tsipe_private->ocs2005_user_states = NULL;\n\tif ((xn_states = sipe_xml_child(xn_userinfo, \"states\")) != NULL) {\n\t\tgchar *orig = sipe_private->ocs2005_user_states = sipe_xml_stringify(xn_states);\n\n\t\t/* this is a hack-around to remove added newline after inner element,\n\t\t * state in this case, where it shouldn't be.\n\t\t * After several use of sipe_xml_stringify, amount of added newlines\n\t\t * grows significantly.\n\t\t */\n\t\tif (orig) {\n\t\t\tgchar c, *stripped = orig;\n\t\t\twhile ((c = *orig++)) {\n\t\t\t\tif ((c != '\\n') /* && (c != '\\r') */) {\n\t\t\t\t\t*stripped++ = c;\n\t\t\t\t}\n\t\t\t}\n\t\t\t*stripped = '\\0';\n\t\t}\n\t}\n\n\t/* Publish initial state if not yet.\n\t * Assuming this happens on initial responce to self subscription\n\t * so we've already updated our UserInfo.\n\t */\n\tif (!SIPE_CORE_PRIVATE_FLAG_IS(INITIAL_PUBLISH)) {\n\t\tsipe_ocs2005_presence_publish(sipe_private, FALSE);\n\t\t/* dalayed run */\n\t\tsipe_cal_delayed_calendar_update(sipe_private);\n\t}\n}\n\nstatic gboolean sipe_is_user_available(struct sipe_core_private *sipe_private)\n{\n\treturn(sipe_strequal(sipe_private->status,\n\t\t\t     sipe_status_activity_to_token(SIPE_ACTIVITY_AVAILABLE)));\n}\n\n\n/**\n * OCS2005 presence XML messages\n *\n * Calendar publication entry\n *\n * @param legacy_dn\t\t(%s) Ex.: /o=EXCHANGE/ou=BTUK02/cn=Recipients/cn=AHHBTT\n * @param fb_start_time_str\t(%s) Ex.: 2009-12-06T17:15:00Z\n * @param free_busy_base64\t(%s) Ex.: AAAAAAAAAAAAAAAAA......\n */\n#define SIPE_SOAP_SET_PRESENCE_CALENDAR \\\n\"<calendarInfo xmlns=\\\"http://schemas.microsoft.com/2002/09/sip/presence\\\" mailboxId=\\\"%s\\\" startTime=\\\"%s\\\" granularity=\\\"PT15M\\\">%s</calendarInfo>\"\n\n/**\n * Note publication entry\n *\n * @param note\t(%s) Ex.: Working from home\n */\n#define SIPE_SOAP_SET_PRESENCE_NOTE_XML  \"<note>%s</note>\"\n\n/**\n * Note's OOF publication entry\n */\n#define SIPE_SOAP_SET_PRESENCE_OOF_XML  \"<oof></oof>\"\n\n/**\n * States publication entry for User State\n *\n * @param avail\t\t\t(%d) Availability 2007-style. Ex.: 9500\n * @param since_time_str\t(%s) Ex.: 2010-01-13T10:30:05Z\n * @param device_id\t\t(%s) epid. Ex.: 4c77e6ec72\n * @param activity_token\t(%s) Ex.: do-not-disturb\n */\n#define SIPE_SOAP_SET_PRESENCE_STATES \\\n          \"<states>\"\\\n            \"<state avail=\\\"%d\\\" since=\\\"%s\\\" validWith=\\\"any-device\\\" deviceId=\\\"%s\\\" set=\\\"manual\\\" xsi:type=\\\"userState\\\">%s</state>\"\\\n          \"</states>\"\n\n/**\n * Presentity publication entry.\n *\n * @param uri\t\t\t(%s) SIP URI without 'sip:' prefix. Ex.: fox@atlanta.local\n * @param aggr_availability\t(%d) Ex.: 300\n * @param aggr_activity\t\t(%d) Ex.: 600\n * @param host_name\t\t(%s) Uppercased. Ex.: ATLANTA\n * @param note_xml_str\t\t(%s) XML string as SIPE_SOAP_SET_PRESENCE_NOTE_XML\n * @param oof_xml_str\t\t(%s) XML string as SIPE_SOAP_SET_PRESENCE_OOF_XML\n * @param states_xml_str\t(%s) XML string as SIPE_SOAP_SET_PRESENCE_STATES\n * @param calendar_info_xml_str\t(%s) XML string as SIPE_SOAP_SET_PRESENCE_CALENDAR\n * @param device_id\t\t(%s) epid. Ex.: 4c77e6ec72\n * @param since_time_str\t(%s) Ex.: 2010-01-13T10:30:05Z\n * @param since_time_str\t(%s) Ex.: 2010-01-13T10:30:05Z\n * @param user_input\t\t(%s) active, idle\n */\n#define SIPE_SOAP_SET_PRESENCE \\\n\t\"<s:Envelope\" \\\n        \" xmlns:s=\\\"http://schemas.xmlsoap.org/soap/envelope/\\\"\" \\\n\t\" xmlns:m=\\\"http://schemas.microsoft.com/winrtc/2002/11/sip\\\"\" \\\n\t\">\" \\\n\t\"<s:Body>\" \\\n\t\"<m:setPresence>\" \\\n\t\"<m:presentity xmlns:xsi=\\\"http://www.w3.org/2001/XMLSchema-instance\\\" m:uri=\\\"sip:%s\\\">\"\\\n\t\"<m:availability m:aggregate=\\\"%d\\\"/>\"\\\n\t\"<m:activity m:aggregate=\\\"%d\\\"/>\"\\\n\t\"<deviceName xmlns=\\\"http://schemas.microsoft.com/2002/09/sip/presence\\\" name=\\\"%s\\\"/>\"\\\n\t\"<rtc:devicedata xmlns:rtc=\\\"http://schemas.microsoft.com/winrtc/2002/11/sip\\\" namespace=\\\"rtcService\\\">\"\\\n\t\"<![CDATA[<caps><renders_gif/><renders_isf/></caps>]]></rtc:devicedata>\"\\\n\t\"<userInfo xmlns=\\\"http://schemas.microsoft.com/2002/09/sip/presence\\\">\"\\\n\t\"%s%s\" \\\n\t\"%s\" \\\n        \"</userInfo>\"\\\n\t\"%s\" \\\n\t\"<device xmlns=\\\"http://schemas.microsoft.com/2002/09/sip/presence\\\" deviceId=\\\"%s\\\" since=\\\"%s\\\" >\"\\\n\t\t\"<userInput since=\\\"%s\\\" >%s</userInput>\"\\\n\t\"</device>\"\\\n\t\"</m:presentity>\" \\\n\t\"</m:setPresence>\"\\\n\t\"</s:Body>\" \\\n\t\"</s:Envelope>\"\n\nstatic void send_presence_soap(struct sipe_core_private *sipe_private,\n\t\t\t       gboolean do_publish_calendar,\n\t\t\t       gboolean do_reset_status)\n{\n\tstruct sipe_calendar* cal = sipe_private->calendar;\n\tgchar *body;\n\tgchar *tmp;\n\tgchar *tmp2 = NULL;\n\tgchar *res_note = NULL;\n\tconst gchar *res_oof = NULL;\n\tconst gchar *note_pub = NULL;\n\tgchar *states = NULL;\n\tgchar *calendar_data = NULL;\n\tconst gchar *epid = sip_transport_epid(sipe_private);\n\tgchar *from = sip_uri_self(sipe_private);\n\ttime_t now = time(NULL);\n\tgchar *since_time_str = sipe_utils_time_to_str(now);\n\tconst gchar *oof_note = cal ? sipe_ews_get_oof_note(cal) : NULL;\n\tconst char *user_input;\n\tgboolean pub_oof = cal && oof_note && (!sipe_private->note || cal->updated > sipe_private->note_since);\n\n\tif (oof_note && sipe_private->note) {\n\t\tSIPE_DEBUG_INFO(\"cal->oof_start           : %s\", sipe_utils_time_to_debug_str(localtime(&(cal->oof_start))));\n\t\tSIPE_DEBUG_INFO(\"sipe_private->note_since : %s\", sipe_utils_time_to_debug_str(localtime(&(sipe_private->note_since))));\n\t}\n\n\tSIPE_DEBUG_INFO(\"sipe_private->note  : %s\", sipe_private->note ? sipe_private->note : \"\");\n\n\tif (!SIPE_CORE_PRIVATE_FLAG_IS(INITIAL_PUBLISH) ||\n\t    do_reset_status)\n\t\tsipe_status_set_activity(sipe_private, SIPE_ACTIVITY_AVAILABLE);\n\n\t/* Note */\n\tif (pub_oof) {\n\t\tnote_pub = oof_note;\n\t\tres_oof = SIPE_SOAP_SET_PRESENCE_OOF_XML;\n\t\tcal->published = TRUE;\n\t} else if (sipe_private->note) {\n\t\tif (SIPE_CORE_PRIVATE_FLAG_IS(OOF_NOTE) &&\n\t\t    !oof_note) { /* stale OOF note, as it's not present in cal already */\n\t\t\tg_free(sipe_private->note);\n\t\t\tsipe_private->note = NULL;\n\t\t\tSIPE_CORE_PRIVATE_FLAG_UNSET(OOF_NOTE);\n\t\t\tsipe_private->note_since = 0;\n\t\t} else {\n\t\t\tnote_pub = sipe_private->note;\n\t\t\tres_oof = SIPE_CORE_PRIVATE_FLAG_IS(OOF_NOTE) ? SIPE_SOAP_SET_PRESENCE_OOF_XML : \"\";\n\t\t}\n\t}\n\n\tif (note_pub)\n\t{\n\t\t/* to protocol internal plain text format */\n\t\ttmp = sipe_backend_markup_strip_html(note_pub);\n\t\tres_note = g_markup_printf_escaped(SIPE_SOAP_SET_PRESENCE_NOTE_XML, tmp);\n\t\tg_free(tmp);\n\t}\n\n\t/* User State */\n\tif (!do_reset_status) {\n\t\tif (sipe_private->status_set_by_user &&\n\t\t    !do_publish_calendar &&\n\t\t    SIPE_CORE_PRIVATE_FLAG_IS(INITIAL_PUBLISH)) {\n\t\t\tconst gchar *activity_token;\n\t\t\tint avail_2007 = sipe_ocs2007_availability_from_status(sipe_private->status,\n\t\t\t\t\t\t\t\t\t       &activity_token);\n\n\t\t\tstates = g_strdup_printf(SIPE_SOAP_SET_PRESENCE_STATES,\n\t\t\t\t\t\tavail_2007,\n\t\t\t\t\t\tsince_time_str,\n\t\t\t\t\t\tepid,\n\t\t\t\t\t\tactivity_token);\n\t\t}\n\t\telse /* preserve existing publication */\n\t\t{\n\t\t\tif (sipe_private->ocs2005_user_states) {\n\t\t\t\tstates = g_strdup(sipe_private->ocs2005_user_states);\n\t\t\t}\n\t\t}\n\t} else {\n\t\t/* do nothing - then User state will be erased */\n\t}\n\tSIPE_CORE_PRIVATE_FLAG_SET(INITIAL_PUBLISH);\n\n\t/* CalendarInfo */\n\tif (cal && (!is_empty(cal->legacy_dn) || !is_empty(cal->email)) && cal->fb_start && !is_empty(cal->free_busy))\n\t{\n\t\tchar *fb_start_str = sipe_utils_time_to_str(cal->fb_start);\n\t\tchar *free_busy_base64 = sipe_cal_get_freebusy_base64(cal->free_busy);\n\t\tcalendar_data = g_strdup_printf(SIPE_SOAP_SET_PRESENCE_CALENDAR,\n\t\t\t\t\t\t!is_empty(cal->legacy_dn) ? cal->legacy_dn : cal->email,\n\t\t\t\t\t\tfb_start_str,\n\t\t\t\t\t\tfree_busy_base64);\n\t\tg_free(fb_start_str);\n\t\tg_free(free_busy_base64);\n\t}\n\n\tuser_input = (sipe_private->status_set_by_user ||\n\t\t      sipe_is_user_available(sipe_private)) ?\n\t\t\"active\" : \"idle\";\n\n\t/* generate XML */\n\tbody = g_strdup_printf(SIPE_SOAP_SET_PRESENCE,\n\t\t\t       sipe_private->username,\n\t\t\t       sipe_ocs2005_availability_from_status(sipe_private),\n\t\t\t       sipe_ocs2005_activity_from_status(sipe_private),\n\t\t\t       (tmp = g_ascii_strup(g_get_host_name(), -1)),\n\t\t\t       res_note ? res_note : \"\",\n\t\t\t       res_oof ? res_oof : \"\",\n\t\t\t       states ? states : \"\",\n\t\t\t       calendar_data ? calendar_data : \"\",\n\t\t\t       epid,\n\t\t\t       since_time_str,\n\t\t\t       since_time_str,\n\t\t\t       user_input);\n\tg_free(tmp);\n\tg_free(tmp2);\n\tg_free(res_note);\n\tg_free(states);\n\tg_free(calendar_data);\n\tg_free(since_time_str);\n\n\tsip_soap_raw_request_cb(sipe_private, from, body, NULL, NULL);\n\n\tg_free(body);\n}\n\nvoid sipe_ocs2005_presence_publish(struct sipe_core_private *sipe_private,\n\t\t\t\t   gboolean do_publish_calendar)\n{\n\tsend_presence_soap(sipe_private, do_publish_calendar, FALSE);\n}\n\nvoid sipe_ocs2005_reset_status(struct sipe_core_private *sipe_private)\n{\n\tsend_presence_soap(sipe_private, FALSE, TRUE);\n}\n\nvoid sipe_ocs2005_apply_calendar_status(struct sipe_core_private *sipe_private,\n\t\t\t\t\tstruct sipe_buddy *sbuddy,\n\t\t\t\t\tconst char *status_id)\n{\n\ttime_t cal_avail_since;\n\tint cal_status = sipe_cal_get_status(sbuddy, time(NULL), &cal_avail_since);\n\tint avail;\n\tgchar *self_uri;\n\n\tif (!sbuddy) return;\n\n\tif (cal_status < SIPE_CAL_NO_DATA) {\n\t\tSIPE_DEBUG_INFO(\"sipe_apply_calendar_status: cal_status      : %d for %s\", cal_status, sbuddy->name);\n\t\tSIPE_DEBUG_INFO(\"sipe_apply_calendar_status: cal_avail_since : %s\", sipe_utils_time_to_debug_str(localtime(&cal_avail_since)));\n\t}\n\n\t/* scheduled Cal update call */\n\tif (!status_id) {\n\t\tstatus_id = sbuddy->last_non_cal_status_id;\n\t\tg_free(sbuddy->activity);\n\t\tsbuddy->activity = g_strdup(sbuddy->last_non_cal_activity);\n\t}\n\n\tif (!status_id) {\n\t\tSIPE_DEBUG_INFO(\"sipe_apply_calendar_status: status_id is NULL for %s, exiting.\",\n\t\t\t\tsbuddy->name ? sbuddy->name : \"\" );\n\t\treturn;\n\t}\n\n\t/* adjust to calendar status */\n\tif (cal_status != SIPE_CAL_NO_DATA) {\n\t\tSIPE_DEBUG_INFO(\"sipe_apply_calendar_status: user_avail_since: %s\", sipe_utils_time_to_debug_str(localtime(&sbuddy->user_avail_since)));\n\n\t\tif ((cal_status == SIPE_CAL_BUSY) &&\n\t\t    (cal_avail_since > sbuddy->user_avail_since) &&\n\t\t    sipe_ocs2007_status_is_busy(status_id)) {\n\t\t\tstatus_id = sipe_status_activity_to_token(SIPE_ACTIVITY_BUSY);\n\t\t\tg_free(sbuddy->activity);\n\t\t\tsbuddy->activity = g_strdup(sipe_core_activity_description(SIPE_ACTIVITY_IN_MEETING));\n\t\t}\n\t\tavail = sipe_ocs2007_availability_from_status(status_id, NULL);\n\n\t\tSIPE_DEBUG_INFO(\"sipe_apply_calendar_status: activity_since  : %s\", sipe_utils_time_to_debug_str(localtime(&sbuddy->activity_since)));\n\t\tif (cal_avail_since > sbuddy->activity_since) {\n\t\t\tif ((cal_status == SIPE_CAL_OOF) &&\n\t\t\t    sipe_ocs2007_availability_is_away(avail)) {\n\t\t\t\tg_free(sbuddy->activity);\n\t\t\t\tsbuddy->activity = g_strdup(sipe_core_activity_description(SIPE_ACTIVITY_OOF));\n\t\t\t}\n\t\t}\n\t}\n\n\t/* then set status_id actually */\n\tSIPE_DEBUG_INFO(\"sipe_apply_calendar_status: to %s for %s\", status_id, sbuddy->name ? sbuddy->name : \"\" );\n\tsipe_backend_buddy_set_status(SIPE_CORE_PUBLIC, sbuddy->name,\n\t\t\t\t      sipe_status_token_to_activity(status_id),\n\t\t                      0);\n\n\t/* set our account state to the one in roaming (including calendar info) */\n\tself_uri = sip_uri_self(sipe_private);\n\tif (SIPE_CORE_PRIVATE_FLAG_IS(INITIAL_PUBLISH) &&\n\t    sipe_strcase_equal(sbuddy->name, self_uri)) {\n\t\tif (sipe_strequal(status_id, sipe_status_activity_to_token(SIPE_ACTIVITY_OFFLINE))) {\n\t\t\t/* do not let offline status switch us off */\n\t\t\tstatus_id = sipe_status_activity_to_token(SIPE_ACTIVITY_INVISIBLE);\n\t\t}\n\n\t\tsipe_status_and_note(sipe_private, status_id);\n\t}\n\tg_free(self_uri);\n}\n\nstatic void update_calendar_status_cb(SIPE_UNUSED_PARAMETER char *name,\n\t\t\t\t      struct sipe_buddy *sbuddy,\n\t\t\t\t      struct sipe_core_private *sipe_private)\n{\n\tsipe_ocs2005_apply_calendar_status(sipe_private, sbuddy, NULL);\n}\n\n/**\n * Updates contact's status\n * based on their calendar information.\n */\nstatic void update_calendar_status(struct sipe_core_private *sipe_private,\n\t\t\t\t   SIPE_UNUSED_PARAMETER void *unused)\n{\n\tSIPE_DEBUG_INFO_NOFORMAT(\"update_calendar_status() started.\");\n\tsipe_buddy_foreach(sipe_private,\n\t\t\t   (GHFunc) update_calendar_status_cb,\n\t\t\t   sipe_private);\n\n\t/* repeat scheduling */\n\tsipe_ocs2005_schedule_status_update(sipe_private,\n\t\t\t\t\t    time(NULL) + 3 * 60 /* 3 min */);\n}\n\n/**\n * Schedules process of contacts' status update\n * based on their calendar information.\n * Should be scheduled to the beginning of every\n * 15 min interval, like:\n * 13:00, 13:15, 13:30, 13:45, etc.\n */\nvoid sipe_ocs2005_schedule_status_update(struct sipe_core_private *sipe_private,\n\t\t\t\t\t time_t calculate_from)\n{\n#define SCHEDULE_INTERVAL 15 * 60 /* 15 min */\n\n\t/* start of the beginning of closest 15 min interval. */\n\ttime_t next_start = (calculate_from / SCHEDULE_INTERVAL + 1) * SCHEDULE_INTERVAL;\n\n\tSIPE_DEBUG_INFO(\"sipe_ocs2005_schedule_status_update: calculate_from time: %s\",\n\t\t\tsipe_utils_time_to_debug_str(localtime(&calculate_from)));\n\tSIPE_DEBUG_INFO(\"sipe_ocs2005_schedule_status_update: next start time    : %s\",\n\t\t\tsipe_utils_time_to_debug_str(localtime(&next_start)));\n\n\tsipe_schedule_seconds(sipe_private,\n\t\t\t      \"<+2005-cal-status>\",\n\t\t\t      NULL,\n\t\t\t      next_start - time(NULL),\n\t\t\t      update_calendar_status,\n\t\t\t      NULL);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-ocs2005.h",
    "content": "/**\n * @file sipe-ocs2005.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct _sipe_xml;\nstruct sipe_core_private;\n\n/**\n * OCS2005 status ID, availability & activity\n */\nconst gchar *sipe_ocs2005_status_from_activity_availability(guint activity,\n\t\t\t\t\t\t\t    guint availablity);\nconst gchar *sipe_ocs2005_activity_description(guint activity);\n\n/**\n * Publish status (OCS2005)\n */\nvoid sipe_ocs2005_presence_publish(struct sipe_core_private *sipe_private,\n\t\t\t\t   gboolean do_publish_calendar);\nvoid sipe_ocs2005_reset_status(struct sipe_core_private *sipe_private);\nvoid sipe_ocs2005_user_info_has_updated(struct sipe_core_private *sipe_private,\n\t\t\t\t\tconst struct _sipe_xml *xn_userinfo);\nvoid sipe_ocs2005_apply_calendar_status(struct sipe_core_private *sipe_private,\n\t\t\t\t\tstruct sipe_buddy *sbuddy,\n\t\t\t\t\tconst char *status_id);\nvoid sipe_ocs2005_schedule_status_update(struct sipe_core_private *sipe_private,\n\t\t\t\t\t time_t calculate_from);\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-ocs2007.c",
    "content": "/**\n * @file sipe-ocs2007.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * OCS2007+ specific code\n *\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipmsg.h\"\n#include \"sip-csta.h\"\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-buddy.h\"\n#include \"sipe-cal.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-appshare.h\"\n#include \"sipe-ews.h\"\n#include \"sipe-media.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-ocs2007.h\"\n#include \"sipe-schedule.h\"\n#include \"sipe-status.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n\n/** MS-PRES publication */\nstruct sipe_publication {\n\tgchar *category;\n\tguint instance;\n\tguint container;\n\tguint version;\n\t/** for 'state' category */\n\tint availability;\n\t/** for 'state:calendarState' category */\n\tchar *cal_event_hash;\n\t/** for 'note' category */\n\tgchar *note;\n\t/** for 'calendarData' category; 300(Team) container */\n\tchar *working_hours_xml_str;\n\tchar *fb_start_str;\n\tchar *free_busy_base64;\n};\n\n/**\n * 2007-style Activity and Availability.\n *\n * [MS-PRES] 3.7.5.5\n *\n * Conversion of legacyInterop availability ranges and activity tokens into\n * SIPE activity tokens. The descriptions of availability ranges are defined at:\n *\n * http://msdn.microsoft.com/en-us/library/lync/dd941370%28v=office.13%29.aspx\n *\n * The values define the starting point of a range.\n */\n#define SIPE_OCS2007_LEGACY_AVAILIBILITY_AVAILABLE      3000\n#define SIPE_OCS2007_LEGACY_AVAILIBILITY_AVAILABLE_IDLE 4500\n#define SIPE_OCS2007_LEGACY_AVAILIBILITY_BUSY           6000\n#define SIPE_OCS2007_LEGACY_AVAILIBILITY_BUSYIDLE       7500\n#define SIPE_OCS2007_LEGACY_AVAILIBILITY_DND            9000 /* do not disturb */\n#define SIPE_OCS2007_LEGACY_AVAILIBILITY_BRB           12000 /* be right back */\n#define SIPE_OCS2007_LEGACY_AVAILIBILITY_AWAY          15000\n#define SIPE_OCS2007_LEGACY_AVAILIBILITY_OFFLINE       18000\n\nconst gchar *sipe_ocs2007_status_from_legacy_availability(guint availability,\n\t\t\t\t\t\t\t  const gchar *activity)\n{\n\tguint type;\n\n\tif (availability < SIPE_OCS2007_LEGACY_AVAILIBILITY_AVAILABLE) {\n\t\ttype = SIPE_ACTIVITY_OFFLINE;\n\t} else if (availability < SIPE_OCS2007_LEGACY_AVAILIBILITY_AVAILABLE_IDLE) {\n\t\ttype = SIPE_ACTIVITY_AVAILABLE;\n\t} else if (availability < SIPE_OCS2007_LEGACY_AVAILIBILITY_BUSY) {\n\t\ttype = SIPE_ACTIVITY_INACTIVE;\n\t} else if (availability < SIPE_OCS2007_LEGACY_AVAILIBILITY_BUSYIDLE) {\n\t\ttype = sipe_status_token_to_activity(activity);\n\t\tif ((type != SIPE_ACTIVITY_ON_PHONE) &&\n\t\t    (type != SIPE_ACTIVITY_IN_CONF))\n\t\t\ttype = SIPE_ACTIVITY_BUSY;\n\t} else if (availability < SIPE_OCS2007_LEGACY_AVAILIBILITY_DND) {\n\t\ttype = SIPE_ACTIVITY_BUSYIDLE;\n\t} else if (availability < SIPE_OCS2007_LEGACY_AVAILIBILITY_BRB) {\n\t\ttype = sipe_status_token_to_activity(activity);\n\t\tif (type != SIPE_ACTIVITY_IN_PRES) {\n\t\t\ttype = SIPE_ACTIVITY_DND;\n\t\t}\n\t} else if (availability < SIPE_OCS2007_LEGACY_AVAILIBILITY_AWAY) {\n\t\ttype = SIPE_ACTIVITY_BRB;\n\t} else if (availability < SIPE_OCS2007_LEGACY_AVAILIBILITY_OFFLINE) {\n\t\ttype = SIPE_ACTIVITY_AWAY;\n\t} else {\n\t\ttype = SIPE_ACTIVITY_OFFLINE;\n\t}\n\n\treturn sipe_status_activity_to_token(type);\n}\n\nconst gchar *sipe_ocs2007_legacy_activity_description(guint availability)\n{\n\tif ((availability >= SIPE_OCS2007_LEGACY_AVAILIBILITY_AVAILABLE_IDLE) &&\n\t    (availability <  SIPE_OCS2007_LEGACY_AVAILIBILITY_BUSY)) {\n\t\treturn(sipe_core_activity_description(SIPE_ACTIVITY_INACTIVE));\n\t} else if ((availability >= SIPE_OCS2007_LEGACY_AVAILIBILITY_BUSYIDLE) &&\n\t\t   (availability <  SIPE_OCS2007_LEGACY_AVAILIBILITY_DND)) {\n\t\treturn(sipe_core_activity_description(SIPE_ACTIVITY_BUSYIDLE));\n\t} else {\n\t\treturn(NULL);\n\t}\n}\n\n/**\n * @param sipe_status_id (in)\n * @param activity_token (out) [only sipe-ocs2005.c/send_presence_soap()\n *                              requests this token]\n */\n#define SIPE_OCS2007_AVAILABILITY_UNKNOWN     0\n#define SIPE_OCS2007_AVAILABILITY_ONLINE   3500\n#define SIPE_OCS2007_AVAILABILITY_BUSY     6500\n#define SIPE_OCS2007_AVAILABILITY_DND      9500 /* do not disturb */\n#define SIPE_OCS2007_AVAILABILITY_BRB     12500 /* be right back */\n#define SIPE_OCS2007_AVAILABILITY_AWAY    15500\n#define SIPE_OCS2007_AVAILABILITY_OFFLINE 18500\nguint sipe_ocs2007_availability_from_status(const gchar *sipe_status_id,\n\t\t\t\t\t    const gchar **activity_token)\n{\n\tguint availability;\n\tguint activity;\n\n\tif (sipe_strequal(sipe_status_id, sipe_status_activity_to_token(SIPE_ACTIVITY_AWAY))) {\n\t\tavailability = SIPE_OCS2007_AVAILABILITY_AWAY;\n\t\tactivity     = SIPE_ACTIVITY_AWAY;\n\t} else if (sipe_strequal(sipe_status_id, sipe_status_activity_to_token(SIPE_ACTIVITY_BRB))) {\n\t\tavailability = SIPE_OCS2007_AVAILABILITY_BRB;\n\t\tactivity     = SIPE_ACTIVITY_BRB;\n\t} else if (sipe_strequal(sipe_status_id, sipe_status_activity_to_token(SIPE_ACTIVITY_DND))) {\n\t\tavailability = SIPE_OCS2007_AVAILABILITY_DND;\n\t\tactivity     = SIPE_ACTIVITY_DND;\n\t} else if (sipe_strequal(sipe_status_id, sipe_status_activity_to_token(SIPE_ACTIVITY_BUSY))) {\n\t\tavailability = SIPE_OCS2007_AVAILABILITY_BUSY;\n\t\tactivity     = SIPE_ACTIVITY_BUSY;\n\t} else if (sipe_strequal(sipe_status_id, sipe_status_activity_to_token(SIPE_ACTIVITY_AVAILABLE))) {\n\t\tavailability = SIPE_OCS2007_AVAILABILITY_ONLINE;\n\t\tactivity     = SIPE_ACTIVITY_ONLINE;\n\t} else if (sipe_strequal(sipe_status_id, sipe_status_activity_to_token(SIPE_ACTIVITY_UNSET))) {\n\t\tavailability = SIPE_OCS2007_AVAILABILITY_UNKNOWN;\n\t\tactivity     = SIPE_ACTIVITY_UNSET;\n\t} else {\n\t\t/* Offline or invisible */\n\t\tavailability = SIPE_OCS2007_AVAILABILITY_OFFLINE;\n\t\tactivity     = SIPE_ACTIVITY_OFFLINE;\n\t}\n\n\tif (activity_token) {\n\t\t*activity_token = sipe_status_activity_to_token(activity);\n\t}\n\n\treturn(availability);\n}\n\ngboolean sipe_ocs2007_status_is_busy(const gchar *status_id)\n{\n\treturn(SIPE_OCS2007_AVAILABILITY_BUSY >=\n\t       sipe_ocs2007_availability_from_status(status_id, NULL));\n\n}\n\ngboolean sipe_ocs2007_availability_is_away(guint availability)\n{\n\treturn(availability >= SIPE_OCS2007_LEGACY_AVAILIBILITY_AWAY);\n}\n\nstatic void send_presence_publish(struct sipe_core_private *sipe_private,\n\t\t\t\t  const char *publications);\n\nstatic void free_publication(struct sipe_publication *publication)\n{\n\tg_free(publication->category);\n\tg_free(publication->cal_event_hash);\n\tg_free(publication->note);\n\n\tg_free(publication->working_hours_xml_str);\n\tg_free(publication->fb_start_str);\n\tg_free(publication->free_busy_base64);\n\n\tg_free(publication);\n}\n\nstruct hash_table_delete_payload {\n\tGHashTable *hash_table;\n\tguint container;\n};\n\nstatic void sipe_remove_category_container_publications_cb(const gchar *name,\n\t\t\t\t\t\t\t   struct sipe_publication *publication,\n\t\t\t\t\t\t\t   struct hash_table_delete_payload *payload)\n{\n\tif (publication->container == payload->container) {\n\t\tg_hash_table_remove(payload->hash_table, name);\n\t}\n}\n\nstatic void sipe_remove_category_container_publications(GHashTable *our_publications,\n\t\t\t\t\t\t\tconst gchar *category,\n\t\t\t\t\t\t\tguint container)\n{\n\tstruct hash_table_delete_payload payload;\n\tpayload.hash_table = g_hash_table_lookup(our_publications, category);\n\n\tif (!payload.hash_table) return;\n\n\tpayload.container = container;\n\tg_hash_table_foreach(payload.hash_table,\n\t\t\t     (GHFunc)sipe_remove_category_container_publications_cb,\n\t\t\t     &payload);\n}\n\n/** MS-PRES container */\nstruct sipe_container {\n\tguint id;\n\tguint version;\n\tGSList *members;\n};\n\n/** MS-PRES container member */\nstruct sipe_container_member {\n\t/** user, domain, sameEnterprise, federated, publicCloud; everyone */\n\tgchar *type;\n\tgchar *value;\n};\n\nstatic const guint containers[] = {32000, 400, 300, 200, 100};\n#define CONTAINERS_LEN (sizeof(containers) / sizeof(guint))\n\nstatic void free_container_member(struct sipe_container_member *member)\n{\n\tif (!member) return;\n\n\tg_free(member->type);\n\tg_free(member->value);\n\tg_free(member);\n}\n\nstatic void sipe_ocs2007_free_container(struct sipe_container *container)\n{\n\tGSList *entry;\n\n\tif (!container) return;\n\n\tentry = container->members;\n\twhile (entry) {\n\t\tvoid *data = entry->data;\n\t\tentry = g_slist_remove(entry, data);\n\t\tfree_container_member((struct sipe_container_member *)data);\n\t}\n\tg_free(container);\n}\n\nvoid sipe_core_buddy_menu_free(struct sipe_core_public *sipe_public)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tsipe_utils_slist_free_full(sipe_private->blist_menu_containers,\n\t\t\t\t   (GDestroyNotify) sipe_ocs2007_free_container);\n\tsipe_private->blist_menu_containers = NULL;\n}\n\nstatic void blist_menu_remember_container(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  struct sipe_container *container)\n{\n\tsipe_private->blist_menu_containers = g_slist_prepend(sipe_private->blist_menu_containers,\n\t\t\t\t\t\t\t      container);\n}\n\nstatic struct sipe_container *create_container(guint index,\n\t\t\t\t\t       const gchar *member_type,\n\t\t\t\t\t       const gchar *member_value,\n\t\t\t\t\t       gboolean is_group)\n{\n\tstruct sipe_container *container = g_new0(struct sipe_container, 1);\n\tstruct sipe_container_member *member = g_new0(struct sipe_container_member, 1);\n\n\tcontainer->id = is_group ? (guint) -1 : containers[index];\n\tcontainer->members = g_slist_append(container->members, member);\n\tmember->type = g_strdup(member_type);\n\tmember->value = g_strdup(member_value);\n\n\treturn(container);\n}\n\nvoid sipe_ocs2007_free(struct sipe_core_private *sipe_private)\n{\n\tsipe_utils_slist_free_full(sipe_private->containers,\n\t\t\t\t   (GDestroyNotify) sipe_ocs2007_free_container);\n}\n\n/**\n * Finds locally stored MS-PRES container member\n */\nstatic struct sipe_container_member *\nsipe_find_container_member(struct sipe_container *container,\n\t\t\t   const gchar *type,\n\t\t\t   const gchar *value)\n{\n\tstruct sipe_container_member *member;\n\tGSList *entry;\n\n\tif (container == NULL || type == NULL) {\n\t\treturn NULL;\n\t}\n\n\tentry = container->members;\n\twhile (entry) {\n\t\tmember = entry->data;\n\t\tif (sipe_strcase_equal(member->type, type) &&\n\t\t    sipe_strcase_equal(member->value, value))\n\t\t{\n\t\t\treturn member;\n\t\t}\n\t\tentry = entry->next;\n\t}\n\treturn NULL;\n}\n\n/**\n * Finds locally stored MS-PRES container by id\n */\nstatic struct sipe_container *sipe_find_container(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t  guint id)\n{\n\tGSList *entry = sipe_private->containers;\n\twhile (entry) {\n\t\tstruct sipe_container *container = entry->data;\n\t\tif (id == container->id) {\n\t\t\treturn container;\n\t\t}\n\t\tentry = entry->next;\n\t}\n\treturn NULL;\n}\n\nstatic int sipe_find_member_access_level(struct sipe_core_private *sipe_private,\n\t\t\t\t\t const gchar *type,\n\t\t\t\t\t const gchar *value)\n{\n\tunsigned int i = 0;\n\tconst gchar *value_mod = value;\n\n\tif (!type) return -1;\n\n\tif (sipe_strequal(\"user\", type)) {\n\t\tvalue_mod = sipe_get_no_sip_uri(value);\n\t}\n\n\tfor (i = 0; i < CONTAINERS_LEN; i++) {\n\t\tstruct sipe_container_member *member;\n\t\tstruct sipe_container *container = sipe_find_container(sipe_private, containers[i]);\n\t\tif (!container) continue;\n\n\t\tmember = sipe_find_container_member(container, type, value_mod);\n\t\tif (member) return containers[i];\n\t}\n\n\treturn -1;\n}\n\n/**\n * Returns pointer to domain part in provided Email URL\n *\n * @param email an email URL. Example: first.last@hq.company.com\n * @return pointer to domain part of email URL. Coresponding example: hq.company.com\n *\n * Doesn't allocate memory\n */\nstatic const gchar *sipe_get_domain(const gchar *email)\n{\n\tgchar *tmp;\n\n\tif (!email) return NULL;\n\n\ttmp = strstr(email, \"@\");\n\n\tif (tmp && ((tmp+1) < (email + strlen(email)))) {\n\t\treturn tmp+1;\n\t} else {\n\t\treturn NULL;\n\t}\n}\n\n/* @TODO: replace with binary search for faster access? */\n/** source: http://support.microsoft.com/kb/897567 */\nstatic const gchar * const public_domains[] = {\n\t\"aol.com\", \"icq.com\", \"love.com\", \"mac.com\", \"br.live.com\",\n\t\"hotmail.co.il\", \"hotmail.co.jp\", \"hotmail.co.th\", \"hotmail.co.uk\",\n\t\"hotmail.com\", \"hotmail.com.ar\", \"hotmail.com.tr\", \"hotmail.es\",\n\t\"hotmail.de\", \"hotmail.fr\", \"hotmail.it\", \"live.at\", \"live.be\",\n\t\"live.ca\", \"live.cl\", \"live.cn\", \"live.co.in\", \"live.co.kr\",\n\t\"live.co.uk\", \"live.co.za\", \"live.com\", \"live.com.ar\", \"live.com.au\",\n\t\"live.com.co\", \"live.com.mx\", \"live.com.my\", \"live.com.pe\",\n\t\"live.com.ph\", \"live.com.pk\", \"live.com.pt\", \"live.com.sg\",\n\t\"live.com.ve\", \"live.de\", \"live.dk\", \"live.fr\", \"live.hk\", \"live.ie\",\n\t\"live.in\", \"live.it\", \"live.jp\", \"live.nl\", \"live.no\", \"live.ph\",\n\t\"live.ru\", \"live.se\", \"livemail.com.br\", \"livemail.tw\",\n\t\"messengeruser.com\", \"msn.com\", \"passport.com\", \"sympatico.ca\",\n\t\"tw.live.com\", \"webtv.net\", \"windowslive.com\", \"windowslive.es\",\n\t\"yahoo.com\",\n\tNULL};\n\nstatic gboolean sipe_is_public_domain(const gchar *domain)\n{\n\tint i = 0;\n\twhile (public_domains[i]) {\n\t\tif (sipe_strcase_equal(public_domains[i], domain)) {\n\t\t\treturn TRUE;\n\t\t}\n\t\ti++;\n\t}\n\treturn FALSE;\n}\n\n/**\n * Access Levels\n * 32000 - Blocked\n * 400   - Personal\n * 300   - Team\n * 200   - Company\n * 100   - Public\n */\nconst gchar *sipe_ocs2007_access_level_name(guint id)\n{\n\tswitch (id) {\n\t\tcase 32000: return _(\"Blocked\");\n\t\tcase 400:   return _(\"Personal\");\n\t\tcase 300:   return _(\"Team\");\n\t\tcase 200:   return _(\"Company\");\n\t\tcase 100:   return _(\"Public\");\n\t}\n\treturn _(\"Unknown\");\n}\n\n/** Member type: user, domain, sameEnterprise, federated, publicCloud; everyone */\nint sipe_ocs2007_find_access_level(struct sipe_core_private *sipe_private,\n\t\t\t\t   const gchar *type,\n\t\t\t\t   const gchar *value,\n\t\t\t\t   gboolean *is_group_access)\n{\n\tint container_id = -1;\n\n\tif (sipe_strequal(\"user\", type)) {\n\t\tconst char *domain;\n\t\tconst char *no_sip_uri = sipe_get_no_sip_uri(value);\n\n\t\tcontainer_id = sipe_find_member_access_level(sipe_private, \"user\", no_sip_uri);\n\t\tif (container_id >= 0) {\n\t\t\tif (is_group_access) *is_group_access = FALSE;\n\t\t\treturn container_id;\n\t\t}\n\n\t\tdomain = sipe_get_domain(no_sip_uri);\n\t\tcontainer_id = sipe_find_member_access_level(sipe_private, \"domain\", domain);\n\t\tif (container_id >= 0)  {\n\t\t\tif (is_group_access) *is_group_access = TRUE;\n\t\t\treturn container_id;\n\t\t}\n\n\t\tcontainer_id = sipe_find_member_access_level(sipe_private, \"sameEnterprise\", NULL);\n\t\tif ((container_id >= 0) && sipe_strcase_equal(sipe_private->public.sip_domain, domain)) {\n\t\t\tif (is_group_access) *is_group_access = TRUE;\n\t\t\treturn container_id;\n\t\t}\n\n\t\tcontainer_id = sipe_find_member_access_level(sipe_private, \"publicCloud\", NULL);\n\t\tif ((container_id >= 0) && sipe_is_public_domain(domain)) {\n\t\t\tif (is_group_access) *is_group_access = TRUE;\n\t\t\treturn container_id;\n\t\t}\n\n\t\tcontainer_id = sipe_find_member_access_level(sipe_private, \"everyone\", NULL);\n\t\tif ((container_id >= 0)) {\n\t\t\tif (is_group_access) *is_group_access = TRUE;\n\t\t\treturn container_id;\n\t\t}\n\t} else {\n\t\tcontainer_id = sipe_find_member_access_level(sipe_private, type, value);\n\t\tif (is_group_access) *is_group_access = FALSE;\n\t}\n\n\treturn container_id;\n}\n\nstatic GSList *get_access_domains(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_container *container;\n\tstruct sipe_container_member *member;\n\tGSList *entry;\n\tGSList *entry2;\n\tGSList *res = NULL;\n\n\tentry = sipe_private->containers;\n\twhile (entry) {\n\t\tcontainer = entry->data;\n\n\t\tentry2 = container->members;\n\t\twhile (entry2) {\n\t\t\tmember = entry2->data;\n\t\t\tif (sipe_strcase_equal(member->type, \"domain\"))\n\t\t\t{\n\t\t\t\tres = sipe_utils_slist_insert_unique_sorted(res,\n\t\t\t\t\t\t\t\t\t    g_strdup(member->value),\n\t\t\t\t\t\t\t\t\t    (GCompareFunc)g_ascii_strcasecmp,\n\t\t\t\t\t\t\t\t\t    g_free);\n\t\t\t}\n\t\t\tentry2 = entry2->next;\n\t\t}\n\t\tentry = entry->next;\n\t}\n\treturn res;\n}\n\nstatic void sipe_send_container_members_prepare(const guint container_id,\n\t\t\t\t\t\tconst guint container_version,\n\t\t\t\t\t\tconst gchar *action,\n\t\t\t\t\t\tconst gchar *type,\n\t\t\t\t\t\tconst gchar *value,\n\t\t\t\t\t\tchar **container_xmls)\n{\n\tgchar *value_str = value ? g_strdup_printf(\" value=\\\"%s\\\"\", value) : g_strdup(\"\");\n\tgchar *body;\n\n\tif (!container_xmls) return;\n\n\tbody = g_strdup_printf(\n\t\t\"<container id=\\\"%d\\\" version=\\\"%d\\\"><member action=\\\"%s\\\" type=\\\"%s\\\"%s/></container>\",\n\t\tcontainer_id,\n\t\tcontainer_version,\n\t\taction,\n\t\ttype,\n\t\tvalue_str);\n\tg_free(value_str);\n\n\tif ((*container_xmls) == NULL) {\n\t\t*container_xmls = body;\n\t} else {\n\t\tchar *tmp = *container_xmls;\n\n\t\t*container_xmls = g_strconcat(*container_xmls, body, NULL);\n\t\tg_free(tmp);\n\t\tg_free(body);\n\t}\n}\n\nstatic void sipe_send_set_container_members(struct sipe_core_private *sipe_private,\n\t\t\t\t\t    char *container_xmls)\n{\n\tgchar *self;\n\tgchar *contact;\n\tgchar *hdr;\n\tgchar *body;\n\n\tif (!container_xmls) return;\n\n\tself = sip_uri_self(sipe_private);\n\tbody = g_strdup_printf(\n\t\t\"<setContainerMembers xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/container-management\\\">\"\n\t\t\"%s\"\n\t\t\"</setContainerMembers>\",\n\t\tcontainer_xmls);\n\n\tcontact = get_contact(sipe_private);\n\thdr = g_strdup_printf(\"Contact: %s\\r\\n\"\n\t\t\t      \"Content-Type: application/msrtc-setcontainermembers+xml\\r\\n\", contact);\n\tg_free(contact);\n\n\tsip_transport_service(sipe_private,\n\t\t\t      self,\n\t\t\t      hdr,\n\t\t\t      body,\n\t\t\t      NULL);\n\n\tg_free(hdr);\n\tg_free(body);\n\tg_free(self);\n}\n\n/**\n  * @param container_id\ta new access level. If -1 then current access level\n  * \t\t\tis just removed (I.e. the member is removed from all containers).\n  * @param type\t\ta type of member. E.g. \"user\", \"sameEnterprise\", etc.\n  * @param value\ta value for member. E.g. SIP URI for \"user\" member type.\n  */\nvoid sipe_ocs2007_change_access_level(struct sipe_core_private *sipe_private,\n\t\t\t\t      const int container_id,\n\t\t\t\t      const gchar *type,\n\t\t\t\t      const gchar *value)\n{\n\tunsigned int i;\n\tint current_container_id = -1;\n\tchar *container_xmls = NULL;\n\n\t/* for each container: find/delete */\n\tfor (i = 0; i < CONTAINERS_LEN; i++) {\n\t\tstruct sipe_container_member *member;\n\t\tstruct sipe_container *container = sipe_find_container(sipe_private, containers[i]);\n\n\t\tif (!container) continue;\n\n\t\tmember = sipe_find_container_member(container, type, value);\n\t\tif (member) {\n\t\t\tcurrent_container_id = containers[i];\n\t\t\t/* delete/publish current access level */\n\t\t\tif (container_id < 0 || container_id != current_container_id) {\n\t\t\t\tsipe_send_container_members_prepare(current_container_id, container->version, \"remove\", type, value, &container_xmls);\n\t\t\t\t/* remove member from our cache, to be able to recalculate AL below */\n\t\t\t\tcontainer->members = g_slist_remove(container->members, member);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* recalculate AL below */\n\tcurrent_container_id = sipe_ocs2007_find_access_level(sipe_private, type, value, NULL);\n\n\t/* assign/publish new access level */\n\tif (container_id != current_container_id && container_id >= 0) {\n\t\tstruct sipe_container *container = sipe_find_container(sipe_private, container_id);\n\t\tguint version = container ? container->version : 0;\n\n\t\tsipe_send_container_members_prepare(container_id, version, \"add\", type, value, &container_xmls);\n\t}\n\n\tif (container_xmls) {\n\t\tsipe_send_set_container_members(sipe_private, container_xmls);\n\t}\n\tg_free(container_xmls);\n}\n\nvoid sipe_core_change_access_level_from_container(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t  gpointer parameter)\n{\n\tstruct sipe_container *container = parameter;\n\tstruct sipe_container_member *member;\n\n\tif (!container || !container->members) return;\n\n\tmember = ((struct sipe_container_member *)container->members->data);\n\n\tif (!member->type) return;\n\n\tSIPE_DEBUG_INFO(\"sipe_ocs2007_change_access_level_from_container: container->id=%d, member->type=%s, member->value=%s\",\n\t\t\tcontainer->id, member->type, member->value ? member->value : \"\");\n\n\tsipe_ocs2007_change_access_level(SIPE_CORE_PRIVATE,\n\t\t\t\t\t container->id,\n\t\t\t\t\t member->type,\n\t\t\t\t\t member->value);\n\n}\n\nvoid sipe_core_change_access_level_for_domain(struct sipe_core_public *sipe_public,\n\t\t\t\t\t      const gchar *domain,\n\t\t\t\t\t      guint index)\n{\n\t/* move Blocked first */\n\tguint i            = (index == 4) ? 0 : index + 1;\n\tguint container_id = containers[i];\n\n\tSIPE_DEBUG_INFO(\"sipe_core_change_access_level_from_id: domain=%s, container_id=(%d)%d\",\n\t\t\tdomain ? domain : \"\", index, container_id);\n\n\tsipe_ocs2007_change_access_level(SIPE_CORE_PRIVATE,\n\t\t\t\t\t container_id,\n\t\t\t\t\t \"domain\",\n\t\t\t\t\t domain);\n}\n\n/**\n * Schedules process of self status publish\n * based on own calendar information.\n * Should be scheduled to the beginning of every\n * 15 min interval, like:\n * 13:00, 13:15, 13:30, 13:45, etc.\n *\n */\nstatic void schedule_publish_update(struct sipe_core_private *sipe_private,\n\t\t\t\t    time_t calculate_from)\n{\n\tint interval = 5*60;\n\t/** start of the beginning of closest 5 min interval. */\n\ttime_t next_start = ((time_t)((int)((int)calculate_from)/interval + 1)*interval);\n\n\tSIPE_DEBUG_INFO(\"sipe_sched_calendar_status_self_publish: calculate_from time: %s\",\n\t\t\tsipe_utils_time_to_debug_str(localtime(&calculate_from)));\n\tSIPE_DEBUG_INFO(\"sipe_sched_calendar_status_self_publish: next start time    : %s\",\n\t\t\tsipe_utils_time_to_debug_str(localtime(&next_start)));\n\n\tsipe_schedule_seconds(sipe_private,\n\t\t\t      \"<+2007-cal-status>\",\n\t\t\t      NULL,\n\t\t\t      next_start - time(NULL),\n\t\t\t      sipe_ocs2007_presence_publish,\n\t\t\t      NULL);\n}\n\n/**\n * An availability XML entry for SIPE_PUB_XML_STATE_CALENDAR\n * @param availability\t\t(%d) Ex.: 6500\n */\n#define SIPE_PUB_XML_STATE_CALENDAR_AVAIL \\\n\"<availability>%d</availability>\"\n/**\n * An activity XML entry for SIPE_PUB_XML_STATE_CALENDAR\n * @param token\t\t\t(%s) Ex.: in-a-meeting\n * @param minAvailability_attr\t(%s) Ex.: minAvailability=\"6500\"\n * @param maxAvailability_attr\t(%s) Ex.: maxAvailability=\"8999\" or none\n */\n#define SIPE_PUB_XML_STATE_CALENDAR_ACTIVITY \\\n\"<activity token=\\\"%s\\\" %s %s></activity>\"\n/**\n * Publishes 'calendarState' category.\n * @param instance\t\t(%u) Ex.: 1339299275\n * @param version\t\t(%u) Ex.: 1\n * @param uri\t\t\t(%s) Ex.: john@contoso.com\n * @param start_time_str\t(%s) Ex.: 2008-01-11T19:00:00Z\n * @param availability\t\t(%s) XML string as SIPE_PUB_XML_STATE_CALENDAR_AVAIL\n * @param activity\t\t(%s) XML string as SIPE_PUB_XML_STATE_CALENDAR_ACTIVITY\n * @param meeting_subject\t(%s) Ex.: Customer Meeting\n * @param meeting_location\t(%s) Ex.: Conf Room 100\n *\n * @param instance\t\t(%u) Ex.: 1339299275\n * @param version\t\t(%u) Ex.: 1\n * @param uri\t\t\t(%s) Ex.: john@contoso.com\n * @param start_time_str\t(%s) Ex.: 2008-01-11T19:00:00Z\n * @param availability\t\t(%s) XML string as SIPE_PUB_XML_STATE_CALENDAR_AVAIL\n * @param activity\t\t(%s) XML string as SIPE_PUB_XML_STATE_CALENDAR_ACTIVITY\n * @param meeting_subject\t(%s) Ex.: Customer Meeting\n * @param meeting_location\t(%s) Ex.: Conf Room 100\n */\n#define SIPE_PUB_XML_STATE_CALENDAR \\\n\t\"<publication categoryName=\\\"state\\\" instance=\\\"%u\\\" container=\\\"2\\\" version=\\\"%u\\\" expireType=\\\"endpoint\\\">\"\\\n\t\t\"<state xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/state\\\" manual=\\\"false\\\" uri=\\\"%s\\\" startTime=\\\"%s\\\" xmlns:xsi=\\\"http://www.w3.org/2001/XMLSchema-instance\\\" xsi:type=\\\"calendarState\\\">\"\\\n\t\t\t\"%s\"\\\n\t\t\t\"%s\"\\\n\t\t\t\"<endpointLocation/>\"\\\n\t\t\t\"<meetingSubject>%s</meetingSubject>\"\\\n\t\t\t\"<meetingLocation>%s</meetingLocation>\"\\\n\t\t\"</state>\"\\\n\t\"</publication>\"\\\n\t\"<publication categoryName=\\\"state\\\" instance=\\\"%u\\\" container=\\\"3\\\" version=\\\"%u\\\" expireType=\\\"endpoint\\\">\"\\\n\t\t\"<state xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/state\\\" manual=\\\"false\\\" uri=\\\"%s\\\" startTime=\\\"%s\\\" xmlns:xsi=\\\"http://www.w3.org/2001/XMLSchema-instance\\\" xsi:type=\\\"calendarState\\\">\"\\\n\t\t\t\"%s\"\\\n\t\t\t\"%s\"\\\n\t\t\t\"<endpointLocation/>\"\\\n\t\t\t\"<meetingSubject>%s</meetingSubject>\"\\\n\t\t\t\"<meetingLocation>%s</meetingLocation>\"\\\n\t\t\"</state>\"\\\n\t\"</publication>\"\n/**\n * Publishes to clear 'calendarState' and 'phoneState' category\n * @param instance\t\t(%u) Ex.: 1251210982\n * @param version\t\t(%u) Ex.: 1\n */\n#define SIPE_PUB_XML_STATE_CALENDAR_PHONE_CLEAR \\\n\t\"<publication categoryName=\\\"state\\\" instance=\\\"%u\\\" container=\\\"2\\\" version=\\\"%u\\\" expireType=\\\"endpoint\\\" expires=\\\"0\\\"/>\"\\\n\t\"<publication categoryName=\\\"state\\\" instance=\\\"%u\\\" container=\\\"3\\\" version=\\\"%u\\\" expireType=\\\"endpoint\\\" expires=\\\"0\\\"/>\"\n\n/**\n * Publishes to clear any category\n * @param category_name\t\t(%s) Ex.: state\n * @param instance\t\t(%u) Ex.: 536870912\n * @param container\t\t(%u) Ex.: 3\n * @param version\t\t(%u) Ex.: 1\n * @param expireType\t\t(%s) Ex.: static\n */\n#define SIPE_PUB_XML_PUBLICATION_CLEAR \\\n\t\"<publication categoryName=\\\"%s\\\" instance=\\\"%u\\\" container=\\\"%u\\\" version=\\\"%u\\\" expireType=\\\"%s\\\" expires=\\\"0\\\"/>\"\n\n/**\n * Publishes 'note' category.\n * @param instance\t\t(%u) Ex.: 2135971629; 0 for personal\n * @param container\t\t(%u) Ex.: 200\n * @param version\t\t(%u) Ex.: 2\n * @param type\t\t\t(%s) Ex.: personal or OOF\n * @param startTime_attr\t(%s) Ex.: startTime=\"2008-01-11T19:00:00Z\"\n * @param endTime_attr\t\t(%s) Ex.: endTime=\"2008-01-15T19:00:00Z\"\n * @param body\t\t\t(%s) Ex.: In the office\n */\n#define SIPE_PUB_XML_NOTE \\\n\t\"<publication categoryName=\\\"note\\\" instance=\\\"%u\\\" container=\\\"%u\\\" version=\\\"%d\\\" expireType=\\\"static\\\">\"\\\n\t\t\"<note xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/note\\\">\"\\\n\t\t\t\"<body type=\\\"%s\\\" uri=\\\"\\\"%s%s>%s</body>\"\\\n\t\t\"</note>\"\\\n\t\"</publication>\"\n/**\n * Publishes 'phoneState' category.\n * @param instance\t\t(%u) Ex.: 1339299275\n * @param version\t\t(%u) Ex.: 1\n * @param availability\t\t(%u) Ex.: 6500\n * @param token\t\t\t(%s) Ex.: on-the-phone\n * @param minAvailability\t(%u) generally same as availability\n *\n * @param instance\t\t(%u) Ex.: 1339299275\n * @param version\t\t(%u) Ex.: 1\n * @param availability          (%u) Ex.: 6500\n * @param token\t\t\t(%s) Ex.: on-the-phone\n * @param minAvailability\t(%u) generally same as availability\n */\n#define SIPE_PUB_XML_STATE_PHONE \\\n\t\"<publication categoryName=\\\"state\\\" instance=\\\"%u\\\" container=\\\"2\\\" version=\\\"%u\\\" expireType=\\\"endpoint\\\">\"\\\n\t\t\"<state xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/state\\\" manual=\\\"false\\\" xmlns:xsi=\\\"http://www.w3.org/2001/XMLSchema-instance\\\" xsi:type=\\\"phoneState\\\">\"\\\n\t\t\t\"<availability>%u</availability>\"\\\n\t\t\t\"<activity token=\\\"%s\\\" minAvailability=\\\"%u\\\" maxAvailability=\\\"%u\\\"/>\"\\\n\t\t\"</state>\"\\\n\t\"</publication>\"\\\n\t\"<publication categoryName=\\\"state\\\" instance=\\\"%u\\\" container=\\\"3\\\" version=\\\"%u\\\" expireType=\\\"endpoint\\\">\"\\\n\t\t\"<state xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/state\\\" manual=\\\"false\\\" xmlns:xsi=\\\"http://www.w3.org/2001/XMLSchema-instance\\\" xsi:type=\\\"phoneState\\\">\"\\\n\t\t\t\"<availability>%u</availability>\"\\\n\t\t\t\"<activity token=\\\"%s\\\" minAvailability=\\\"%u\\\" maxAvailability=\\\"%u\\\"/>\"\\\n\t\t\"</state>\"\\\n\t\"</publication>\"\n\n/**\n * Only Busy and OOF calendar event are published.\n * Different instances are used for that.\n *\n * Must be g_free'd after use.\n */\nstatic gchar *sipe_publish_get_category_state_calendar(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t       struct sipe_cal_event *event,\n\t\t\t\t\t\t       const char *uri,\n\t\t\t\t\t\t       int cal_satus)\n{\n\tgchar *start_time_str;\n\tint availability = 0;\n\tgchar *res;\n\tgchar *tmp = NULL;\n\tguint instance = (cal_satus == SIPE_CAL_OOF) ?\n\t\tsipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_CALENDAR_OOF) :\n\t\tsipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_CALENDAR);\n\n\t/* key is <category><instance><container> */\n\tgchar *key_2 = g_strdup_printf(\"<%s><%u><%u>\", \"state\", instance, 2);\n\tgchar *key_3 = g_strdup_printf(\"<%s><%u><%u>\", \"state\", instance, 3);\n\tgpointer state = g_hash_table_lookup(sipe_private->our_publications, \"state\");\n\tstruct sipe_publication *publication_2 = state ? g_hash_table_lookup(state, key_2) : NULL;\n\tstruct sipe_publication *publication_3 = state ? g_hash_table_lookup(state, key_3) : NULL;\n\n\tg_free(key_2);\n\tg_free(key_3);\n\n\tif (!publication_3 && !event) { /* was nothing, have nothing, exiting */\n\t\tSIPE_DEBUG_INFO(\"sipe_publish_get_category_state_calendar: \"\n\t\t\t\t\"Exiting as no publication and no event for cal_satus:%d\", cal_satus);\n\t\treturn NULL;\n\t}\n\n\tif (event &&\n\t    publication_3 &&\n\t    (publication_3->availability == availability) &&\n\t    sipe_strequal(publication_3->cal_event_hash, (tmp = sipe_cal_event_hash(event))))\n\t{\n\t\tg_free(tmp);\n\t\tSIPE_DEBUG_INFO(\"sipe_publish_get_category_state_calendar: \"\n\t\t\t\t\"cal state has NOT changed for cal_satus:%d. Exiting.\", cal_satus);\n\t\treturn NULL; /* nothing to update */\n\t}\n\tg_free(tmp);\n\n\tif (event &&\n\t    (event->cal_status == SIPE_CAL_BUSY ||\n\t     event->cal_status == SIPE_CAL_OOF))\n\t{\n\t\tgchar *availability_xml_str = NULL;\n\t\tgchar *activity_xml_str = NULL;\n\t\tgchar *escaped_subject  = event->subject  ? g_markup_escape_text(event->subject,  -1) : NULL;\n\t\tgchar *escaped_location = event->location ? g_markup_escape_text(event->location, -1) : NULL;\n\n\t\tif (event->cal_status == SIPE_CAL_BUSY) {\n\t\t\tavailability_xml_str = g_strdup_printf(SIPE_PUB_XML_STATE_CALENDAR_AVAIL,\n\t\t\t\t\t\t\t       SIPE_OCS2007_AVAILABILITY_BUSY);\n\t\t}\n\n\t\tif (event->cal_status == SIPE_CAL_BUSY && event->is_meeting) {\n\t\t\tactivity_xml_str = g_strdup_printf(SIPE_PUB_XML_STATE_CALENDAR_ACTIVITY,\n\t\t\t\t\t\t\t   sipe_status_activity_to_token(SIPE_ACTIVITY_IN_MEETING),\n\t\t\t\t\t\t\t   \"minAvailability=\\\"6500\\\"\",\n\t\t\t\t\t\t\t   \"maxAvailability=\\\"8999\\\"\");\n\t\t} else if (event->cal_status == SIPE_CAL_OOF) {\n\t\t\tactivity_xml_str = g_strdup_printf(SIPE_PUB_XML_STATE_CALENDAR_ACTIVITY,\n\t\t\t\t\t\t\t   sipe_status_activity_to_token(SIPE_ACTIVITY_OOF),\n\t\t\t\t\t\t\t   \"minAvailability=\\\"12000\\\"\",\n\t\t\t\t\t\t\t   \"\");\n\t\t}\n\t\tstart_time_str = sipe_utils_time_to_str(event->start_time);\n\n\t\tres = g_strdup_printf(SIPE_PUB_XML_STATE_CALENDAR,\n\t\t\t\t\tinstance,\n\t\t\t\t\tpublication_2 ? publication_2->version : 0,\n\t\t\t\t\turi,\n\t\t\t\t\tstart_time_str,\n\t\t\t\t\tavailability_xml_str ? availability_xml_str : \"\",\n\t\t\t\t\tactivity_xml_str ? activity_xml_str : \"\",\n\t\t\t\t\tescaped_subject  ? escaped_subject  : \"\",\n\t\t\t\t\tescaped_location ? escaped_location : \"\",\n\n\t\t\t\t\tinstance,\n\t\t\t\t\tpublication_3 ? publication_3->version : 0,\n\t\t\t\t\turi,\n\t\t\t\t\tstart_time_str,\n\t\t\t\t\tavailability_xml_str ? availability_xml_str : \"\",\n\t\t\t\t\tactivity_xml_str ? activity_xml_str : \"\",\n\t\t\t\t\tescaped_subject  ? escaped_subject  : \"\",\n\t\t\t\t\tescaped_location ? escaped_location : \"\"\n\t\t\t\t\t);\n\t\tg_free(escaped_location);\n\t\tg_free(escaped_subject);\n\t\tg_free(start_time_str);\n\t\tg_free(availability_xml_str);\n\t\tg_free(activity_xml_str);\n\n\t}\n\telse /* including !event, SIPE_CAL_FREE, SIPE_CAL_TENTATIVE */\n\t{\n\t\tres = g_strdup_printf(SIPE_PUB_XML_STATE_CALENDAR_PHONE_CLEAR,\n\t\t\t\t\tinstance,\n\t\t\t\t\tpublication_2 ? publication_2->version : 0,\n\n\t\t\t\t\tinstance,\n\t\t\t\t\tpublication_3 ? publication_3->version : 0\n\t\t\t\t\t);\n\t}\n\n\treturn res;\n}\n\n/**\n * Returns 'note' XML part for publication.\n * Must be g_free'd after use.\n *\n * Protocol format for Note is plain text.\n *\n * @param note a note in Sipe internal HTML format\n * @param note_type either personal or OOF\n */\nstatic gchar *sipe_publish_get_category_note(struct sipe_core_private *sipe_private,\n\t\t\t\t\t     const char *note, /* html */\n\t\t\t\t\t     const char *note_type,\n\t\t\t\t\t     time_t note_start,\n\t\t\t\t\t     time_t note_end,\n\t\t\t\t\t     gboolean force_publish)\n{\n\tguint instance = sipe_strequal(\"OOF\", note_type) ? sipe_get_pub_instance(sipe_private, SIPE_PUB_NOTE_OOF) : 0;\n\t/* key is <category><instance><container> */\n\tgchar *key_note_200 = g_strdup_printf(\"<%s><%u><%u>\", \"note\", instance, 200);\n\tgchar *key_note_300 = g_strdup_printf(\"<%s><%u><%u>\", \"note\", instance, 300);\n\tgchar *key_note_400 = g_strdup_printf(\"<%s><%u><%u>\", \"note\", instance, 400);\n\n\tgpointer notes = g_hash_table_lookup(sipe_private->our_publications, \"note\");\n\tstruct sipe_publication *publication_note_200 = notes ? g_hash_table_lookup(notes, key_note_200) : NULL;\n\tstruct sipe_publication *publication_note_300 = notes ? g_hash_table_lookup(notes, key_note_300) : NULL;\n\tstruct sipe_publication *publication_note_400 = notes ? g_hash_table_lookup(notes, key_note_400) : NULL;\n\n\tchar *tmp = note ? sipe_backend_markup_strip_html(note) : NULL;\n\tchar *n1 = tmp ? g_markup_escape_text(tmp, -1) : NULL;\n\tconst char *n2 = publication_note_200 ? publication_note_200->note : NULL;\n\tchar *res, *tmp1, *tmp2, *tmp3;\n\tchar *start_time_attr;\n\tchar *end_time_attr;\n\n\tg_free(tmp);\n\ttmp = NULL;\n\tg_free(key_note_200);\n\tg_free(key_note_300);\n\tg_free(key_note_400);\n\n\t/* we even need to republish empty note */\n\tif (!force_publish && sipe_strequal(n1, n2))\n\t{\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_publish_get_category_note: note has NOT changed. Exiting.\");\n\t\tg_free(n1);\n\t\treturn NULL; /* nothing to update */\n\t}\n\n\tstart_time_attr = note_start ? g_strdup_printf(\" startTime=\\\"%s\\\"\", (tmp = sipe_utils_time_to_str(note_start))) : NULL;\n\tg_free(tmp);\n\ttmp = NULL;\n\tend_time_attr = note_end ? g_strdup_printf(\" endTime=\\\"%s\\\"\", (tmp = sipe_utils_time_to_str(note_end))) : NULL;\n\tg_free(tmp);\n\n\tif (n1) {\n\t\ttmp1 = g_strdup_printf(SIPE_PUB_XML_NOTE,\n\t\t\t\t       instance,\n\t\t\t\t       200,\n\t\t\t\t       publication_note_200 ? publication_note_200->version : 0,\n\t\t\t\t       note_type,\n\t\t\t\t       start_time_attr ? start_time_attr : \"\",\n\t\t\t\t       end_time_attr ? end_time_attr : \"\",\n\t\t\t\t       n1);\n\n\t\ttmp2 = g_strdup_printf(SIPE_PUB_XML_NOTE,\n\t\t\t\t       instance,\n\t\t\t\t       300,\n\t\t\t\t       publication_note_300 ? publication_note_300->version : 0,\n\t\t\t\t       note_type,\n\t\t\t\t       start_time_attr ? start_time_attr : \"\",\n\t\t\t\t       end_time_attr ? end_time_attr : \"\",\n\t\t\t\t       n1);\n\n\t\ttmp3 = g_strdup_printf(SIPE_PUB_XML_NOTE,\n\t\t\t\t       instance,\n\t\t\t\t       400,\n\t\t\t\t       publication_note_400 ? publication_note_400->version : 0,\n\t\t\t\t       note_type,\n\t\t\t\t       start_time_attr ? start_time_attr : \"\",\n\t\t\t\t       end_time_attr ? end_time_attr : \"\",\n\t\t\t\t       n1);\n\t} else {\n\t\ttmp1 = g_strdup_printf( SIPE_PUB_XML_PUBLICATION_CLEAR,\n\t\t\t\t\t\"note\",\n\t\t\t\t\tinstance,\n\t\t\t\t\t200,\n\t\t\t\t\tpublication_note_200 ? publication_note_200->version : 0,\n\t\t\t\t\t\"static\");\n\t\ttmp2 = g_strdup_printf( SIPE_PUB_XML_PUBLICATION_CLEAR,\n\t\t\t\t\t\"note\",\n\t\t\t\t\tinstance,\n\t\t\t\t\t300,\n\t\t\t\t\tpublication_note_200 ? publication_note_200->version : 0,\n\t\t\t\t\t\"static\");\n\t\ttmp3 = g_strdup_printf( SIPE_PUB_XML_PUBLICATION_CLEAR,\n\t\t\t\t\t\"note\",\n\t\t\t\t\tinstance,\n\t\t\t\t\t400,\n\t\t\t\t\tpublication_note_200 ? publication_note_200->version : 0,\n\t\t\t\t\t\"static\");\n\t}\n\tres =  g_strconcat(tmp1, tmp2, tmp3, NULL);\n\n\tg_free(start_time_attr);\n\tg_free(end_time_attr);\n\tg_free(tmp1);\n\tg_free(tmp2);\n\tg_free(tmp3);\n\tg_free(n1);\n\n\treturn res;\n}\n\n/**\n * Publishes 'calendarData' category's WorkingHours.\n *\n * @param version\t        (%u)  Ex.: 1\n * @param email\t                (%s)  Ex.: alice@cosmo.local\n * @param working_hours_xml_str\t(%s)  Ex.: <WorkingHours xmlns=.....\n *\n * @param version\t        (%u)\n *\n * @param version\t        (%u)\n * @param email\t                (%s)\n * @param working_hours_xml_str\t(%s)\n *\n * @param version\t        (%u)\n * @param email\t                (%s)\n * @param working_hours_xml_str\t(%s)\n *\n * @param version\t        (%u)\n * @param email\t                (%s)\n * @param working_hours_xml_str\t(%s)\n *\n * @param version\t        (%u)\n */\n#define SIPE_PUB_XML_WORKING_HOURS \\\n\t\"<publication categoryName=\\\"calendarData\\\" instance=\\\"0\\\" container=\\\"1\\\" version=\\\"%d\\\" expireType=\\\"static\\\">\"\\\n\t\t\"<calendarData xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/calendarData\\\" mailboxID=\\\"%s\\\">%s\"\\\n\t\t\"</calendarData>\"\\\n\t\"</publication>\"\\\n\t\"<publication categoryName=\\\"calendarData\\\" instance=\\\"0\\\" container=\\\"100\\\" version=\\\"%d\\\" expireType=\\\"static\\\">\"\\\n\t\t\"<calendarData xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/calendarData\\\"/>\"\\\n\t\"</publication>\"\\\n\t\"<publication categoryName=\\\"calendarData\\\" instance=\\\"0\\\" container=\\\"200\\\" version=\\\"%d\\\" expireType=\\\"static\\\">\"\\\n\t\t\"<calendarData xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/calendarData\\\" mailboxID=\\\"%s\\\">%s\"\\\n\t\t\"</calendarData>\"\\\n\t\"</publication>\"\\\n\t\"<publication categoryName=\\\"calendarData\\\" instance=\\\"0\\\" container=\\\"300\\\" version=\\\"%d\\\" expireType=\\\"static\\\">\"\\\n\t\t\"<calendarData xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/calendarData\\\" mailboxID=\\\"%s\\\">%s\"\\\n\t\t\"</calendarData>\"\\\n\t\"</publication>\"\\\n\t\"<publication categoryName=\\\"calendarData\\\" instance=\\\"0\\\" container=\\\"400\\\" version=\\\"%d\\\" expireType=\\\"static\\\">\"\\\n\t\t\"<calendarData xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/calendarData\\\" mailboxID=\\\"%s\\\">%s\"\\\n\t\t\"</calendarData>\"\\\n\t\"</publication>\"\\\n\t\"<publication categoryName=\\\"calendarData\\\" instance=\\\"0\\\" container=\\\"32000\\\" version=\\\"%d\\\" expireType=\\\"static\\\">\"\\\n\t\t\"<calendarData xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/calendarData\\\"/>\"\\\n\t\"</publication>\"\n\n/**\n * Returns 'calendarData' XML part with WorkingHours for publication.\n * Must be g_free'd after use.\n */\nstatic gchar *sipe_publish_get_category_cal_working_hours(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_calendar* cal = sipe_private->calendar;\n\n\t/* key is <category><instance><container> */\n\tgchar *key_cal_1     = g_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", 0, 1);\n\tgchar *key_cal_100   = g_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", 0, 100);\n\tgchar *key_cal_200   = g_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", 0, 200);\n\tgchar *key_cal_300   = g_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", 0, 300);\n\tgchar *key_cal_400   = g_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", 0, 400);\n\tgchar *key_cal_32000 = g_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", 0, 32000);\n\n\tgpointer tmp = g_hash_table_lookup(sipe_private->our_publications, \"calendarData\");\n\tstruct sipe_publication *publication_cal_1 = tmp ? g_hash_table_lookup(tmp, key_cal_1) : NULL;\n\tstruct sipe_publication *publication_cal_100 = tmp ? g_hash_table_lookup(tmp, key_cal_100) : NULL;\n\tstruct sipe_publication *publication_cal_200 = tmp ? g_hash_table_lookup(tmp, key_cal_200) : NULL;\n\tstruct sipe_publication *publication_cal_300 = tmp ? g_hash_table_lookup(tmp, key_cal_300) : NULL;\n\tstruct sipe_publication *publication_cal_400 = tmp ? g_hash_table_lookup(tmp, key_cal_400) : NULL;\n\tstruct sipe_publication *publication_cal_32000 = tmp ? g_hash_table_lookup(tmp, key_cal_32000) : NULL;\n\n\tconst char *n1 = cal ? cal->working_hours_xml_str : NULL;\n\tconst char *n2 = publication_cal_300 ? publication_cal_300->working_hours_xml_str : NULL;\n\n\tg_free(key_cal_1);\n\tg_free(key_cal_100);\n\tg_free(key_cal_200);\n\tg_free(key_cal_300);\n\tg_free(key_cal_400);\n\tg_free(key_cal_32000);\n\n\tif (!cal || is_empty(cal->email) || is_empty(cal->working_hours_xml_str)) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_publish_get_category_cal_working_hours: no data to publish, exiting\");\n\t\treturn NULL;\n\t}\n\n\tif (sipe_strequal(n1, n2))\n\t{\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_publish_get_category_cal_working_hours: WorkingHours has NOT changed. Exiting.\");\n\t\treturn NULL; /* nothing to update */\n\t}\n\n\treturn g_strdup_printf(SIPE_PUB_XML_WORKING_HOURS,\n\t\t\t\t/* 1 */\n\t\t\t\tpublication_cal_1 ? publication_cal_1->version : 0,\n\t\t\t\tcal->email,\n\t\t\t\tcal->working_hours_xml_str,\n\t\t\t\t/* 100 - Public */\n\t\t\t\tpublication_cal_100 ? publication_cal_100->version : 0,\n\t\t\t\t/* 200 - Company */\n\t\t\t\tpublication_cal_200 ? publication_cal_200->version : 0,\n\t\t\t\tcal->email,\n\t\t\t\tcal->working_hours_xml_str,\n\t\t\t\t/* 300 - Team */\n\t\t\t\tpublication_cal_300 ? publication_cal_300->version : 0,\n\t\t\t\tcal->email,\n\t\t\t\tcal->working_hours_xml_str,\n\t\t\t\t/* 400 - Personal */\n\t\t\t\tpublication_cal_400 ? publication_cal_400->version : 0,\n\t\t\t\tcal->email,\n\t\t\t\tcal->working_hours_xml_str,\n\t\t\t\t/* 32000 - Blocked */\n\t\t\t\tpublication_cal_32000 ? publication_cal_32000->version : 0\n\t\t\t      );\n}\n\n/**\n * Publishes 'calendarData' category's FreeBusy.\n *\n * @param instance\t        (%u)  Ex.: 1300372959\n * @param version\t        (%u)  Ex.: 1\n *\n * @param instance\t        (%u)  Ex.: 1300372959\n * @param version\t        (%u)  Ex.: 1\n *\n * @param instance\t        (%u)  Ex.: 1300372959\n * @param version\t        (%u)  Ex.: 1\n * @param email\t                (%s)  Ex.: alice@cosmo.local\n * @param fb_start_time_str\t(%s)  Ex.: 2009-12-03T00:00:00Z\n * @param free_busy_base64\t(%s)  Ex.: AAAAAAAAAAAAAAAAAAAAA.....\n *\n * @param instance\t        (%u)  Ex.: 1300372959\n * @param version\t        (%u)  Ex.: 1\n * @param email\t                (%s)  Ex.: alice@cosmo.local\n * @param fb_start_time_str\t(%s)  Ex.: 2009-12-03T00:00:00Z\n * @param free_busy_base64\t(%s)  Ex.: AAAAAAAAAAAAAAAAAAAAA.....\n *\n * @param instance\t        (%u)  Ex.: 1300372959\n * @param version\t        (%u)  Ex.: 1\n * @param email\t                (%s)  Ex.: alice@cosmo.local\n * @param fb_start_time_str\t(%s)  Ex.: 2009-12-03T00:00:00Z\n * @param free_busy_base64\t(%s)  Ex.: AAAAAAAAAAAAAAAAAAAAA.....\n *\n * @param instance\t        (%u)  Ex.: 1300372959\n * @param version\t        (%u)  Ex.: 1\n */\n#define SIPE_PUB_XML_FREE_BUSY \\\n\t\"<publication categoryName=\\\"calendarData\\\" instance=\\\"%u\\\" container=\\\"1\\\" version=\\\"%d\\\" expireType=\\\"endpoint\\\">\"\\\n\t\t\"<calendarData xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/calendarData\\\"/>\"\\\n\t\"</publication>\"\\\n\t\"<publication categoryName=\\\"calendarData\\\" instance=\\\"%u\\\" container=\\\"100\\\" version=\\\"%d\\\" expireType=\\\"endpoint\\\">\"\\\n\t\t\"<calendarData xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/calendarData\\\"/>\"\\\n\t\"</publication>\"\\\n\t\"<publication categoryName=\\\"calendarData\\\" instance=\\\"%u\\\" container=\\\"200\\\" version=\\\"%d\\\" expireType=\\\"endpoint\\\">\"\\\n\t\t\"<calendarData xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/calendarData\\\" mailboxID=\\\"%s\\\">\"\\\n\t\t\t\"<freeBusy startTime=\\\"%s\\\" granularity=\\\"PT15M\\\" encodingVersion=\\\"1\\\">%s</freeBusy>\"\\\n\t\t\"</calendarData>\"\\\n\t\"</publication>\"\\\n\t\"<publication categoryName=\\\"calendarData\\\" instance=\\\"%u\\\" container=\\\"300\\\" version=\\\"%d\\\" expireType=\\\"endpoint\\\">\"\\\n\t\t\"<calendarData xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/calendarData\\\" mailboxID=\\\"%s\\\">\"\\\n\t\t\t\"<freeBusy startTime=\\\"%s\\\" granularity=\\\"PT15M\\\" encodingVersion=\\\"1\\\">%s</freeBusy>\"\\\n\t\t\"</calendarData>\"\\\n\t\"</publication>\"\\\n\t\"<publication categoryName=\\\"calendarData\\\" instance=\\\"%u\\\" container=\\\"400\\\" version=\\\"%d\\\" expireType=\\\"endpoint\\\">\"\\\n\t\t\"<calendarData xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/calendarData\\\" mailboxID=\\\"%s\\\">\"\\\n\t\t\t\"<freeBusy startTime=\\\"%s\\\" granularity=\\\"PT15M\\\" encodingVersion=\\\"1\\\">%s</freeBusy>\"\\\n\t\t\"</calendarData>\"\\\n\t\"</publication>\"\\\n\t\"<publication categoryName=\\\"calendarData\\\" instance=\\\"%u\\\" container=\\\"32000\\\" version=\\\"%d\\\" expireType=\\\"endpoint\\\">\"\\\n\t\t\"<calendarData xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/calendarData\\\"/>\"\\\n\t\"</publication>\"\n\n/**\n * Returns 'calendarData' XML part with FreeBusy for publication.\n * Must be g_free'd after use.\n */\nstatic gchar *sipe_publish_get_category_cal_free_busy(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_calendar* cal = sipe_private->calendar;\n\tguint cal_data_instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_CALENDAR_DATA);\n\tchar *fb_start_str;\n\tchar *free_busy_base64;\n\t/* const char *st; */\n\t/* const char *fb; */\n\tchar *res;\n\n\t/* key is <category><instance><container> */\n\tgchar *key_cal_1     = g_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", cal_data_instance, 1);\n\tgchar *key_cal_100   = g_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", cal_data_instance, 100);\n\tgchar *key_cal_200   = g_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", cal_data_instance, 200);\n\tgchar *key_cal_300   = g_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", cal_data_instance, 300);\n\tgchar *key_cal_400   = g_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", cal_data_instance, 400);\n\tgchar *key_cal_32000 = g_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", cal_data_instance, 32000);\n\n\tgpointer tmp = g_hash_table_lookup(sipe_private->our_publications, \"calendarData\");\n\tstruct sipe_publication *publication_cal_1 = tmp ? g_hash_table_lookup(tmp, key_cal_1) : NULL;\n\tstruct sipe_publication *publication_cal_100 = tmp ? g_hash_table_lookup(tmp, key_cal_100) : NULL;\n\tstruct sipe_publication *publication_cal_200 = tmp ? g_hash_table_lookup(tmp, key_cal_200) : NULL;\n\tstruct sipe_publication *publication_cal_300 = tmp ? g_hash_table_lookup(tmp, key_cal_300) : NULL;\n\tstruct sipe_publication *publication_cal_400 = tmp ? g_hash_table_lookup(tmp, key_cal_400) : NULL;\n\tstruct sipe_publication *publication_cal_32000 = tmp ? g_hash_table_lookup(tmp, key_cal_32000) : NULL;\n\n\tg_free(key_cal_1);\n\tg_free(key_cal_100);\n\tg_free(key_cal_200);\n\tg_free(key_cal_300);\n\tg_free(key_cal_400);\n\tg_free(key_cal_32000);\n\n\tif (!cal || is_empty(cal->email) || !cal->fb_start || is_empty(cal->free_busy)) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_publish_get_category_cal_free_busy: no data to publish, exiting\");\n\t\treturn NULL;\n\t}\n\n\tfb_start_str = sipe_utils_time_to_str(cal->fb_start);\n\tfree_busy_base64 = sipe_cal_get_freebusy_base64(cal->free_busy);\n\n\t/* we will rebuplish the same data to refresh publication time,\n\t * so if data from multiple sources, most recent will be choosen\n\t */\n\t// st = publication_cal_300 ? publication_cal_300->fb_start_str : NULL;\n\t// fb = publication_cal_300 ? publication_cal_300->free_busy_base64 : NULL;\n\t//\n\t//if (sipe_strequal(st, fb_start_str) && sipe_strequal(fb, free_busy_base64))\n\t//{\n\t//\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_publish_get_category_cal_free_busy: FreeBusy has NOT changed. Exiting.\");\n\t//\tg_free(fb_start_str);\n\t//\tg_free(free_busy_base64);\n\t//\treturn NULL; /* nothing to update */\n\t//}\n\n\tres = g_strdup_printf(SIPE_PUB_XML_FREE_BUSY,\n\t\t\t\t/* 1 */\n\t\t\t\tcal_data_instance,\n\t\t\t\tpublication_cal_1 ? publication_cal_1->version : 0,\n\t\t\t\t/* 100 - Public */\n\t\t\t\tcal_data_instance,\n\t\t\t\tpublication_cal_100 ? publication_cal_100->version : 0,\n\t\t\t\t/* 200 - Company */\n\t\t\t\tcal_data_instance,\n\t\t\t\tpublication_cal_200 ? publication_cal_200->version : 0,\n\t\t\t\tcal->email,\n\t\t\t\tfb_start_str,\n\t\t\t\tfree_busy_base64,\n\t\t\t\t/* 300 - Team */\n\t\t\t\tcal_data_instance,\n\t\t\t\tpublication_cal_300 ? publication_cal_300->version : 0,\n\t\t\t\tcal->email,\n\t\t\t\tfb_start_str,\n\t\t\t\tfree_busy_base64,\n\t\t\t\t/* 400 - Personal */\n\t\t\t\tcal_data_instance,\n\t\t\t\tpublication_cal_400 ? publication_cal_400->version : 0,\n\t\t\t\tcal->email,\n\t\t\t\tfb_start_str,\n\t\t\t\tfree_busy_base64,\n\t\t\t\t/* 32000 - Blocked */\n\t\t\t\tcal_data_instance,\n\t\t\t\tpublication_cal_32000 ? publication_cal_32000->version : 0\n\t\t\t     );\n\n\tg_free(fb_start_str);\n\tg_free(free_busy_base64);\n\treturn res;\n}\n\n#ifdef HAVE_VV\n#define SIPE_PUB_XML_DEVICE_VV \\\n\t\t\t\t\"<voice capture=\\\"true\\\" render=\\\"true\\\" publish=\\\"false\\\"/>\"\\\n\t\t\t\t\"<video capture=\\\"true\\\" render=\\\"true\\\" publish=\\\"false\\\"/>\"\n#else\n#define SIPE_PUB_XML_DEVICE_VV\n#endif\n\n#ifdef HAVE_FREERDP\n#define SIPE_PUB_XML_DEVICE_APPSHARE \\\n\t\t\t\t\"<applicationSharing capture=\\\"true\\\" render=\\\"true\\\" publish=\\\"false\\\"/>\"\\\n\t\t\t\t\"<contentPowerPoint capture=\\\"true\\\" render=\\\"true\\\" publish=\\\"false\\\"/>\"\n#else\n#define SIPE_PUB_XML_DEVICE_APPSHARE\n#endif\n\n/**\n * Publishes 'device' category.\n * @param instance\t(%u) Ex.: 1938468728\n * @param version\t(%u) Ex.: 1\n * @param endpointId\t(%s) Ex.: C707E38E-1E10-5413-94D9-ECAC260A0269\n * @param uri\t\t(%s) Self URI. Ex.: sip:alice7@boston.local\n * @param timezone\t(%s) Ex.: 00:00:00+01:00\n * @param machineName\t(%s) Ex.: BOSTON-OCS07\n */\n#define SIPE_PUB_XML_DEVICE \\\n\t\"<publication categoryName=\\\"device\\\" instance=\\\"%u\\\" container=\\\"2\\\" version=\\\"%u\\\" expireType=\\\"endpoint\\\">\"\\\n\t\t\"<device xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/device\\\" endpointId=\\\"%s\\\">\"\\\n\t\t\t\"<capabilities preferred=\\\"false\\\" uri=\\\"%s\\\">\"\\\n\t\t\t\t\"<text capture=\\\"true\\\" render=\\\"true\\\" publish=\\\"false\\\"/>\"\\\n\t\t\t\t\"<gifInk capture=\\\"false\\\" render=\\\"true\\\" publish=\\\"false\\\"/>\"\\\n\t\t\t\t\"<isfInk capture=\\\"false\\\" render=\\\"true\\\" publish=\\\"false\\\"/>\"\\\n\t\t\t\tSIPE_PUB_XML_DEVICE_VV\\\n\t\t\t\tSIPE_PUB_XML_DEVICE_APPSHARE\\\n\t\t\t\"</capabilities>\"\\\n\t\t\t\"<timezone>%s</timezone>\"\\\n\t\t\t\"<machineName>%s</machineName>\"\\\n\t\t\"</device>\"\\\n\t\"</publication>\"\n\n/**\n * Returns 'device' XML part for publication.\n * Must be g_free'd after use.\n */\nstatic gchar *sipe_publish_get_category_device(struct sipe_core_private *sipe_private)\n{\n\tgchar *uri;\n\tgchar *doc;\n\tgchar *uuid = get_uuid(sipe_private);\n\tguint device_instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_DEVICE);\n\t/* key is <category><instance><container> */\n\tgchar *key = g_strdup_printf(\"<%s><%u><%u>\", \"device\", device_instance, 2);\n\tGHashTable *tmp = g_hash_table_lookup(sipe_private->our_publications, \"device\");\n\tstruct sipe_publication *publication = tmp ? g_hash_table_lookup(tmp, key) : NULL;\n\n\tg_free(key);\n\n\turi = sip_uri_self(sipe_private);\n\tdoc = g_strdup_printf(SIPE_PUB_XML_DEVICE,\n\t\tdevice_instance,\n\t\tpublication ? publication->version : 0,\n\t\tuuid,\n\t\turi,\n\t\t\"00:00:00+01:00\", /* @TODO make timezone real*/\n\t\tg_get_host_name()\n\t);\n\n\tg_free(uri);\n\tg_free(uuid);\n\n\treturn doc;\n}\n\n/**\n * Publishes 'machineState' category.\n * @param instance\t(%u) Ex.: 926460663\n * @param version\t(%u) Ex.: 22\n * @param availability\t(%d) Ex.: 3500\n * @param instance\t(%u) Ex.: 926460663\n * @param version\t(%u) Ex.: 22\n * @param availability\t(%d) Ex.: 3500\n */\n#define SIPE_PUB_XML_STATE_MACHINE \\\n\t\"<publication categoryName=\\\"state\\\" instance=\\\"%u\\\" container=\\\"2\\\" version=\\\"%u\\\" expireType=\\\"endpoint\\\">\"\\\n\t\t\"<state xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/state\\\" manual=\\\"false\\\" xmlns:xsi=\\\"http://www.w3.org/2001/XMLSchema-instance\\\" xsi:type=\\\"machineState\\\">\"\\\n\t\t\t\"<availability>%d</availability>\"\\\n\t\t\t\"<endpointLocation/>\"\\\n\t\t\"</state>\"\\\n\t\"</publication>\"\\\n\t\"<publication categoryName=\\\"state\\\" instance=\\\"%u\\\" container=\\\"3\\\" version=\\\"%u\\\" expireType=\\\"endpoint\\\">\"\\\n\t\t\"<state xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/state\\\" manual=\\\"false\\\" xmlns:xsi=\\\"http://www.w3.org/2001/XMLSchema-instance\\\" xsi:type=\\\"machineState\\\">\"\\\n\t\t\t\"<availability>%d</availability>\"\\\n\t\t\t\"<endpointLocation/>\"\\\n\t\t\"</state>\"\\\n\t\"</publication>\"\n\n/**\n * Publishes 'userState' category.\n * @param instance\t(%u) User. Ex.: 536870912\n * @param version\t(%u) User Container 2. Ex.: 22\n * @param availability\t(%d) User Container 2. Ex.: 15500\n * @param instance\t(%u) User. Ex.: 536870912\n * @param version\t(%u) User Container 3.Ex.: 22\n * @param availability\t(%d) User Container 3. Ex.: 15500\n */\n#define SIPE_PUB_XML_STATE_USER \\\n\t\"<publication categoryName=\\\"state\\\" instance=\\\"%u\\\" container=\\\"2\\\" version=\\\"%u\\\" expireType=\\\"static\\\">\"\\\n\t\t\"<state xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/state\\\" manual=\\\"true\\\" xmlns:xsi=\\\"http://www.w3.org/2001/XMLSchema-instance\\\" xsi:type=\\\"userState\\\">\"\\\n\t\t\t\"<availability>%d</availability>\"\\\n\t\t\t\"<endpointLocation/>\"\\\n\t\t\"</state>\"\\\n\t\"</publication>\"\\\n\t\"<publication categoryName=\\\"state\\\" instance=\\\"%u\\\" container=\\\"3\\\" version=\\\"%u\\\" expireType=\\\"static\\\">\"\\\n\t\t\"<state xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/state\\\" manual=\\\"true\\\" xmlns:xsi=\\\"http://www.w3.org/2001/XMLSchema-instance\\\" xsi:type=\\\"userState\\\">\"\\\n\t\t\t\"<availability>%d</availability>\"\\\n\t\t\t\"<endpointLocation/>\"\\\n\t\t\"</state>\"\\\n\t\"</publication>\"\n\n/**\n * A service method - use\n * - send_publish_get_category_state_machine and\n * - send_publish_get_category_state_user instead.\n * Must be g_free'd after use.\n */\nstatic gchar *sipe_publish_get_category_state(struct sipe_core_private *sipe_private,\n\t\t\t\t\t      gboolean force_publish,\n\t\t\t\t\t      gboolean is_user_state)\n{\n\tint availability = sipe_ocs2007_availability_from_status(sipe_private->status, NULL);\n\tguint instance = is_user_state ? sipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_USER) :\n\t\t\t\t\t sipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_MACHINE);\n\t/* key is <category><instance><container> */\n\tgchar *key_2 = g_strdup_printf(\"<%s><%u><%u>\", \"state\", instance, 2);\n\tgchar *key_3 = g_strdup_printf(\"<%s><%u><%u>\", \"state\", instance, 3);\n\tgpointer state = g_hash_table_lookup(sipe_private->our_publications, \"state\");\n\tstruct sipe_publication *publication_2 = state ? g_hash_table_lookup(state, key_2) : NULL;\n\tstruct sipe_publication *publication_3 = state ? g_hash_table_lookup(state, key_3) : NULL;\n\n\tg_free(key_2);\n\tg_free(key_3);\n\n\tif (!force_publish && publication_2 && (publication_2->availability == availability))\n\t{\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_publish_get_category_state: state has NOT changed. Exiting.\");\n\t\treturn NULL; /* nothing to update */\n\t}\n\n\treturn g_strdup_printf( is_user_state ? SIPE_PUB_XML_STATE_USER : SIPE_PUB_XML_STATE_MACHINE,\n\t\t\t\tinstance,\n\t\t\t\tpublication_2 ? publication_2->version : 0,\n\t\t\t\tavailability,\n\t\t\t\tinstance,\n\t\t\t\tpublication_3 ? publication_3->version : 0,\n\t\t\t\tavailability);\n}\n\n/**\n * Returns 'machineState' XML part for publication.\n * Must be g_free'd after use.\n */\nstatic gchar *sipe_publish_get_category_state_machine(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t      gboolean force_publish)\n{\n\treturn sipe_publish_get_category_state(sipe_private, force_publish, FALSE);\n}\n\n/**\n * Returns 'userState' XML part for publication.\n * Must be g_free'd after use.\n */\nstatic gchar *sipe_publish_get_category_state_user(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t   gboolean force_publish)\n{\n\treturn sipe_publish_get_category_state(sipe_private, force_publish, TRUE);\n}\n\nstatic void send_publish_category_initial(struct sipe_core_private *sipe_private)\n{\n\tgchar *pub_device   = sipe_publish_get_category_device(sipe_private);\n\tgchar *pub_machine;\n\tgchar *pub_user;\n\tgchar *publications;\n\n\tsipe_status_set_activity(sipe_private,\n\t\t\t\t sipe_backend_status(SIPE_CORE_PUBLIC));\n\n\tpub_machine  = sipe_publish_get_category_state_machine(sipe_private,\n\t\t\t\t\t\t\t       TRUE);\n\tpub_user = sipe_publish_get_category_state_user(sipe_private, TRUE);\n\n\tpublications = g_strdup_printf(\"%s%s%s\",\n\t\t\t\t       pub_device,\n\t\t\t\t       pub_machine ? pub_machine : \"\",\n\t\t\t\t       pub_user ? pub_user : \"\");\n\tg_free(pub_device);\n\tg_free(pub_machine);\n\tg_free(pub_user);\n\n\tsend_presence_publish(sipe_private, publications);\n\tg_free(publications);\n}\n\nstatic gboolean process_send_presence_category_publish_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t\t\tstruct sipmsg *msg,\n\t\t\t\t\t\t\t\tstruct transaction *trans)\n{\n\tconst gchar *contenttype = sipmsg_find_content_type_header(msg);\n\n\tif (msg->response == 200 && g_str_has_prefix(contenttype, \"application/vnd-microsoft-roaming-self+xml\")) {\n\t\tsipe_ocs2007_process_roaming_self(sipe_private, msg);\n\t} else if (msg->response == 409 && g_str_has_prefix(contenttype, \"application/msrtc-fault+xml\")) {\n\t\tsipe_xml *xml;\n\t\tconst sipe_xml *node;\n\t\tgchar *fault_code;\n\t\tGHashTable *faults;\n\t\tint index_our;\n\t\tgboolean has_device_publication = FALSE;\n\n\t\txml = sipe_xml_parse(msg->body, msg->bodylen);\n\n\t\t/* test if version mismatch fault */\n\t\tfault_code = sipe_xml_data(sipe_xml_child(xml, \"Faultcode\"));\n\t\tif (!sipe_strequal(fault_code, \"Client.BadCall.WrongDelta\")) {\n\t\t\tSIPE_DEBUG_INFO(\"process_send_presence_category_publish_response: unsupported fault code:%s returning.\", fault_code);\n\t\t\tg_free(fault_code);\n\t\t\tsipe_xml_free(xml);\n\t\t\treturn TRUE;\n\t\t}\n\t\tg_free(fault_code);\n\n\t\t/* accumulating information about faulty versions */\n\t\tfaults = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);\n\t\tfor (node = sipe_xml_child(xml, \"details/operation\");\n\t\t     node;\n\t\t     node = sipe_xml_twin(node))\n\t\t{\n\t\t\tconst gchar *index = sipe_xml_attribute(node, \"index\");\n\t\t\tconst gchar *curVersion = sipe_xml_attribute(node, \"curVersion\");\n\n\t\t\tg_hash_table_insert(faults, g_strdup(index), g_strdup(curVersion));\n\t\t\tSIPE_DEBUG_INFO(\"fault added: index:%s curVersion:%s\", index, curVersion);\n\t\t}\n\t\tsipe_xml_free(xml);\n\n\t\t/* here we are parsing our own request to figure out what publication\n\t\t * referenced here only by index went wrong\n\t\t */\n\t\txml = sipe_xml_parse(trans->msg->body, trans->msg->bodylen);\n\n\t\t/* publication */\n\t\tfor (node = sipe_xml_child(xml, \"publications/publication\"),\n\t\t     index_our = 1; /* starts with 1 - our first publication */\n\t\t     node;\n\t\t     node = sipe_xml_twin(node), index_our++)\n\t\t{\n\t\t\tgchar *idx = g_strdup_printf(\"%d\", index_our);\n\t\t\tconst gchar *curVersion = g_hash_table_lookup(faults, idx);\n\t\t\tconst gchar *categoryName = sipe_xml_attribute(node, \"categoryName\");\n\t\t\tg_free(idx);\n\n\t\t\tif (sipe_strequal(\"device\", categoryName)) {\n\t\t\t\thas_device_publication = TRUE;\n\t\t\t}\n\n\t\t\tif (curVersion) { /* fault exist on this index */\n\t\t\t\tconst gchar *container = sipe_xml_attribute(node, \"container\");\n\t\t\t\tconst gchar *instance = sipe_xml_attribute(node, \"instance\");\n\t\t\t\t/* key is <category><instance><container> */\n\t\t\t\tgchar *key = g_strdup_printf(\"<%s><%s><%s>\", categoryName, instance, container);\n\t\t\t\tGHashTable *category = g_hash_table_lookup(sipe_private->our_publications, categoryName);\n\n\t\t\t\tif (category) {\n\t\t\t\t\tstruct sipe_publication *publication =\n\t\t\t\t\t\tg_hash_table_lookup(category, key);\n\n\t\t\t\t\tSIPE_DEBUG_INFO(\"key is %s\", key);\n\n\t\t\t\t\tif (publication) {\n\t\t\t\t\t\tSIPE_DEBUG_INFO(\"Updating %s with version %s. Was %d before.\",\n\t\t\t\t\t\t\t\tkey, curVersion, publication->version);\n\t\t\t\t\t\t/* updating publication's version to the correct one */\n\t\t\t\t\t\tpublication->version = atoi(curVersion);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t/* We somehow lost this category from our publications... */\n\t\t\t\t\tstruct sipe_publication *publication = g_new0(struct sipe_publication, 1);\n\t\t\t\t\tpublication->category  = g_strdup(categoryName);\n\t\t\t\t\tpublication->instance  = atoi(instance);\n\t\t\t\t\tpublication->container = atoi(container);\n\t\t\t\t\tpublication->version   = atoi(curVersion);\n\t\t\t\t\tcategory = g_hash_table_new_full(g_str_hash, g_str_equal,\n\t\t\t\t\t\t\t\t\t g_free, (GDestroyNotify)free_publication);\n\t\t\t\t\tg_hash_table_insert(category, g_strdup(key), publication);\n\t\t\t\t\tg_hash_table_insert(sipe_private->our_publications, g_strdup(categoryName), category);\n\t\t\t\t\tSIPE_DEBUG_INFO(\"added lost category '%s' key '%s'\", categoryName, key);\n\t\t\t\t}\n\t\t\t\tg_free(key);\n\t\t\t}\n\t\t}\n\t\tsipe_xml_free(xml);\n\t\tg_hash_table_destroy(faults);\n\n\t\t/* rebublishing with right versions */\n\t\tif (has_device_publication) {\n\t\t\tsend_publish_category_initial(sipe_private);\n\t\t} else {\n\t\t\tsipe_ocs2007_category_publish(sipe_private, TRUE);\n\t\t}\n\t}\n\treturn TRUE;\n}\n\n/**\n * Publishes categories.\n * @param uri\t\t(%s) Self URI. Ex.: sip:alice7@boston.local\n * @param publications\t(%s) XML publications\n */\n#define SIPE_SEND_PRESENCE \\\n\t\"<publish xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/rich-presence\\\">\"\\\n\t\t\"<publications uri=\\\"%s\\\">\"\\\n\t\t\t\"%s\"\\\n\t\t\"</publications>\"\\\n\t\"</publish>\"\n\nstatic void send_presence_publish(struct sipe_core_private *sipe_private,\n\t\t\t\t  const char *publications)\n{\n\tgchar *uri;\n\tgchar *doc;\n\tgchar *tmp;\n\tgchar *hdr;\n\n\turi = sip_uri_self(sipe_private);\n\tdoc = g_strdup_printf(SIPE_SEND_PRESENCE,\n\t\turi,\n\t\tpublications);\n\n\ttmp = get_contact(sipe_private);\n\thdr = g_strdup_printf(\"Contact: %s\\r\\n\"\n\t\t\"Content-Type: application/msrtc-category-publish+xml\\r\\n\", tmp);\n\n\tsip_transport_service(sipe_private,\n\t\t\t      uri,\n\t\t\t      hdr,\n\t\t\t      doc,\n\t\t\t      process_send_presence_category_publish_response);\n\n\tg_free(tmp);\n\tg_free(hdr);\n\tg_free(uri);\n\tg_free(doc);\n}\n\n/**\n * Publishes self status\n * based on own calendar information.\n */\nvoid sipe_ocs2007_presence_publish(struct sipe_core_private *sipe_private,\n\t\t\t\t   SIPE_UNUSED_PARAMETER void *unused)\n{\n\tstruct sipe_calendar* cal = sipe_private->calendar;\n\tstruct sipe_cal_event* event = NULL;\n\tgchar *pub_cal_working_hours = NULL;\n\tgchar *pub_cal_free_busy = NULL;\n\tgchar *pub_calendar = NULL;\n\tgchar *pub_calendar2 = NULL;\n\tgchar *pub_oof_note = NULL;\n\tconst gchar *oof_note;\n\ttime_t oof_start = 0;\n\ttime_t oof_end = 0;\n\n\tif (!cal) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"publish_calendar_status_self() no calendar data.\");\n\t\treturn;\n\t}\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"publish_calendar_status_self() started.\");\n\tif (cal->cal_events) {\n\t\tevent = sipe_cal_get_event(cal->cal_events, time(NULL));\n\t}\n\n\tif (event) {\n\t\tsipe_cal_event_debug(event, \"publish_calendar_status_self: current event is:\\n\");\n\t} else {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"publish_calendar_status_self: current event is NULL\");\n\t}\n\n\t/* Logic\n\tif OOF\n\t\tOOF publish, Busy clean\n\tilse if Busy\n\t\tOOF clean, Busy publish\n\telse\n\t\tOOF clean, Busy clean\n\t*/\n\tif (event && event->cal_status == SIPE_CAL_OOF) {\n\t\tpub_calendar  = sipe_publish_get_category_state_calendar(sipe_private, event, cal->email, SIPE_CAL_OOF);\n\t\tpub_calendar2 = sipe_publish_get_category_state_calendar(sipe_private, NULL,  cal->email, SIPE_CAL_BUSY);\n\t} else if (event && event->cal_status == SIPE_CAL_BUSY) {\n\t\tpub_calendar  = sipe_publish_get_category_state_calendar(sipe_private, NULL,  cal->email, SIPE_CAL_OOF);\n\t\tpub_calendar2 = sipe_publish_get_category_state_calendar(sipe_private, event, cal->email, SIPE_CAL_BUSY);\n\t} else {\n\t\tpub_calendar  = sipe_publish_get_category_state_calendar(sipe_private, NULL,  cal->email, SIPE_CAL_OOF);\n\t\tpub_calendar2 = sipe_publish_get_category_state_calendar(sipe_private, NULL,  cal->email, SIPE_CAL_BUSY);\n\t}\n\n\toof_note = sipe_ews_get_oof_note(cal);\n\tif (sipe_strequal(\"Scheduled\", cal->oof_state)) {\n\t\toof_start = cal->oof_start;\n\t\toof_end = cal->oof_end;\n\t}\n\tpub_oof_note = sipe_publish_get_category_note(sipe_private, oof_note, \"OOF\", oof_start, oof_end, FALSE);\n\n\tpub_cal_working_hours = sipe_publish_get_category_cal_working_hours(sipe_private);\n\tpub_cal_free_busy = sipe_publish_get_category_cal_free_busy(sipe_private);\n\n\tif (!pub_cal_working_hours && !pub_cal_free_busy && !pub_calendar && !pub_calendar2 && !pub_oof_note) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"publish_calendar_status_self: nothing has changed.\");\n\t} else {\n\t\tgchar *publications = g_strdup_printf(\"%s%s%s%s%s\",\n\t\t\t\t       pub_cal_working_hours ? pub_cal_working_hours : \"\",\n\t\t\t\t       pub_cal_free_busy ? pub_cal_free_busy : \"\",\n\t\t\t\t       pub_calendar ? pub_calendar : \"\",\n\t\t\t\t       pub_calendar2 ? pub_calendar2 : \"\",\n\t\t\t\t       pub_oof_note ? pub_oof_note : \"\");\n\n\t\tsend_presence_publish(sipe_private, publications);\n\t\tg_free(publications);\n\t}\n\n\tg_free(pub_cal_working_hours);\n\tg_free(pub_cal_free_busy);\n\tg_free(pub_calendar);\n\tg_free(pub_calendar2);\n\tg_free(pub_oof_note);\n\n\t/* repeat scheduling */\n\tschedule_publish_update(sipe_private, time(NULL));\n}\n\nvoid sipe_ocs2007_category_publish(struct sipe_core_private *sipe_private,\n\t\t\t\t   gboolean force_publish)\n{\n\tGString *publications = g_string_new(\"\");\n\tgchar *tmp;\n\n\tif (force_publish || sipe_private->status_set_by_user) {\n\t\ttmp = sipe_publish_get_category_state_user(sipe_private,\n\t\t\t\t\t\t\t   force_publish);\n\t\tif (tmp) {\n\t\t\tg_string_append(publications, tmp);\n\t\t\tg_free(tmp);\n\t\t}\n\t}\n\n\ttmp = sipe_publish_get_category_state_machine(sipe_private,\n\t\t\t\t\t\t      force_publish);\n\tif (tmp) {\n\t\tg_string_append(publications, tmp);\n\t\tg_free(tmp);\n\t}\n\n\ttmp = sipe_publish_get_category_note(sipe_private,\n\t\t\t\t\t     sipe_private->note,\n\t\t\t\t\t     SIPE_CORE_PRIVATE_FLAG_IS(OOF_NOTE) ? \"OOF\" : \"personal\",\n\t\t\t\t\t     0,\n\t\t\t\t\t     0,\n\t\t\t\t\t     force_publish);\n\tif (tmp) {\n\t\tg_string_append(publications, tmp);\n\t\tg_free(tmp);\n\t}\n\n\tif (publications->len)\n\t\tsend_presence_publish(sipe_private, publications->str);\n\telse\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_osc2007_category_publish: nothing has changed. Exiting.\");\n\n\tg_string_free(publications, TRUE);\n}\n\nvoid sipe_ocs2007_phone_state_publish(struct sipe_core_private *sipe_private)\n{\n\tgchar *publications = NULL;\n\tguint instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_PHONE_VOIP);\n\n\t/* key is <category><instance><container> */\n\tgchar *key_2 = g_strdup_printf(\"<%s><%u><%u>\", \"state\", instance, 2);\n\tgchar *key_3 = g_strdup_printf(\"<%s><%u><%u>\", \"state\", instance, 3);\n\tgpointer state = g_hash_table_lookup(sipe_private->our_publications, \"state\");\n\tstruct sipe_publication *publication_2 = state ? g_hash_table_lookup(state, key_2) : NULL;\n\tstruct sipe_publication *publication_3 = state ? g_hash_table_lookup(state, key_3) : NULL;\n\tg_free(key_2);\n\tg_free(key_3);\n\n#ifdef HAVE_VV\n\tif (g_hash_table_size(sipe_private->media_calls)) {\n\t\tguint availability_min = 0;\n\t\tguint availability_max = 8999;\n\t\tconst gchar *token = NULL;\n\t\tGList *calls = g_hash_table_get_values(sipe_private->media_calls);\n\t\tGList *i;\n\n\t\tif (sipe_core_media_get_call(SIPE_CORE_PUBLIC)) {\n\t\t\tavailability_min = 6500;\n\t\t\ttoken = sipe_status_activity_to_token(SIPE_ACTIVITY_ON_PHONE);\n\t\t}\n\n\t\tfor (i = calls; i; i = i->next) {\n\t\t\tif (sipe_media_is_conference_call(i->data)) {\n\t\t\t\tavailability_min = 7000;\n\t\t\t\ttoken = sipe_status_activity_to_token(SIPE_ACTIVITY_IN_CONF);\n\t\t\t}\n\n\t\t\tif (sipe_appshare_get_role(i->data) == SIPE_APPSHARE_ROLE_PRESENTER) {\n\t\t\t\tavailability_min = 9000;\n\t\t\t\tavailability_max = 11999;\n\t\t\t\ttoken = sipe_status_activity_to_token(SIPE_ACTIVITY_IN_PRES);\n\t\t\t}\n\t\t}\n\n\t\tg_list_free(calls);\n\n\t\tif (token) {\n\t\t\tpublications = g_strdup_printf(SIPE_PUB_XML_STATE_PHONE,\n\t\t\t\t\tinstance, publication_2 ? publication_2->version : 0,\n\t\t\t\t\tavailability_min, token, availability_min, availability_max,\n\t\t\t\t\tinstance, publication_3 ? publication_3->version : 0,\n\t\t\t\t\tavailability_min, token, availability_min, availability_max);\n\t\t}\n\t} else\n#endif\n\t{\n\t\tpublications = g_strdup_printf(SIPE_PUB_XML_STATE_CALENDAR_PHONE_CLEAR,\n\t\t\t\tinstance, publication_2 ? publication_2->version : 0,\n\t\t\t\tinstance, publication_3 ? publication_3->version : 0);\n\t}\n\n\tif (publications) {\n\t\tsend_presence_publish(sipe_private, publications);\n\t\tg_free(publications);\n\t}\n}\n\nstatic void sipe_publish_get_cat_state_user_to_clear(SIPE_UNUSED_PARAMETER const char *name,\n\t\t\t\t\t\t     gpointer value,\n\t\t\t\t\t\t     GString* str)\n{\n\tstruct sipe_publication *publication = value;\n\n\tg_string_append_printf( str,\n\t\t\t\tSIPE_PUB_XML_PUBLICATION_CLEAR,\n\t\t\t\tpublication->category,\n\t\t\t\tpublication->instance,\n\t\t\t\tpublication->container,\n\t\t\t\tpublication->version,\n\t\t\t\t\"static\");\n}\n\nvoid sipe_ocs2007_reset_status(struct sipe_core_private *sipe_private)\n{\n\tGString* str;\n\tgchar *publications;\n\n\tif (!sipe_private->user_state_publications || g_hash_table_size(sipe_private->user_state_publications) == 0) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_reset_status: no userState publications, exiting.\");\n\t\treturn;\n\t}\n\n\tstr = g_string_new(NULL);\n\tg_hash_table_foreach(sipe_private->user_state_publications, (GHFunc)sipe_publish_get_cat_state_user_to_clear, str);\n\tpublications = g_string_free(str, FALSE);\n\n\tsend_presence_publish(sipe_private, publications);\n\tg_free(publications);\n}\n\n/* key is <category><instance><container> */\nstatic gboolean sipe_is_our_publication(struct sipe_core_private *sipe_private,\n\t\t\t\t\tconst gchar *key)\n{\n\tGSList *entry;\n\n\t/* filling keys for our publications if not yet cached */\n\tif (!sipe_private->our_publication_keys) {\n\t\tguint device_instance\t  = sipe_get_pub_instance(sipe_private, SIPE_PUB_DEVICE);\n\t\tguint machine_instance\t  = sipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_MACHINE);\n\t\tguint user_instance\t  = sipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_USER);\n\t\tguint calendar_instance\t  = sipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_CALENDAR);\n\t\tguint cal_oof_instance\t  = sipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_CALENDAR_OOF);\n\t\tguint phone_voip_instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_PHONE_VOIP);\n\t\tguint cal_data_instance\t  = sipe_get_pub_instance(sipe_private, SIPE_PUB_CALENDAR_DATA);\n\t\tguint note_oof_instance\t  = sipe_get_pub_instance(sipe_private, SIPE_PUB_NOTE_OOF);\n\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"* Our Publication Instances *\");\n\t\tSIPE_DEBUG_INFO(\"\\tDevice               : %u\\t0x%08X\", device_instance, device_instance);\n\t\tSIPE_DEBUG_INFO(\"\\tMachine State        : %u\\t0x%08X\", machine_instance, machine_instance);\n\t\tSIPE_DEBUG_INFO(\"\\tUser Stare           : %u\\t0x%08X\", user_instance, user_instance);\n\t\tSIPE_DEBUG_INFO(\"\\tCalendar State       : %u\\t0x%08X\", calendar_instance, calendar_instance);\n\t\tSIPE_DEBUG_INFO(\"\\tCalendar OOF State   : %u\\t0x%08X\", cal_oof_instance, cal_oof_instance);\n\t\tSIPE_DEBUG_INFO(\"\\tVOIP Phone State     : %u\\t0x%08X\", phone_voip_instance, phone_voip_instance);\n\t\tSIPE_DEBUG_INFO(\"\\tCalendar FreeBusy    : %u\\t0x%08X\", cal_data_instance, cal_data_instance);\n\t\tSIPE_DEBUG_INFO(\"\\tOOF Note             : %u\\t0x%08X\", note_oof_instance, note_oof_instance);\n\t\tSIPE_DEBUG_INFO(\"\\tNote                 : %u\", 0);\n\t\tSIPE_DEBUG_INFO(\"\\tCalendar WorkingHours: %u\", 0);\n\n\t\t/* device */\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"device\", device_instance, 2));\n\n\t\t/* state:machineState */\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"state\", machine_instance, 2));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"state\", machine_instance, 3));\n\n\t\t/* state:userState */\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"state\", user_instance, 2));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"state\", user_instance, 3));\n\n\t\t/* state:calendarState */\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"state\", calendar_instance, 2));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"state\", calendar_instance, 3));\n\n\t\t/* state:calendarState OOF */\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"state\", cal_oof_instance, 2));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"state\", cal_oof_instance, 3));\n\n\t\t/* state:phoneState */\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"state\", phone_voip_instance, 2));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"state\", phone_voip_instance, 3));\n\n\t\t/* note */\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"note\", 0, 200));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"note\", 0, 300));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"note\", 0, 400));\n\n\t\t/* note OOF */\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"note\", note_oof_instance, 200));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"note\", note_oof_instance, 300));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"note\", note_oof_instance, 400));\n\n\t\t/* calendarData:WorkingHours */\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", 0, 1));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", 0, 100));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", 0, 200));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", 0, 300));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", 0, 400));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", 0, 32000));\n\n\t\t/* calendarData:FreeBusy */\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", cal_data_instance, 1));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", cal_data_instance, 100));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", cal_data_instance, 200));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", cal_data_instance, 300));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", cal_data_instance, 400));\n\t\tsipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys,\n\t\t\tg_strdup_printf(\"<%s><%u><%u>\", \"calendarData\", cal_data_instance, 32000));\n\n\t\t//SIPE_DEBUG_INFO(\"sipe_is_our_publication: sipe_private->our_publication_keys length=%d\",\n\t\t//\t  sipe_private->our_publication_keys ? (int) g_slist_length(sipe_private->our_publication_keys) : -1);\n\t}\n\n\t//SIPE_DEBUG_INFO(\"sipe_is_our_publication: key=%s\", key);\n\n\tentry = sipe_private->our_publication_keys;\n\twhile (entry) {\n\t\t//SIPE_DEBUG_INFO(\"   sipe_is_our_publication: entry->data=%s\", entry->data);\n\t\tif (sipe_strequal(entry->data, key)) {\n\t\t\treturn TRUE;\n\t\t}\n\t\tentry = entry->next;\n\t}\n\treturn FALSE;\n}\n\nstatic void sipe_refresh_blocked_status_cb(char *buddy_name,\n\t\t\t\t\t   SIPE_UNUSED_PARAMETER struct sipe_buddy *buddy,\n\t\t\t\t\t   struct sipe_core_private *sipe_private)\n{\n\tint container_id = sipe_ocs2007_find_access_level(sipe_private, \"user\", buddy_name, NULL);\n\tgboolean blocked = (container_id == 32000);\n\tgboolean blocked_in_blist = sipe_backend_buddy_is_blocked(SIPE_CORE_PUBLIC, buddy_name);\n\n\t/* SIPE_DEBUG_INFO(\"sipe_refresh_blocked_status_cb: buddy_name=%s, blocked=%s, blocked_in_blist=%s\",\n\t\tbuddy_name, blocked ? \"T\" : \"F\", blocked_in_blist ? \"T\" : \"F\"); */\n\n\tif (blocked != blocked_in_blist) {\n\t\tsipe_backend_buddy_set_blocked_status(SIPE_CORE_PUBLIC, buddy_name, blocked);\n\t}\n}\n\nstatic void sipe_refresh_blocked_status(struct sipe_core_private *sipe_private)\n{\n\tsipe_buddy_foreach(sipe_private,\n\t\t\t   (GHFunc) sipe_refresh_blocked_status_cb,\n\t\t\t   sipe_private);\n}\n\n/**\n  *   When we receive some self (BE) NOTIFY with a new subscriber\n  *   we sends a setSubscribers request to him [SIP-PRES] 4.8\n  *\n  */\nvoid sipe_ocs2007_process_roaming_self(struct sipe_core_private *sipe_private,\n\t\t\t\t       struct sipmsg *msg)\n{\n\tgchar *contact;\n\tgchar *to;\n\tsipe_xml *xml;\n\tconst sipe_xml *node;\n\tconst sipe_xml *node2;\n        char *display_name = NULL;\n        char *uri;\n\tGSList *category_names = NULL;\n\tint aggreg_avail = 0;\n\tgchar *activity_token = NULL;\n\tgboolean do_update_status = FALSE;\n\tgboolean has_note_cleaned = FALSE;\n\tGHashTable *devices;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_ocs2007_process_roaming_self\");\n\n\txml = sipe_xml_parse(msg->body, msg->bodylen);\n\tif (!xml) return;\n\n\tcontact = get_contact(sipe_private);\n\tto = sip_uri_self(sipe_private);\n\n\t/* categories */\n\t/* set list of categories participating in this XML */\n\tfor (node = sipe_xml_child(xml, \"categories/category\"); node; node = sipe_xml_twin(node)) {\n\t\tconst gchar *name = sipe_xml_attribute(node, \"name\");\n\t\tcategory_names = sipe_utils_slist_insert_unique_sorted(category_names,\n\t\t\t\t\t\t\t\t       (gchar *)name,\n\t\t\t\t\t\t\t\t       (GCompareFunc)strcmp,\n\t\t\t\t\t\t\t\t       NULL);\n\t}\n\tSIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: category_names length=%d\",\n\t\t\tcategory_names ? (int) g_slist_length(category_names) : -1);\n\t/* drop category information */\n\tif (category_names) {\n\t\tGSList *entry = category_names;\n\t\twhile (entry) {\n\t\t\tGHashTable *cat_publications;\n\t\t\tconst gchar *category = entry->data;\n\t\t\tentry = entry->next;\n\t\t\tSIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: dropping category: %s\", category);\n\t\t\tcat_publications = g_hash_table_lookup(sipe_private->our_publications, category);\n\t\t\tif (cat_publications) {\n\t\t\t\tg_hash_table_remove(sipe_private->our_publications, category);\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: dropped category: %s\", category);\n\t\t\t}\n\t\t}\n\t}\n\tg_slist_free(category_names);\n\n\t/* filling our categories reflected in roaming data */\n\tdevices = g_hash_table_new_full(g_str_hash, g_str_equal,\n\t\t\t\t\tg_free, NULL);\n\tfor (node = sipe_xml_child(xml, \"categories/category\"); node; node = sipe_xml_twin(node)) {\n\t\tconst char *tmp;\n\t\tconst gchar *name = sipe_xml_attribute(node, \"name\");\n\t\tguint container = sipe_xml_int_attribute(node, \"container\", -1);\n\t\tguint instance  = sipe_xml_int_attribute(node, \"instance\", -1);\n\t\tguint version   = sipe_xml_int_attribute(node, \"version\", 0);\n\t\ttime_t publish_time = (tmp = sipe_xml_attribute(node, \"publishTime\")) ?\n\t\t\tsipe_utils_str_to_time(tmp) : 0;\n\t\tgchar *key;\n\t\tGHashTable *cat_publications = g_hash_table_lookup(sipe_private->our_publications, name);\n\n\t\t/* Ex. clear note: <category name=\"note\"/> */\n\t\tif (container == (guint)-1) {\n\t\t\tg_free(sipe_private->note);\n\t\t\tsipe_private->note = NULL;\n\t\t\tdo_update_status = TRUE;\n\t\t\tcontinue;\n\t\t}\n\n\t\t/* Ex. clear note: <category name=\"note\" container=\"200\"/> */\n\t\tif (instance == (guint)-1) {\n\t\t\tif (container == 200) {\n\t\t\t\tg_free(sipe_private->note);\n\t\t\t\tsipe_private->note = NULL;\n\t\t\t\tdo_update_status = TRUE;\n\t\t\t}\n\t\t\tSIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: removing publications for: %s/%u\", name, container);\n\t\t\tsipe_remove_category_container_publications(\n\t\t\t\tsipe_private->our_publications, name, container);\n\t\t\tcontinue;\n\t\t}\n\n\t\t/* key is <category><instance><container> */\n\t\tkey = g_strdup_printf(\"<%s><%u><%u>\", name, instance, container);\n\t\tSIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: key=%s version=%d\", key, version);\n\n\t\t/* capture all userState publication for later clean up if required */\n\t\tif (sipe_strequal(name, \"state\") && (container == 2 || container == 3)) {\n\t\t\tconst sipe_xml *xn_state = sipe_xml_child(node, \"state\");\n\n\t\t\tif (xn_state && sipe_strequal(sipe_xml_attribute(xn_state, \"type\"), \"userState\")) {\n\t\t\t\tstruct sipe_publication *publication = g_new0(struct sipe_publication, 1);\n\t\t\t\tpublication->category  = g_strdup(name);\n\t\t\t\tpublication->instance  = instance;\n\t\t\t\tpublication->container = container;\n\t\t\t\tpublication->version   = version;\n\n\t\t\t\tif (!sipe_private->user_state_publications) {\n\t\t\t\t\tsipe_private->user_state_publications = g_hash_table_new_full(\n\t\t\t\t\t\tg_str_hash, g_str_equal,\n\t\t\t\t\t\tg_free,\t(GDestroyNotify)free_publication);\n\t\t\t\t}\n\t\t\t\tg_hash_table_insert(sipe_private->user_state_publications, g_strdup(key), publication);\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: added to user_state_publications key=%s version=%d\",\n\t\t\t\t\t\tkey, version);\n\t\t\t}\n\t\t}\n\n\t\t/* count each client instance only once */\n\t\tif (sipe_strequal(name, \"device\"))\n\t\t\tg_hash_table_replace(devices, g_strdup_printf(\"%u\", instance), NULL);\n\n\t\tif (sipe_is_our_publication(sipe_private, key)) {\n\t\t\tstruct sipe_publication *publication = g_new0(struct sipe_publication, 1);\n\n\t\t\tpublication->category = g_strdup(name);\n\t\t\tpublication->instance  = instance;\n\t\t\tpublication->container = container;\n\t\t\tpublication->version   = version;\n\n\t\t\t/* filling publication->availability */\n\t\t\tif (sipe_strequal(name, \"state\")) {\n\t\t\t\tconst sipe_xml *xn_state = sipe_xml_child(node, \"state\");\n\t\t\t\tconst sipe_xml *xn_avail = sipe_xml_child(xn_state, \"availability\");\n\n\t\t\t\tif (xn_avail) {\n\t\t\t\t\tgchar *avail_str = sipe_xml_data(xn_avail);\n\t\t\t\t\tif (avail_str) {\n\t\t\t\t\t\tpublication->availability = atoi(avail_str);\n\t\t\t\t\t}\n\t\t\t\t\tg_free(avail_str);\n\t\t\t\t}\n\t\t\t\t/* for calendarState */\n\t\t\t\tif (xn_state && sipe_strequal(sipe_xml_attribute(xn_state, \"type\"), \"calendarState\")) {\n\t\t\t\t\tconst sipe_xml *xn_activity = sipe_xml_child(xn_state, \"activity\");\n\t\t\t\t\tstruct sipe_cal_event *event = g_new0(struct sipe_cal_event, 1);\n\n\t\t\t\t\tevent->start_time = sipe_utils_str_to_time(sipe_xml_attribute(xn_state, \"startTime\"));\n\t\t\t\t\tif (xn_activity) {\n\t\t\t\t\t\tif (sipe_strequal(sipe_xml_attribute(xn_activity, \"token\"),\n\t\t\t\t\t\t\t\t  sipe_status_activity_to_token(SIPE_ACTIVITY_IN_MEETING)))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tevent->is_meeting = TRUE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tevent->subject = sipe_xml_data(sipe_xml_child(xn_state, \"meetingSubject\"));\n\t\t\t\t\tevent->location = sipe_xml_data(sipe_xml_child(xn_state, \"meetingLocation\"));\n\n\t\t\t\t\tpublication->cal_event_hash = sipe_cal_event_hash(event);\n\t\t\t\t\tSIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: hash=%s\",\n\t\t\t\t\t\t\tpublication->cal_event_hash);\n\t\t\t\t\tsipe_cal_event_free(event);\n\t\t\t\t}\n\t\t\t}\n\t\t\t/* filling publication->note */\n\t\t\tif (sipe_strequal(name, \"note\")) {\n\t\t\t\tconst sipe_xml *xn_body = sipe_xml_child(node, \"note/body\");\n\n\t\t\t\tif (!has_note_cleaned) {\n\t\t\t\t\thas_note_cleaned = TRUE;\n\n\t\t\t\t\tg_free(sipe_private->note);\n\t\t\t\t\tsipe_private->note = NULL;\n\t\t\t\t\tsipe_private->note_since = publish_time;\n\n\t\t\t\t\tdo_update_status = TRUE;\n\t\t\t\t}\n\n\t\t\t\tg_free(publication->note);\n\t\t\t\tpublication->note = NULL;\n\t\t\t\tif (xn_body) {\n\t\t\t\t\tchar *tmp;\n\n\t\t\t\t\tpublication->note = g_markup_escape_text((tmp = sipe_xml_data(xn_body)), -1);\n\t\t\t\t\tg_free(tmp);\n\t\t\t\t\tif (publish_time >= sipe_private->note_since) {\n\t\t\t\t\t\tg_free(sipe_private->note);\n\t\t\t\t\t\tsipe_private->note = g_strdup(publication->note);\n\t\t\t\t\t\tsipe_private->note_since = publish_time;\n\t\t\t\t\t\tif (sipe_strequal(sipe_xml_attribute(xn_body, \"type\"), \"OOF\"))\n\t\t\t\t\t\t\tSIPE_CORE_PRIVATE_FLAG_SET(OOF_NOTE);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tSIPE_CORE_PRIVATE_FLAG_UNSET(OOF_NOTE);\n\n\t\t\t\t\t\tdo_update_status = TRUE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* filling publication->fb_start_str, free_busy_base64, working_hours_xml_str */\n\t\t\tif (sipe_strequal(name, \"calendarData\") && (publication->container == 300)) {\n\t\t\t\tconst sipe_xml *xn_free_busy = sipe_xml_child(node, \"calendarData/freeBusy\");\n\t\t\t\tconst sipe_xml *xn_working_hours = sipe_xml_child(node, \"calendarData/WorkingHours\");\n\t\t\t\tif (xn_free_busy) {\n\t\t\t\t\tpublication->fb_start_str = g_strdup(sipe_xml_attribute(xn_free_busy, \"startTime\"));\n\t\t\t\t\tpublication->free_busy_base64 = sipe_xml_data(xn_free_busy);\n\t\t\t\t}\n\t\t\t\tif (xn_working_hours) {\n\t\t\t\t\tpublication->working_hours_xml_str = sipe_xml_stringify(xn_working_hours);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!cat_publications) {\n\t\t\t\tcat_publications = g_hash_table_new_full(\n\t\t\t\t\t\t\tg_str_hash, g_str_equal,\n\t\t\t\t\t\t\tg_free,\t(GDestroyNotify)free_publication);\n\t\t\t\tg_hash_table_insert(sipe_private->our_publications, g_strdup(name), cat_publications);\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: added GHashTable cat=%s\", name);\n\t\t\t}\n\t\t\tg_hash_table_insert(cat_publications, g_strdup(key), publication);\n\t\t\tSIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: added key=%s version=%d\", key, version);\n\t\t}\n\t\tg_free(key);\n\n\t\t/* aggregateState (not an our publication) from 2-nd container */\n\t\tif (sipe_strequal(name, \"state\") && container == 2) {\n\t\t\tconst sipe_xml *xn_state = sipe_xml_child(node, \"state\");\n\t\t\tconst sipe_xml *xn_activity = sipe_xml_child(xn_state, \"activity\");\n\n\t\t\tif (xn_state && sipe_strequal(sipe_xml_attribute(xn_state, \"type\"), \"aggregateState\")) {\n\t\t\t\tconst sipe_xml *xn_avail = sipe_xml_child(xn_state, \"availability\");\n\n\t\t\t\tif (xn_avail) {\n\t\t\t\t\tgchar *avail_str = sipe_xml_data(xn_avail);\n\t\t\t\t\tif (avail_str) {\n\t\t\t\t\t\taggreg_avail = atoi(avail_str);\n\t\t\t\t\t}\n\t\t\t\t\tg_free(avail_str);\n\t\t\t\t}\n\n\t\t\t\tdo_update_status = TRUE;\n\t\t\t}\n\n\t\t\tif (xn_activity) {\n\t\t\t\tif (activity_token) {\n\t\t\t\t\tg_free(activity_token);\n\t\t\t\t}\n\t\t\t\tactivity_token = g_strdup(sipe_xml_attribute(xn_activity, \"token\"));\n\t\t\t}\n\t\t}\n\n\t\t/* userProperties published by server from AD */\n\t\tif (!sipe_private->csta &&\n\t\t    sipe_strequal(name, \"userProperties\")) {\n\t\t\tconst sipe_xml *line;\n\t\t\t/* line, for Remote Call Control (RCC) or external Lync/Communicator call */\n\t\t\tfor (line = sipe_xml_child(node, \"userProperties/lines/line\"); line; line = sipe_xml_twin(line)) {\n\t\t\t\tconst gchar *line_type = sipe_xml_attribute(line, \"lineType\");\n\t\t\t\tgchar *line_uri = sipe_xml_data(line);\n\t\t\t\tif (!line_uri) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (sipe_strequal(line_type, \"Rcc\") || sipe_strequal(line_type, \"Dual\")) {\n\t\t\t\t\tconst gchar *line_server = sipe_xml_attribute(line, \"lineServer\");\n\t\t\t\t\tif (line_server) {\n\t\t\t\t\t\tgchar *tmp = g_strstrip(line_uri);\n\t\t\t\t\t\tSIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: line_uri=%s server=%s\",\n\t\t\t\t\t\t\t\ttmp, line_server);\n\t\t\t\t\t\tsip_csta_open(sipe_private, tmp, line_server);\n\t\t\t\t\t}\n\t\t\t\t}\n#ifdef HAVE_VV\n\t\t\t\telse if (sipe_strequal(line_type, \"Uc\")) {\n\n\t\t\t\t\tif (!sipe_private->uc_line_uri) {\n\t\t\t\t\t\tsipe_private->uc_line_uri = g_strdup(g_strstrip(line_uri));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_ocs2007_process_roaming_self: \"\n\t\t\t\t\t\t\t\t\"sipe_private->uc_line_uri is already set.\");\n\t\t\t\t\t}\n\t\t\t\t}\n#endif\n\n\t\t\t\tg_free(line_uri);\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tSIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: sipe_private->our_publications size=%d\",\n\t\t\tsipe_private->our_publications ? (int) g_hash_table_size(sipe_private->our_publications) : -1);\n\n\t/* active clients for user account */\n\tif (g_hash_table_size(devices) == 0) {\n\t\t/* updated roaming information without device information - no need to update MPOP flag */\n\t} else if (g_hash_table_size(devices) > 1) {\n\t\tSIPE_CORE_PRIVATE_FLAG_SET(MPOP);\n\t\tSIPE_LOG_INFO(\"sipe_ocs2007_process_roaming_self: multiple clients detected (%d)\",\n\t\t\t      g_hash_table_size(devices));\n\t} else {\n\t\tSIPE_CORE_PRIVATE_FLAG_UNSET(MPOP);\n\t\tSIPE_LOG_INFO_NOFORMAT(\"sipe_ocs2007_process_roaming_self: single client detected\");\n\t}\n\tg_hash_table_destroy(devices);\n\n\t/* containers */\n\tfor (node = sipe_xml_child(xml, \"containers/container\"); node; node = sipe_xml_twin(node)) {\n\t\tguint id = sipe_xml_int_attribute(node, \"id\", 0);\n\t\tstruct sipe_container *container = sipe_find_container(sipe_private, id);\n\n\t\tif (container) {\n\t\t\tsipe_private->containers = g_slist_remove(sipe_private->containers, container);\n\t\t\tSIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: removed existing container id=%d v%d\", container->id, container->version);\n\t\t\tsipe_ocs2007_free_container(container);\n\t\t}\n\t\tcontainer = g_new0(struct sipe_container, 1);\n\t\tcontainer->id = id;\n\t\tcontainer->version = sipe_xml_int_attribute(node, \"version\", 0);\n\t\tsipe_private->containers = g_slist_append(sipe_private->containers, container);\n\t\tSIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: added container id=%d v%d\", container->id, container->version);\n\n\t\tfor (node2 = sipe_xml_child(node, \"member\"); node2; node2 = sipe_xml_twin(node2)) {\n\t\t\tstruct sipe_container_member *member = g_new0(struct sipe_container_member, 1);\n\t\t\tmember->type = g_strdup(sipe_xml_attribute(node2, \"type\"));\n\t\t\tmember->value = g_strdup(sipe_xml_attribute(node2, \"value\"));\n\t\t\tcontainer->members = g_slist_append(container->members, member);\n\t\t\tSIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: added container member type=%s value=%s\",\n\t\t\t\t\tmember->type, member->value ? member->value : \"\");\n\t\t}\n\t}\n\n\tSIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: access_level_set=%s\",\n\t\t\tSIPE_CORE_PRIVATE_FLAG_IS(ACCESS_LEVEL_SET) ? \"TRUE\" : \"FALSE\");\n\tif (!SIPE_CORE_PRIVATE_FLAG_IS(ACCESS_LEVEL_SET) && sipe_xml_child(xml, \"containers\")) {\n\t\tchar *container_xmls = NULL;\n\t\tint sameEnterpriseAL = sipe_ocs2007_find_access_level(sipe_private, \"sameEnterprise\", NULL, NULL);\n\t\tint federatedAL      = sipe_ocs2007_find_access_level(sipe_private, \"federated\", NULL, NULL);\n\n\t\tSIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: sameEnterpriseAL=%d\", sameEnterpriseAL);\n\t\tSIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: federatedAL=%d\", federatedAL);\n\t\t/* initial set-up to let counterparties see your status */\n\t\tif (sameEnterpriseAL < 0) {\n\t\t\tstruct sipe_container *container = sipe_find_container(sipe_private, 200);\n\t\t\tguint version = container ? container->version : 0;\n\t\t\tsipe_send_container_members_prepare(200, version, \"add\", \"sameEnterprise\", NULL, &container_xmls);\n\t\t}\n\t\tif (federatedAL < 0) {\n\t\t\tstruct sipe_container *container = sipe_find_container(sipe_private, 100);\n\t\t\tguint version = container ? container->version : 0;\n\t\t\tsipe_send_container_members_prepare(100, version, \"add\", \"federated\", NULL, &container_xmls);\n\t\t}\n\t\tSIPE_CORE_PRIVATE_FLAG_SET(ACCESS_LEVEL_SET);\n\n\t\tif (container_xmls) {\n\t\t\tsipe_send_set_container_members(sipe_private, container_xmls);\n\t\t}\n\t\tg_free(container_xmls);\n\t}\n\n\t/* Refresh contacts' blocked status */\n\tsipe_refresh_blocked_status(sipe_private);\n\n\t/* subscribers */\n\tfor (node = sipe_xml_child(xml, \"subscribers/subscriber\"); node; node = sipe_xml_twin(node)) {\n\t\tconst char *user;\n\t\tconst char *acknowledged;\n\t\tgchar *hdr;\n\t\tgchar *body;\n\n\t\tuser = sipe_xml_attribute(node, \"user\"); /* without 'sip:' prefix */\n\t\tif (!user) continue;\n\t\tSIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: user %s\", user);\n\t\tdisplay_name = g_strdup(sipe_xml_attribute(node, \"displayName\"));\n\t\turi = sip_uri_from_name(user);\n\n\t\tsipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_DISPLAY_NAME, display_name);\n\t\tsipe_backend_buddy_refresh_properties(SIPE_CORE_PUBLIC, uri);\n\n\t        acknowledged= sipe_xml_attribute(node, \"acknowledged\");\n\t\tif(sipe_strcase_equal(acknowledged,\"false\")){\n                        SIPE_DEBUG_INFO(\"sipe_ocs2007_process_roaming_self: user added you %s\", user);\n\t\t\tif (!sipe_backend_buddy_find(SIPE_CORE_PUBLIC, uri, NULL)) {\n\t\t\t\tsipe_backend_buddy_request_add(SIPE_CORE_PUBLIC, uri, display_name);\n\t\t\t}\n\n\t\t        hdr = g_strdup_printf(\n\t\t\t\t      \"Contact: %s\\r\\n\"\n\t\t\t\t      \"Content-Type: application/msrtc-presence-setsubscriber+xml\\r\\n\", contact);\n\n\t\t        body = g_strdup_printf(\n\t\t\t\t       \"<setSubscribers xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/presence-subscribers\\\">\"\n\t\t\t\t       \"<subscriber user=\\\"%s\\\" acknowledged=\\\"true\\\"/>\"\n\t\t\t\t       \"</setSubscribers>\", user);\n\n\t\t        sip_transport_service(sipe_private,\n\t\t\t\t\t      to,\n\t\t\t\t\t      hdr,\n\t\t\t\t\t      body,\n\t\t\t\t\t      NULL);\n\t\t        g_free(body);\n\t\t        g_free(hdr);\n                }\n\t\tg_free(display_name);\n\t\tg_free(uri);\n\t}\n\n\tg_free(contact);\n\tsipe_xml_free(xml);\n\n\t/* Publish initial state if not yet.\n\t * Assuming this happens on initial responce to subscription to roaming-self\n\t * so we've already updated our roaming data in full.\n\t * Only for 2007+\n\t */\n\tif (!SIPE_CORE_PRIVATE_FLAG_IS(INITIAL_PUBLISH)) {\n\t\tsend_publish_category_initial(sipe_private);\n\t\tSIPE_CORE_PRIVATE_FLAG_SET(INITIAL_PUBLISH);\n\t\t/* dalayed run */\n\t\tsipe_cal_delayed_calendar_update(sipe_private);\n\t\tdo_update_status = FALSE;\n\t} else if (aggreg_avail) {\n\n\t\tif (aggreg_avail &&\n\t\t    (aggreg_avail < SIPE_OCS2007_LEGACY_AVAILIBILITY_OFFLINE)) {\n\t\t\t/* not offline */\n\t\t\tsipe_status_set_token(sipe_private,\n\t\t\t\t\t      sipe_ocs2007_status_from_legacy_availability(aggreg_avail, activity_token));\n\t\t} else {\n\t\t\t/* do not let offline status switch us off */\n\t\t\tsipe_status_set_activity(sipe_private,\n\t\t\t\t\t\t SIPE_ACTIVITY_INVISIBLE);\n\t\t}\n\t}\n\n\tif (do_update_status) {\n\t\tsipe_status_and_note(sipe_private, NULL);\n\t}\n\n\tg_free(to);\n\tg_free(activity_token);\n}\n\n/**\n * for Access levels menu\n */\n#define INDENT_FMT\t\t\t\"  %s\"\n\n/**\n * Member is indirectly belong to access level container.\n * For example 'sameEnterprise' is in the container and user\n * belongs to that same enterprise.\n */\n#define INDENT_MARKED_INHERITED_FMT\t\"= %s\"\n\nstatic struct sipe_backend_buddy_menu *access_levels_menu(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t\t  struct sipe_backend_buddy_menu *menu,\n\t\t\t\t\t\t\t  const gchar *member_type,\n\t\t\t\t\t\t\t  const gchar *member_value,\n\t\t\t\t\t\t\t  const gboolean extra_menu)\n{\n\tunsigned int i;\n\tgboolean is_group_access = FALSE;\n\tint container_id;\n\n\tif (!menu)\n\t\tmenu = sipe_backend_buddy_menu_start(SIPE_CORE_PUBLIC);\n\n\tcontainer_id = sipe_ocs2007_find_access_level(sipe_private,\n\t\t\t\t\t\t      member_type,\n\t\t\t\t\t\t      member_value,\n\t\t\t\t\t\t      &is_group_access);\n\n\tfor (i = 1; i <= CONTAINERS_LEN; i++) {\n\t\t/*\n\t\t * Blocked should remain in the first place\n\t\t * in the containers[] array.\n\t\t */\n\t\tunsigned int j  = (i == CONTAINERS_LEN) ? 0 : i;\n\t\tint container_j = containers[j];\n\t\tconst gchar *acc_level_name = sipe_ocs2007_access_level_name(container_j);\n\t\tstruct sipe_container *container = create_container(j,\n\t\t\t\t\t\t\t\t    member_type,\n\t\t\t\t\t\t\t\t    member_value,\n\t\t\t\t\t\t\t\t    FALSE);\n\t\tgchar *label;\n\n\t\t/* libpurple memory leak workaround */\n\t\tblist_menu_remember_container(sipe_private, container);\n\n\t\t/* current container/access level */\n\t\tif (container_j == container_id) {\n\t\t\tlabel = is_group_access ?\n\t\t\t\tg_strdup_printf(INDENT_MARKED_INHERITED_FMT, acc_level_name) :\n\t\t\t\tg_strdup_printf(SIPE_OCS2007_INDENT_MARKED_FMT, acc_level_name);\n\t\t} else {\n\t\t\tlabel = g_strdup_printf(INDENT_FMT, acc_level_name);\n\t\t}\n\n\t\tmenu = sipe_backend_buddy_menu_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t   menu,\n\t\t\t\t\t\t   label,\n\t\t\t\t\t\t   SIPE_BUDDY_MENU_CHANGE_ACCESS_LEVEL,\n\t\t\t\t\t\t   container);\n\t\tg_free(label);\n\t}\n\n\tif (extra_menu && (container_id >= 0) && !is_group_access) {\n\t\tstruct sipe_container *container = create_container(0,\n\t\t\t\t\t\t\t\t\t    member_type,\n\t\t\t\t\t\t\t\t\t    member_value,\n\t\t\t\t\t\t\t\t\t    TRUE);\n\t\tgchar *label;\n\n\t\t/* separator */\n\t\tmenu = sipe_backend_buddy_menu_separator(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t menu,\n\t\t\t\t\t\t\t \"  --------------\");\n\n\n\t\t/* libpurple memory leak workaround */\n\t\tblist_menu_remember_container(sipe_private, container);\n\n\t\t/* Translators: remove (clear) previously assigned access level */\n\t\tlabel = g_strdup_printf(INDENT_FMT, _(\"Unspecify\"));\n\t\tmenu = sipe_backend_buddy_menu_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t   menu,\n\t\t\t\t\t\t   label,\n\t\t\t\t\t\t   SIPE_BUDDY_MENU_CHANGE_ACCESS_LEVEL,\n\t\t\t\t\t\t   container);\n\t\tg_free(label);\n\t}\n\n\treturn(menu);\n}\n\nstatic struct sipe_backend_buddy_menu *access_groups_menu(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_backend_buddy_menu *menu = sipe_backend_buddy_menu_start(SIPE_CORE_PUBLIC);\n\tGSList *access_domains, *entry;\n\n\tmenu = sipe_backend_buddy_sub_menu_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t       menu,\n\t\t\t\t\t       _(\"People in my company\"),\n\t\t\t\t\t       access_levels_menu(sipe_private,\n\t\t\t\t\t\t\t\t  NULL,\n\t\t\t\t\t\t\t\t  \"sameEnterprise\",\n\t\t\t\t\t\t\t\t  NULL,\n\t\t\t\t\t\t\t\t  FALSE));\n\n\t/* this is original name, don't edit */\n\tmenu = sipe_backend_buddy_sub_menu_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t       menu,\n\t\t\t\t\t       _(\"People in domains connected with my company\"),\n\t\t\t\t\t       access_levels_menu(sipe_private,\n\t\t\t\t\t\t\t\t  NULL,\n\t\t\t\t\t\t\t\t  \"federated\",\n\t\t\t\t\t\t\t\t  NULL,\n\t\t\t\t\t\t\t\t  FALSE));\n\n\tmenu = sipe_backend_buddy_sub_menu_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t       menu,\n\t\t\t\t\t       _(\"People in public domains\"),\n\t\t\t\t\t       access_levels_menu(sipe_private,\n\t\t\t\t\t\t\t\t  NULL,\n\t\t\t\t\t\t\t\t  \"publicCloud\",\n\t\t\t\t\t\t\t\t  NULL,\n\t\t\t\t\t\t\t\t  TRUE));\n\n\tentry = access_domains = get_access_domains(sipe_private);\n\twhile (entry) {\n\t\tgchar *domain    = entry->data;\n\t\tgchar *menu_name = g_strdup_printf(_(\"People at %s\"), domain);\n\n\t\t/* takes over ownership of entry->data (= domain) */\n\t\tmenu = sipe_backend_buddy_sub_menu_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t       menu,\n\t\t\t\t\t\t       menu_name,\n\t\t\t\t\t\t       access_levels_menu(sipe_private,\n\t\t\t\t\t\t\t\t\t  NULL,\n\t\t\t\t\t\t\t\t\t  \"domain\",\n\t\t\t\t\t\t\t\t\t  domain,\n\t\t\t\t\t\t\t\t\t  TRUE));\n\t\tg_free(menu_name);\n\n\t\tentry = entry->next;\n\t}\n\tg_slist_free(access_domains);\n\n\t/* separator */\n\t/*\t\t\t                  People in domains connected with my company */\n\tmenu = sipe_backend_buddy_menu_separator(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t menu,\n\t\t\t\t\t\t \"-------------------------------------------\");\n\n\tmenu = sipe_backend_buddy_menu_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t   menu,\n\t\t\t\t\t   _(\"Add new domain...\"),\n\t\t\t\t\t   SIPE_BUDDY_MENU_ADD_NEW_DOMAIN,\n\t\t\t\t\t   NULL);\n\n\treturn(menu);\n}\n\nstruct sipe_backend_buddy_menu *sipe_ocs2007_access_control_menu(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t\t\t const gchar *buddy_name)\n{\n\tstruct sipe_backend_buddy_menu *menu = sipe_backend_buddy_menu_start(SIPE_CORE_PUBLIC);\n\tgchar *label;\n\n\t/*\n\t * Workaround for missing libpurple API to release resources allocated\n\t * during blist_node_menu() callback. See also:\n\t *\n\t *   <http://developer.pidgin.im/ticket/12597>\n\t *\n\t * We remember all memory blocks in a list and deallocate them when\n\t *\n\t *   - the next time we enter the callback, or\n\t *   - the account is disconnected\n\t *\n\t * That means that after the buddy menu has been closed we have unused\n\t * resources but at least we don't leak them anymore...\n\t */\n\tsipe_core_buddy_menu_free(SIPE_CORE_PUBLIC);\n\n\tlabel = g_strdup_printf(INDENT_FMT, _(\"Online help...\"));\n\tmenu = sipe_backend_buddy_menu_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t   menu,\n\t\t\t\t\t   label,\n\t\t\t\t\t   SIPE_BUDDY_MENU_ACCESS_LEVEL_HELP,\n\t\t\t\t\t   NULL);\n\tg_free(label);\n\n\tlabel = g_strdup_printf(INDENT_FMT, _(\"Access groups\"));\n\tmenu = sipe_backend_buddy_sub_menu_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t       menu,\n\t\t\t\t\t       label,\n\t\t\t\t\t       access_groups_menu(sipe_private));\n\tg_free(label);\n\n\tmenu = access_levels_menu(sipe_private,\n\t\t\t\t  menu,\n\t\t\t\t  \"user\",\n\t\t\t\t  sipe_get_no_sip_uri(buddy_name),\n\t\t\t\t  TRUE);\n\n\treturn(menu);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-ocs2007.h",
    "content": "/**\n * @file sipe-ocs2007.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2015 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipmsg;\nstruct sipe_container;\nstruct sipe_core_private;\n\n/**\n * Member is directly placed to access level container.\n * For example SIP URI of user is in the container.\n */\n#define SIPE_OCS2007_INDENT_MARKED_FMT\t\t\"* %s\"\n\n/**\n * OCS2007 status ID, availability & activity\n */\nguint sipe_ocs2007_availability_from_status(const gchar *sipe_status_id,\n\t\t\t\t\t    const gchar **activity_token);\nconst gchar *sipe_ocs2007_status_from_legacy_availability(guint availability,\n\t\t\t\t\t\t\t  const gchar *activity);\nconst gchar *sipe_ocs2007_legacy_activity_description(guint availability);\ngboolean sipe_ocs2007_status_is_busy(const gchar *status_id);\ngboolean sipe_ocs2007_availability_is_away(guint availability);\n\n/**\n * Publish status (OCS2007+)\n */\nvoid sipe_ocs2007_presence_publish(struct sipe_core_private *sipe_private,\n\t\t\t\t   gpointer unused);\nvoid sipe_ocs2007_free(struct sipe_core_private *sipe_private);\nvoid sipe_ocs2007_category_publish(struct sipe_core_private *sipe_private,\n\t\t\t\t   gboolean force_publish);\nvoid sipe_ocs2007_phone_state_publish(struct sipe_core_private *sipe_private);\nvoid sipe_ocs2007_reset_status(struct sipe_core_private *sipe_private);\nvoid sipe_ocs2007_process_roaming_self(struct sipe_core_private *sipe_private,\n\t\t\t\t       struct sipmsg *msg);\n\n/**\n * OCS2007 Access Levels\n */\nconst gchar *sipe_ocs2007_access_level_name(guint id);\nint sipe_ocs2007_find_access_level(struct sipe_core_private *sipe_private,\n\t\t\t\t   const gchar *type,\n\t\t\t\t   const gchar *value,\n\t\t\t\t   gboolean *is_group_access);\nvoid sipe_ocs2007_change_access_level(struct sipe_core_private *sipe_private,\n\t\t\t\t      const int container_id,\n\t\t\t\t      const gchar *type,\n\t\t\t\t      const gchar *value);\n\n/* buddy menu */\nstruct sipe_backend_buddy_menu *sipe_ocs2007_access_control_menu(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t\t\t const gchar *buddy_name);\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-rtf-tests.c",
    "content": "/**\n * @file sipe-rtf-tests.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n * Tests for sipe-rtf.c\n */\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-rtf.h\"\n\nvoid sipe_backend_debug_literal(sipe_debug_level level,\n\t\t\t\tconst gchar *msg)\n{\n\tprintf(\"DEBUG %d: %s\", level, msg);\n}\nvoid sipe_backend_debug(sipe_debug_level level,\n\t\t\tconst gchar *format,\n\t\t\t...)\n{\n\tva_list args;\n\tgchar *msg;\n\tva_start(args, format);\n\tmsg = g_strdup_vprintf(format, args);\n\tva_end(args);\n\n\tsipe_backend_debug_literal(level, msg);\n\tg_free(msg);\n}\n\nstatic const struct test_data {\n  const gchar *input;\n  const gchar *expected;\n} tests[] = {\n\t{\n\t\t\"{\\\\rtf1\\\\fbidis\\\\ansi\\\\ansicpg1252\\\\deff0\\\\nouicompat\\\\deflang1033{\\\\fonttbl{\\\\f0\\\\fnil\\\\fcharset0 Segoe UI;}{\\\\f1\\\\fswiss\\\\fcharset177 Arial;}{\\\\f2\\\\fnil Segoe UI;}}{\\\\colortbl ;\\\\red0\\\\green0\\\\blue0;}{\\\\*\\\\generator Riched20 15.0.4420}{\\\\*\\\\mmathPr\\\\mwrapIndent1440 }\\\\viewkind4\\\\uc1\\\\pard\\\\ltrpar\\\\cf1\\\\outl\\\\f0\\\\fs20\\\\u8235?\\\\f1\\\\par\\n\"\n\t\t\"\\\\par\\n\"\n\t\t\"Enter 0 For SAP, ... issues \\\\par\\n\"\n\t\t\"\\\\par\\n\"\n\t\t\"For all non-SAP issues, select your preferred language:\\\\par\\n\"\n\t\t\"1 English\\\\par\\n\"\n\t\t\"2 Deutsch\\\\par\\n\"\n\t\t\"...\\\\par\\n\"\n\t\t\"11 for all other languages\\\\par\\n\"\n\t\t\"\\\\outl0\\\\f2\\\\ltrch\\\\lang1033\\\\par{\\\\*\\\\lyncflags rtf=1}}\\n\",\n\t\t// \\u8235 == U+202B == UTF-8 0xE2 0x80 0xAB (RIGHT-TO-LEFT EMBEDDING)\n\t\t\"\\xE2\\x80\\xAB<br/><br/>Enter 0 For SAP, ... issues <br/><br/>\"\n\t\t\"For all non-SAP issues, select your preferred language:<br/>\"\n\t\t\"1 English<br/>\"\n\t\t\"2 Deutsch<br/>\"\n\t\t\"...<br/>\"\n\t\t\"11 for all other languages<br/><br/>\",\n\t},\n\t{\n\t\t\"{\\\\rtf1\\\\ansi\\\\deff3\\\\adeflang1025\\n\"\n\t\t\"{\\\\fonttbl{\\\\f0\\\\froman\\\\fprq2\\\\fcharset0 Times New Roman;}{\\\\f1\\\\froman\\\\fprq2\\\\fcharset2 Symbol;}{\\\\f2\\\\fswiss\\\\fprq2\\\\fcharset0 Arial;}{\\\\f3\\\\froman\\\\fprq2\\\\fcharset0 Liberation Serif{\\\\*\\\\falt Times New Roman};}{\\\\f4\\\\fswiss\\\\fprq2\\\\fcharset0 Liberation Sans{\\\\*\\\\falt Arial};}{\\\\f5\\\\fnil\\\\fprq2\\\\fcharset0 Noto Sans CJK SC Regular;}{\\\\f6\\\\fnil\\\\fprq2\\\\fcharset0 Lohit Devanagari;}{\\\\f7\\\\fnil\\\\fprq0\\\\fcharset128 Lohit Devanagari;}}\\n\"\n\t\t\"{\\\\colortbl;\\\\red0\\\\green0\\\\blue0;\\\\red0\\\\green0\\\\blue255;\\\\red0\\\\green255\\\\blue255;\\\\red0\\\\green255\\\\blue0;\\\\red255\\\\green0\\\\blue255;\\\\red255\\\\green0\\\\blue0;\\\\red255\\\\green255\\\\blue0;\\\\red255\\\\green255\\\\blue255;\\\\red0\\\\green0\\\\blue128;\\\\red0\\\\green128\\\\blue128;\\\\red0\\\\green128\\\\blue0;\\\\red128\\\\green0\\\\blue128;\\\\red128\\\\green0\\\\blue0;\\\\red128\\\\green128\\\\blue0;\\\\red128\\\\green128\\\\blue128;\\\\red192\\\\green192\\\\blue192;}\\n\"\n\t\t\"{\\\\stylesheet{\\\\s0\\\\snext0\\\\widctlpar\\\\hyphpar0\\\\cf0\\\\kerning1\\\\dbch\\\\af8\\\\langfe2052\\\\dbch\\\\af6\\\\afs24\\\\alang1081\\\\loch\\\\f3\\\\hich\\\\af3\\\\fs24\\\\lang1033 Normal;}\\n\"\n\t\t\"{\\\\s15\\\\sbasedon0\\\\snext16\\\\sb240\\\\sa120\\\\keepn\\\\dbch\\\\af5\\\\dbch\\\\af6\\\\afs28\\\\loch\\\\f4\\\\fs28 Heading;}\\n\"\n\t\t\"{\\\\s16\\\\sbasedon0\\\\snext16\\\\sl276\\\\slmult1\\\\sb0\\\\sa140 Text Body;}\\n\"\n\t\t\"{\\\\s17\\\\sbasedon16\\\\snext17\\\\sl276\\\\slmult1\\\\sb0\\\\sa140\\\\dbch\\\\af7 List;}\\n\"\n\t\t\"{\\\\s18\\\\sbasedon0\\\\snext18\\\\sb120\\\\sa120\\\\noline\\\\i\\\\dbch\\\\af7\\\\afs24\\\\ai\\\\fs24 Caption;}\\n\"\n\t\t\"{\\\\s19\\\\sbasedon0\\\\snext19\\\\noline\\\\dbch\\\\af7 Index;}\\n\"\n\t\t\"}{\\\\*\\\\generator LibreOffice/6.1.2.1$Linux_X86_64 LibreOffice_project/10$Build-1}{\\\\info{\\\\creatim\\\\yr2018\\\\mo12\\\\dy10\\\\hr8\\\\min25}{\\\\revtim\\\\yr2018\\\\mo12\\\\dy10\\\\hr8\\\\min26}{\\\\printim\\\\yr0\\\\mo0\\\\dy0\\\\hr0\\\\min0}}{\\\\*\\\\userprops}\\\\deftab709\\n\"\n\t\t\"\\\\viewscale100\\n\"\n\t\t\"{\\\\*\\\\pgdsctbl\\n\"\n\t\t\"{\\\\pgdsc0\\\\pgdscuse451\\\\pgwsxn12240\\\\pghsxn15840\\\\marglsxn1134\\\\margrsxn1134\\\\margtsxn1134\\\\margbsxn1134\\\\pgdscnxt0 Default Style;}}\\n\"\n\t\t\"\\\\formshade\\\\paperh15840\\\\paperw12240\\\\margl1134\\\\margr1134\\\\margt1134\\\\margb1134\\\\sectd\\\\sbknone\\\\sectunlocked1\\\\pgndec\\\\pgwsxn12240\\\\pghsxn15840\\\\marglsxn1134\\\\margrsxn1134\\\\margtsxn1134\\\\margbsxn1134\\\\ftnbj\\\\ftnstart1\\\\ftnrstcont\\\\ftnnar\\\\aenddoc\\\\aftnrstcont\\\\aftnstart1\\\\aftnnrlc\\n\"\n\t\t\"{\\\\*\\\\ftnsep\\\\chftnsep}\\\\pgndec\\\\pard\\\\plain \\\\s0\\\\widctlpar\\\\hyphpar0\\\\cf0\\\\kerning1\\\\dbch\\\\af8\\\\langfe2052\\\\dbch\\\\af6\\\\afs24\\\\alang1081\\\\loch\\\\f3\\\\hich\\\\af3\\\\fs24\\\\lang1033{\\\\rtlch \\\\ltrch\\\\loch\\n\"\n\t\t\"\\\\\\\\\\\\{The quick brown fox jumped over jumps over the lazy dog\\\\\\\\\\\\}}\\n\"\n\t\t\"\\\\par \\\\pard\\\\plain \\\\s0\\\\widctlpar\\\\hyphpar0\\\\cf0\\\\kerning1\\\\dbch\\\\af8\\\\langfe2052\\\\dbch\\\\af6\\\\afs24\\\\alang1081\\\\loch\\\\f3\\\\hich\\\\af3\\\\fs24\\\\lang1033\\\\rtlch \\\\ltrch\\\\loch\\n\"\n\t\t\"\\n\"\n\t\t\"\\\\par }\\n\",\n\t\t\"\\\\{The quick brown fox jumped over jumps over the lazy dog\\\\}<br/><br/>\",\n\t},\n\t{\n\t\t\"{\\\\u228\\\\'e4\\\\u246\\\\'f6\\\\u252\\\\'fc\\\\u196\\\\'c4\\\\u214\\\\'d6\\\\u220\\\\'dc\\\\u229\\\\'e5\\\\u197\\\\'c5\\\\u8364\\\\'80\\\\u163\\\\'a3$}\",\n\t\t\"äöüÄÖÜåÅ€£$\",\n\t},\n\t{\n\t\t\"{\\\\u256\\\\'3f\\\\u512\\\\'3f\\\\u999\\\\'3f\\\\u1000\\\\'3f}{\\\\cf0\\\\kerning1\\\\dbch\\\\af5\\\\langfe1033\\\\dbch\\\\af5\\\\rtlch \\\\ltrch\\\\loch\\\\fs24\\\\lang1033\\\\loch\\\\f5\\\\hich\\\\af5\\n\"\n\t\t\"\\\\uc2 \\\\u9839\\\\'81\\\\'f2\\\\uc1 }{\\\\cf0\\\\kerning1\\\\dbch\\\\af6\\\\langfe1033\\\\dbch\\\\af6\\\\rtlch \\\\ltrch\\\\loch\\\\fs24\\\\lang1033\\\\loch\\\\f5\\\\hich\\\\af5\\n\"\n\t\t\"\\\\u11360\\\\'3f}\",\n\t\t\"ĀȀϧϨ♯Ⱡ\",\n\t},\n\t{\n\t\tNULL,\n\t\tNULL,\n\t},\n};\n\nint main(SIPE_UNUSED_PARAMETER int argc,\n\t SIPE_UNUSED_PARAMETER char *argv[])\n{\n\tguint succeeded           = 0;\n\tguint failed              = 0;\n\tconst struct test_data *t = tests;\n\n\tfor (; t->input; t++) {\n\t\tchar *html = sipe_rtf_to_html(t->input);\n\n\t\tif (strcmp(html, t->expected) == 0) {\n\t\t\tsucceeded++;\n\t\t} else {\n\t\t\tprintf(\"FAILED: %s\\n        %s\\n\",\n\t\t\t       html, t->expected);\n\t\t\tfailed++;\n\t\t}\n\n\t\tg_free(html);\n\t}\n\n\tprintf(\"Result: %d PASSED %d FAILED\\n\", succeeded, failed);\n\treturn(failed);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-rtf.h",
    "content": "/**\n * @file sipe-rtf.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * Simple parser to extract plain text from RTF and transform it to HTML\n */\n\n/*\n * Interface dependencies:\n *\n * <glib.h>\n */\n\n/**\n * Extract plain text from RTF and transform it to HTML\n *\n * @param rtf pointer to RTF text\n * @return    string with HTML. Must be g_free()'d.\n */\ngchar *sipe_rtf_to_html(const gchar *rtf);\n"
  },
  {
    "path": "src/core/sipe-rtf.l",
    "content": "/************************ tell Emacs this is a -*-C-*- file *************\n * @file sipe-rtf.l\n *\n * pidgin-sipe\n *\n * Copyright (C) 2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * Simple parser to extract plain text from RTF and transform it to HTML\n */\n\n/* generated module */\n%option outfile=\"sipe-rtf.c\"\n%option prefix=\"sipe_rtf_lexer_\"\n\n/* flex configuration options */\n%option 8bit\n%option bison-bridge\n%option full\n%option nodefault\n%option noinput\n%option nointeractive\n%option pointer\n%option reentrant\n%option nounput\n%option warn\n%option noyyalloc\n%option noyyfree\n%option noyyrealloc\n%option noyywrap\n\n%{\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-rtf.h\"\n\n/*\n * small string buffer to avoid memory allocations\n *\n * Must be length of longest interesting keyword + 1\n * Currently that would be \"par\"\n */\n#define SIPE_RTF_LEXER_KEYWORD_SIZE 3 + 1 + 1\n\n/* lexer token value type */\nstruct parser_lval_type {\n\tguint number;\n\tgchar keyword_buffer[SIPE_RTF_LEXER_KEYWORD_SIZE];\n};\n#define YYSTYPE struct parser_lval_type\n\n/* lexer tokens */\n#define KEYWORD           256\n#define KEYWORD_PARAMETER 257\n#define KEYWORD_END       258\n#define LEXER_ERROR       259\n\n/* parser state */\nstruct parser_state {\n\tGString                 *text;\n\tguint                    unicode_ignore_length;\n\tguint                    ignore;\n\tstruct parser_lval_type  lval;\n};\n\nstatic void sipe_rtf_add_char(struct parser_state *state, gchar c);\nstatic void sipe_rtf_add_text(struct parser_state *state, const gchar *text);\nstatic void sipe_rtf_add_unichar(struct parser_state *state, gunichar c);\n%}\n\nDIGIT  [0-9]\nHEX    [0-9a-fA-F]\nLETTER [a-zA-Z]\n\n%x RTF_KEYWORD\n\n%%\n                      /* stuff that we simply throw away   */\n[\\r\\n]+               /* line endings                      */\n\"{\"\\\\\\*[^}]*\"}\"       /* comments                          */\n                      /* font definitions                  */\n\"{\"\\\\f{DIGIT}+\\\\[^;]+;\"}\"\n\"{\"                   /* section start                     */\n\"}\"                   /* section end                       */\n\n                      /* pass plain text to output buffer  */\n                      /* escaped special characters        */\n\\\\\\\\                  { sipe_rtf_add_char(yyextra, '\\\\'); }\n\\\\\"{\"                 { sipe_rtf_add_char(yyextra, '{');  }\n\\\\\"}\"                 { sipe_rtf_add_char(yyextra, '}');  }\n\\\\\\'{HEX}{2}          { /* 2 digit hex to 8-bit character  */\n                        unsigned int c;\n                        sscanf(yytext + 2, \"%x\", &c);\n                        sipe_rtf_add_char(yyextra, c);\n                      }\n\\\\u{DIGIT}+           { /* Unicode character               */\n                        gunichar c;\n                        sscanf(yytext + 2, \"%d\", &c);\n                        sipe_rtf_add_unichar(yyextra, c);\n                      }\n                      /* all other plain text              */\n[^{}\\\\\\n\\r]+          { sipe_rtf_add_text(yyextra, yytext); }\n\n                      /* stuff passed to parser for further processing */\n\\\\{LETTER}+           {\n                        BEGIN(RTF_KEYWORD);\n                        g_strlcpy(yylval->keyword_buffer,\n                                  yytext + 1,\n                                  SIPE_RTF_LEXER_KEYWORD_SIZE);\n                        return(KEYWORD);\n                      }\n<RTF_KEYWORD>{DIGIT}+     {\n                        sscanf(yytext, \"%d\", &yylval->number);\n                        return(KEYWORD_PARAMETER);\n                      }\n<RTF_KEYWORD>(;|[^0-9][^;\\\\]*;|[ ])? {\n                        /* reset <keyword start condition and throw away */\n                        BEGIN(INITIAL);\n                        return(KEYWORD_END);\n                      }\n<RTF_KEYWORD>.|\\n     { /* reset <RTF_KEYWORD> start condition */\n                        BEGIN(INITIAL);\n                        yyless(0);\n                        return(KEYWORD_END);\n                      }\n\n                      /* indicate anything else as error to parser */\n<INITIAL,RTF_KEYWORD>.|\\n {\n                        return(LEXER_ERROR);\n                      }\n%%\n\n/* memory allocation for flex code */\nvoid *sipe_rtf_lexer_alloc(yy_size_t size,\n\t\t\t   SIPE_UNUSED_PARAMETER yyscan_t yyscanner)\n{\n\treturn g_malloc(size);\n}\n\nvoid *sipe_rtf_lexer_realloc(void *ptr, yy_size_t size,\n\t\t\t     SIPE_UNUSED_PARAMETER yyscan_t yyscanner)\n{\n\treturn g_realloc(ptr, size);\n}\n\nvoid sipe_rtf_lexer_free(void *ptr,\n\t\t\t SIPE_UNUSED_PARAMETER yyscan_t yyscanner)\n{\n\tg_free(ptr);\n}\n\n/* add text to buffer */\nstatic void sipe_rtf_add_char(struct parser_state *state, gchar c)\n{\n  /* ignored characters after unicode sequence */\n  if (state->ignore) {\n    state->ignore--;\n  } else {\n    g_string_append_c(state->text, c);\n  }\n}\n\nstatic void sipe_rtf_add_text(struct parser_state *state, const gchar *text)\n{\n  /* ignored characters after unicode sequence */\n  if (state->ignore) {\n    while (*text && state->ignore--) text++;\n  }\n  if (!*text)\n    return;\n\n  /* add the remainder to the text buffer */\n  g_string_append(state->text, text);\n}\n\nstatic void sipe_rtf_add_unichar(struct parser_state *state, gunichar c)\n{\n  /* ignored characters after unicode sequence */\n  state->ignore = state->unicode_ignore_length;\n\n  g_string_append_unichar(state->text, c);\n}\n\nstatic void sipe_rtf_parse_keyword(struct parser_state *state,\n\t\t\t\t   const gchar *keyword) {\n\tif (strcmp(keyword, \"par\") == 0) {\n\t\tsipe_rtf_add_text(state, \"<br/>\");\n\t}\n}\n\nstatic void sipe_rtf_parse_keyword_parameter(struct parser_state *state,\n\t\t\t\t\t     const gchar *keyword,\n\t\t\t\t\t     unsigned int parameter) {\n\tif (strcmp(keyword, \"uc\") == 0) {\n\t\tstate->unicode_ignore_length = parameter;\n\t}\n}\n\n/****************************************************************************\n *\n * RTF parser\n *\n * based on Bison parser\n *\n * %output  \"sipe-rtf-parser.c\"\n * %defines \"sipe-rtf-parser.h\"\n *\n * %define api.pure   full\n * %define api.prefix {sipe_rtf_parser_}\n *\n * %param       {yyscan_t scanner}\n * %parse-param {struct parser_state *state}\n *\n * %{\n * #include ...\n * %}\n *\n * %union {\n *   gchar keyword_buffer[SIPE_RTF_LEXER_KEYWORD_SIZE];\n *   guint number;\n * }\n *\n * %token <keyword_buffer> KEYWORD\n * %token <number>         KEYWORD_PARAMETER\n * %token                  KEYWORD_END\n * %token                  LEXER_ERROR\n *\n * %%\n * sequence:\n *           %empty\n * \t| sequence KEYWORD KEYWORD_PARAMETER KEYWORD_END {\n * \t    const char   *keyword   = $2;\n * \t    unsigned int  parameter = $3;\n * \t    sipe_rtf_parse_keyword_parameter(state, keyword, parameter);\n *         }\n * \t| sequence KEYWORD KEYWORD_END {\n * \t    const char   *keyword   = $2;\n * \t    sipe_rtf_parse_keyword(state, keyword);\n *         }\n *         | sequence LEXER_ERROR {\n * \t    yyerror(scanner, state, \"lexer error\");\n * \t    YYERROR;\n *         }\n *         ;\n * %%\n */\nstatic void sipe_rtf_parser_error(const gchar *msg)\n{\n\tSIPE_DEBUG_ERROR(\"sipe_rtf_parser_error: %s\", msg);\n}\n\nstatic int sipe_rtf_parser_get_token(yyscan_t scanner,\n\t\t\t\t     struct parser_state *state,\n\t\t\t\t     gboolean required)\n{\n\tint token = sipe_rtf_lexer_lex(&state->lval, scanner);\n\n\tif (required && (token < 1)) {\n\t\tsipe_rtf_parser_error(\"unexpected end of RTF\");\n\t\treturn -1;\n\t}\n\n\treturn token;\n}\n\nstatic gboolean sipe_rtf_parser(yyscan_t scanner,\n\t\t\t\tstruct parser_state *state)\n{\n\tstruct parser_lval_type *lval = &state->lval;\n\tint token;\n\n\t/* read tokens from parser until it returns EOF */\n\twhile (TRUE) {\n\t\tif ((token = sipe_rtf_parser_get_token(scanner,\n\t\t\t\t\t\t       state,\n\t\t\t\t\t\t       FALSE)) < 0)\n\t\t\treturn TRUE;\n\n\t\tswitch (token) {\n\t\tcase 0: /* parse succeeded */\n\t\t\treturn FALSE;\n\t\t\tbreak;\n\n\t\tcase KEYWORD:\n\t\t\t{\n\t\t\t\tconst gchar *keyword = lval->keyword_buffer;\n\n\t\t\t\tif ((token = sipe_rtf_parser_get_token(scanner,\n\t\t\t\t\t\t\t\t       state,\n\t\t\t\t\t\t\t\t       TRUE)) < 0)\n\t\t\t\t\treturn TRUE;\n\n\t\t\t\tswitch (token) {\n\t\t\t\tcase KEYWORD_END:\n\t\t\t\t\tsipe_rtf_parse_keyword(state, keyword);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase KEYWORD_PARAMETER:\n\t\t\t\t\t{\n\t\t\t\t\t\tguint parameter = lval->number;\n\n\t\t\t\t\t\tif ((token = sipe_rtf_parser_get_token(scanner,\n\t\t\t\t\t\t\t\t\t\t       state,\n\t\t\t\t\t\t\t\t\t\t       TRUE)) < 0) {\n\t\t\t\t\t\t\treturn TRUE;\n\t\t\t\t\t\t} else if (token == KEYWORD_END) {\n\t\t\t\t\t\t\tsipe_rtf_parse_keyword_parameter(state,\n\t\t\t\t\t\t\t\t\t\t\t keyword,\n\t\t\t\t\t\t\t\t\t\t\t parameter);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsipe_rtf_parser_error(\"unexpected token\");\n\t\t\t\t\t\t\treturn TRUE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tsipe_rtf_parser_error(\"broken keyword\");\n\t\t\t\t\treturn TRUE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tsipe_rtf_parser_error(\"unexpected token\");\n\t\t\treturn TRUE;\n\t\t}\n\t}\n}\n\ngchar *sipe_rtf_to_html(const gchar *rtf)\n{\n\tstruct parser_state state;\n\tyyscan_t scanner;\n\n\t/* initialize state */\n\tstate.text                  = g_string_new(\"\");\n\tstate.unicode_ignore_length = 1;\n\tstate.ignore                = 0;\n\n\tif (!sipe_rtf_lexer_lex_init(&scanner)) {\n\t\tYY_BUFFER_STATE buf = sipe_rtf_lexer__scan_string(rtf,\n\t\t\t\t\t\t\t\t  scanner);\n\t\tsipe_rtf_lexer_set_extra(&state, scanner);\n\n\t\tif (sipe_rtf_parser(scanner, &state)) {\n\t\t\tSIPE_DEBUG_ERROR(\"sipe_rtf_to_html: unable to process the following RTF text\\n%s\",\n\t\t\t\t\t rtf);\n\t\t}\n\n\t\tsipe_rtf_lexer__delete_buffer(buf, scanner);\n\t} else {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_rtf_to_html: can't initialize lexer\");\n\t}\n\n\treturn g_string_free(state.text, FALSE);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-schedule.c",
    "content": "/**\n * @file sipe-schedule.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <glib.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-schedule.h\"\n\nstruct sipe_schedule {\n\t/**\n\t * Name of action.\n\t * Format is <Event>[<Data>...]\n\t * Example:  <presence><sip:user@domain.com> or <registration>\n\t */\n\tgchar *name;\n\tstruct sipe_core_private *sipe_private;\n\tgpointer backend_private;\n\tgpointer payload;\n\tsipe_schedule_action action;\n\tGDestroyNotify destroy;\n};\n\nstatic void sipe_schedule_deallocate(struct sipe_schedule *schedule)\n{\n\tif (schedule->destroy) (*schedule->destroy)(schedule->payload);\n\tg_free(schedule->name);\n\tg_free(schedule);\n}\n\nvoid sipe_core_schedule_execute(gpointer data)\n{\n\tstruct sipe_schedule *expired = data;\n\tstruct sipe_core_private *sipe_private = expired->sipe_private;\n\n\tSIPE_DEBUG_INFO(\"sipe_core_schedule_execute: executing %s\", expired->name);\n\tsipe_private->timeouts = g_slist_remove(sipe_private->timeouts, expired);\n\tSIPE_DEBUG_INFO(\"sipe_core_schedule_execute timeouts count %d after removal\",\n\t\t\tg_slist_length(sipe_private->timeouts));\n\n\t(*expired->action)(sipe_private, expired->payload);\n\tsipe_schedule_deallocate(expired);\n}\n\nstatic struct sipe_schedule *sipe_schedule_allocate(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t    const gchar *name,\n\t\t\t\t\t\t    gpointer payload,\n\t\t\t\t\t\t    sipe_schedule_action action,\n\t\t\t\t\t\t    GDestroyNotify destroy)\n{\n\tstruct sipe_schedule *new;\n\n\t/* Make sure each action only exists once */\n\tsipe_schedule_cancel(sipe_private, name);\n\n\tnew = g_new0(struct sipe_schedule, 1);\n\tnew->name = g_strdup(name);\n\tnew->sipe_private = sipe_private;\n\tnew->payload = payload;\n\tnew->action = action;\n\tnew->destroy = destroy;\n\tsipe_private->timeouts = g_slist_append(sipe_private->timeouts, new);\n\tSIPE_DEBUG_INFO(\"sipe_schedule_allocate timeouts count %d after addition\",\n\t\t\tg_slist_length(sipe_private->timeouts));\n\treturn(new);\n}\n\nvoid sipe_schedule_seconds(struct sipe_core_private *sipe_private,\n\t\t\t   const gchar *name,\n\t\t\t   gpointer payload,\n\t\t\t   guint seconds,\n\t\t\t   sipe_schedule_action action,\n\t\t\t   GDestroyNotify destroy)\n{\n\tstruct sipe_schedule *new = sipe_schedule_allocate(sipe_private,\n\t\t\t\t\t\t\t   name,\n\t\t\t\t\t\t\t   payload,\n\t\t\t\t\t\t\t   action,\n\t\t\t\t\t\t\t   destroy);\n\tSIPE_DEBUG_INFO(\"scheduling action %s timeout %d seconds\",\n\t\t\tname, seconds);\n\tnew->backend_private = sipe_backend_schedule_seconds(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t     seconds,\n\t\t\t\t\t\t\t     new);\n}\n\nvoid sipe_schedule_mseconds(struct sipe_core_private *sipe_private,\n\t\t\t    const gchar *name,\n\t\t\t    gpointer payload,\n\t\t\t    guint milliseconds,\n\t\t\t    sipe_schedule_action action,\n\t\t\t    GDestroyNotify destroy)\n{\n\tstruct sipe_schedule *new = sipe_schedule_allocate(sipe_private,\n\t\t\t\t\t\t\t   name,\n\t\t\t\t\t\t\t   payload,\n\t\t\t\t\t\t\t   action,\n\t\t\t\t\t\t\t   destroy);\n\tSIPE_DEBUG_INFO(\"scheduling action %s timeout %d milliseconds\",\n\t\t\tname, milliseconds);\n\tnew->backend_private = sipe_backend_schedule_mseconds(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t      milliseconds,\n\t\t\t\t\t\t\t      new);\n}\n\nstatic void sipe_schedule_remove(struct sipe_core_private *sipe_private,\n\t\t\t\t struct sipe_schedule *schedule)\n{\n\tSIPE_DEBUG_INFO(\"sipe_schedule_remove: action name=%s\",\n\t\t\tschedule->name);\n\tsipe_backend_schedule_cancel(SIPE_CORE_PUBLIC,\n\t\t\t\t     schedule->backend_private);\n\tsipe_schedule_deallocate(schedule);\n}\n\nvoid sipe_schedule_cancel(struct sipe_core_private *sipe_private,\n\t\t\t  const gchar *name)\n{\n\tGSList *entry;\n\n\tif (!sipe_private->timeouts || !name) return;\n\n\tentry = sipe_private->timeouts;\n\twhile (entry) {\n\t\tstruct sipe_schedule *schedule = entry->data;\n\t\tif (sipe_strequal(schedule->name, name)) {\n\t\t\tGSList *to_delete = entry;\n\t\t\tentry = entry->next;\n\t\t\tsipe_private->timeouts = g_slist_delete_link(sipe_private->timeouts,\n\t\t\t\t\t\t\t\t     to_delete);\n\t\t\tsipe_schedule_remove(sipe_private, schedule);\n\t\t} else {\n\t\t\tentry = entry->next;\n\t\t}\n\t}\n}\n\nvoid sipe_schedule_cancel_all(struct sipe_core_private *sipe_private)\n{\n\tGSList *entry = sipe_private->timeouts;\n\n\twhile (entry) {\n\t\tsipe_schedule_remove(sipe_private, entry->data);\n\t\tentry = entry->next;\n\t}\n\n\tg_slist_free(sipe_private->timeouts);\n\tsipe_private->timeouts = NULL;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-schedule.h",
    "content": "/**\n * @file sipe-schedule.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\n\ntypedef void (*sipe_schedule_action)(struct sipe_core_private *sipe_private,\n\t\t\t\t     gpointer data);\n\n/**\n  * Do schedule action for execution in the future.\n  * Non repetitive execution.\n  *\n  * @param sipe_core_private\n  * @param name of action (will be copied)\n  * @param timeout in seconds or milliseconds\n  * @param action  callback function\n  * @param destroy payload destroy function\n  * @param payload callback data (can be NULL, otherwise caller must allocate memory)\n  */\nvoid sipe_schedule_seconds(struct sipe_core_private *sipe_private,\n\t\t\t   const gchar *name,\n\t\t\t   gpointer payload,\n\t\t\t   guint seconds,\n\t\t\t   sipe_schedule_action action,\n\t\t\t   GDestroyNotify destroy);\nvoid sipe_schedule_mseconds(struct sipe_core_private *sipe_private,\n\t\t\t    const gchar *name,\n\t\t\t    gpointer payload,\n\t\t\t    guint milliseconds,\n\t\t\t    sipe_schedule_action action,\n\t\t\t    GDestroyNotify destroy);\nvoid sipe_schedule_cancel(struct sipe_core_private *sipe_private,\n\t\t\t  const gchar *name);\nvoid sipe_schedule_cancel_all(struct sipe_core_private *sipe_private);\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-session.c",
    "content": "/**\n * @file sipe-session.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2009-2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#include <glib.h>\n\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-chat.h\"\n#include \"sipe-conf.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-dialog.h\"\n#include \"sipe-session.h\"\n#include \"sipe-utils.h\"\n\nstatic void\nsipe_free_queued_message(struct queued_message *message)\n{\n\tg_free(message->body);\n\tg_free(message->content_type);\n\tg_free(message);\n}\n\nstruct sip_session *\nsipe_session_add_chat(struct sipe_core_private *sipe_private,\n\t\t      struct sipe_chat_session *chat_session,\n\t\t      gboolean multiparty,\n\t\t      const gchar *id)\n{\n\tstruct sip_session *session = g_new0(struct sip_session, 1);\n\tsession->callid = gencallid();\n\tif (chat_session) {\n\t\tsession->chat_session = chat_session;\n\t} else {\n\t\tgchar *chat_title = sipe_chat_get_name();\n\t\tsession->chat_session = sipe_chat_create_session(multiparty ?\n\t\t\t\t\t\t\t\t SIPE_CHAT_TYPE_MULTIPARTY :\n\t\t\t\t\t\t\t\t SIPE_CHAT_TYPE_CONFERENCE,\n\t\t\t\t\t\t\t\t id,\n\t\t\t\t\t\t\t\t chat_title);\n\t\tg_free(chat_title);\n\t}\n\tsession->unconfirmed_messages = g_hash_table_new_full(\n\t\tg_str_hash, g_str_equal, g_free, (GDestroyNotify)sipe_free_queued_message);\n\tsession->conf_unconfirmed_messages = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);\n\tsipe_private->sessions = g_slist_append(sipe_private->sessions, session);\n\treturn session;\n}\n\n#ifdef HAVE_VV\n\nstruct sip_session *\nsipe_session_add_call(struct sipe_core_private *sipe_private,\n\t\t      const gchar *who)\n{\n\tstruct sip_session *session = g_new0(struct sip_session, 1);\n\tSIPE_DEBUG_INFO(\"sipe_session_add_call: new session for %s\", who);\n\tsession->with = g_strdup(who);\n\tsession->unconfirmed_messages = g_hash_table_new_full(\n\t\tg_str_hash, g_str_equal, g_free, (GDestroyNotify)sipe_free_queued_message);\n\tsession->is_call = TRUE;\n\tsipe_private->sessions = g_slist_append(sipe_private->sessions, session);\n\treturn session;\n}\n\n#endif\n\nstruct sip_session *\nsipe_session_find_chat(struct sipe_core_private *sipe_private,\n\t\t       struct sipe_chat_session *chat_session)\n{\n\tif (sipe_private == NULL || chat_session == NULL) {\n\t\treturn NULL;\n\t}\n\n\tSIPE_SESSION_FOREACH {\n\t\tif (session->chat_session == chat_session) {\n\t\t\treturn session;\n\t\t}\n\t} SIPE_SESSION_FOREACH_END;\n\treturn NULL;\n\n}\n\nstruct sip_session *\nsipe_session_find_chat_by_callid(struct sipe_core_private *sipe_private,\n\t\t\t\t const gchar *callid)\n{\n\tif (sipe_private == NULL || callid == NULL) {\n\t\treturn NULL;\n\t}\n\n\tSIPE_SESSION_FOREACH {\n\t\tif (session->callid &&\n\t\t    sipe_strcase_equal(callid, session->callid)) {\n\t\t\treturn session;\n\t\t}\n\t} SIPE_SESSION_FOREACH_END;\n\treturn NULL;\n}\n\nstruct sip_session *\nsipe_session_find_conference(struct sipe_core_private *sipe_private,\n\t\t\t     const gchar *focus_uri)\n{\n\tif (sipe_private == NULL || focus_uri == NULL) {\n\t\treturn NULL;\n\t}\n\n\tSIPE_SESSION_FOREACH {\n\t\tif (session->chat_session &&\n\t\t    (session->chat_session->type == SIPE_CHAT_TYPE_CONFERENCE) &&\n\t\t    sipe_strcase_equal(focus_uri, session->chat_session->id)) {\n\t\t\treturn session;\n\t\t}\n\t} SIPE_SESSION_FOREACH_END;\n\treturn NULL;\n}\n\nstruct sip_session *\nsipe_session_find_im(struct sipe_core_private *sipe_private,\n\t\t     const gchar *who)\n{\n\tif (sipe_private == NULL || who == NULL) {\n\t\treturn NULL;\n\t}\n\n\tSIPE_SESSION_FOREACH {\n\t\tif (!session->is_call &&\n\t\t    session->with && sipe_strcase_equal(who, session->with)) {\n\t\t\treturn session;\n\t\t}\n\t} SIPE_SESSION_FOREACH_END;\n\treturn NULL;\n}\n\nstruct sip_session *\nsipe_session_find_or_add_im(struct sipe_core_private *sipe_private,\n\t\t\t    const gchar *who)\n{\n\tstruct sip_session *session = sipe_session_find_im(sipe_private, who);\n\tif (!session) {\n\t\tSIPE_DEBUG_INFO(\"sipe_session_find_or_add_im: new session for %s\", who);\n\t\tsession = g_new0(struct sip_session, 1);\n\t\tsession->with = g_strdup(who);\n\t\tsession->unconfirmed_messages = g_hash_table_new_full(\n\t\t\tg_str_hash, g_str_equal, g_free, (GDestroyNotify)sipe_free_queued_message);\n\t\tsipe_private->sessions = g_slist_append(sipe_private->sessions, session);\n\t}\n\treturn session;\n}\n\nstruct sip_session *\nsipe_session_find_chat_or_im(struct sipe_core_private *sipe_private,\n\t\t\t     const gchar *callid,\n\t\t\t     const gchar *who)\n{\n\tstruct sip_session *session = sipe_session_find_chat_by_callid(sipe_private,\n\t\t\t\t\t\t\t\t       callid);\n\tif (!session) {\n\t\tsession = sipe_session_find_im(sipe_private, who);\n\t}\n\treturn session;\n}\n\nvoid\nsipe_session_remove(struct sipe_core_private *sipe_private,\n\t\t    struct sip_session *session)\n{\n\tsipe_private->sessions = g_slist_remove(sipe_private->sessions, session);\n\n\tsipe_dialog_remove_all(session);\n\tsipe_dialog_free(session->focus_dialog);\n\n\twhile (sipe_session_dequeue_message(session));\n\n\tsipe_utils_slist_free_full(session->pending_invite_queue, g_free);\n\n\tg_hash_table_destroy(session->unconfirmed_messages);\n\tif (session->conf_unconfirmed_messages)\n\t\tg_hash_table_destroy(session->conf_unconfirmed_messages);\n\n\tif (session->chat_session) {\n\t\tsipe_chat_remove_session(session->chat_session);\n\t}\n\n\tg_free(session->with);\n\tg_free(session->callid);\n\tg_free(session->im_mcu_uri);\n\tg_free(session->subject);\n\tg_free(session->audio_video_entity);\n\tg_free(session);\n}\n\nvoid\nsipe_session_close(struct sipe_core_private *sipe_private,\n\t\t   struct sip_session *session)\n{\n\tif (session) {\n\t\tif (session->chat_session &&\n\t\t    (session->chat_session->type == SIPE_CHAT_TYPE_CONFERENCE)) {\n\t\t\tsipe_conf_immcu_closed(sipe_private, session);\n\t\t\tconf_session_close(sipe_private, session);\n\t\t}\n\n\t\tSIPE_DIALOG_FOREACH {\n\t\t\t/* @TODO slow down BYE message sending rate */\n\t\t\t/* @see single subscription code */\n\t\t\tsip_transport_bye(sipe_private, dialog);\n\t\t} SIPE_DIALOG_FOREACH_END;\n\n\t\tsipe_session_remove(sipe_private, session);\n\t}\n}\n\nvoid\nsipe_session_enqueue_message(struct sip_session *session,\n\t\t\t     const gchar *body, const gchar *content_type)\n{\n\tstruct queued_message *msg = g_new0(struct queued_message,1);\n\tmsg->body = g_strdup(body);\n\tif (content_type != NULL)\n\t\tmsg->content_type = g_strdup(content_type);\n\n\tsession->outgoing_message_queue = g_slist_append(session->outgoing_message_queue, msg);\n}\n\nGSList *\nsipe_session_dequeue_message(struct sip_session *session)\n{\n\tstruct queued_message *msg;\n\n\tif (session->outgoing_message_queue == NULL)\n\t\treturn NULL;\n\n\tmsg = session->outgoing_message_queue->data;\n\tsession->outgoing_message_queue = g_slist_remove(session->outgoing_message_queue, msg);\n\tg_free(msg->body);\n\tg_free(msg->content_type);\n\tg_free(msg);\n\n\treturn session->outgoing_message_queue;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-session.h",
    "content": "/**\n * @file sipe-sesion.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2009-11 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/*\n * Interface dependencies:\n *\n * <glib.h>\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\nstruct sipe_chat_session;\n\n/* Helper macros to iterate over session list in a SIP account */\n#define SIPE_SESSION_FOREACH {                             \\\n\tGSList *entry = sipe_private->sessions;                    \\\n\twhile (entry) {                                    \\\n\t\tstruct sip_session *session = entry->data; \\\n\t\tentry = entry->next;\n#define SIPE_SESSION_FOREACH_END }}\n\n/** Correspond to multi-party conversation */\nstruct sip_session {\n\t/** chat session */\n\tstruct sipe_chat_session *chat_session;\n\n\tgchar *with; /* For IM or call sessions only (not multi-party) . A URI.*/\n\t/** key is user (URI) */\n\tGSList *dialogs;\n\t/** Key is <Call-ID><CSeq><METHOD><To> */\n\tGHashTable *unconfirmed_messages;\n\tGSList *outgoing_message_queue;\n\n\t/*\n\t * Multiparty conversation related fields\n\t */\n\t/** Call-Id identifying the conversation */\n\tgchar *callid; /* For multiparty conversations */\n\tint bid;\n\tgboolean is_voting_in_progress;\n\tGSList *pending_invite_queue;\n\n\t/*\n\t * Conference related fields\n\t */\n\tgchar *im_mcu_uri;\n\tgchar *subject;\n\tgboolean locked;\n\tstruct sip_dialog *focus_dialog;\n\t/** Key is Message-Id */\n\tGHashTable *conf_unconfirmed_messages;\n\tgchar *audio_video_entity;\n\tguint audio_media_id;\n\tguint video_media_source_id;\n\n\t/*\n\t * Media call related fields\n\t */\n\tgboolean is_call;\n\n\t/*\n\t * Group Chat related fields\n\t */\n\tgboolean is_groupchat;\n};\n\n/**\n * An item in outgoing message queue.\n *\n * Messages are put in the queue until a response to initial INVITE is received\n * from remote dialog participant.\n */\nstruct queued_message {\n\t/** Body of the message. */\n\tgchar *body;\n\t/**\n\t * Content type of message body, e.g. text/plain for chat messages,\n\t * text/x-msmsgsinvite for filetransfer initialization. Setting this to NULL\n\t * means default value text/plain.\n\t */\n\tgchar *content_type;\n\tguint cseq;\n};\n\n/**\n * Add a new chat session\n *\n * @param sipe_private (in) SIPE core data. May be NULL\n * @param chat_session (in) non-NULL to rejoin existing chat\n * @param multiparty   (in) multiparty or conference\n * @param id           (in) new chat session identifier (ignored for rejoin).\n *\n * @return pointer to new session\n */\nstruct sip_session *\nsipe_session_add_chat(struct sipe_core_private *sipe_private,\n\t\t      struct sipe_chat_session *chat_session,\n\t\t      gboolean multiparty,\n\t\t      const gchar *id);\n\n#ifdef HAVE_VV\n\n/**\n * Add a new media call session\n *\n * @param sipe_private (in) SIPE core data.\n * @param who (in) remote partner.\n *\n * @return pointer to new session\n */\nstruct sip_session *\nsipe_session_add_call(struct sipe_core_private *sipe_private,\n\t\t      const gchar *who);\n\n#endif\n\n/**\n * Find chat session\n *\n * @param sipe_private (in) SIPE core data. May be NULL\n * @param chat_session (in) chat session data. May be NULL\n *\n * @return pointer to session or NULL\n */\nstruct sip_session *\nsipe_session_find_chat(struct sipe_core_private *sipe_private,\n\t\t       struct sipe_chat_session *chat_session);\n\n/**\n * Find chat session by Call ID\n *\n * @param sipe_private (in) SIPE core data. May be NULL\n * @param callid (in) Call ID. May be NULL\n *\n * @return pointer to session or NULL\n */\nstruct sip_session *\nsipe_session_find_chat_by_callid(struct sipe_core_private *sipe_private,\n\t\t\t\t const gchar *callid);\n\n/**\n * Find Conference session\n *\n * @param sipe_private (in) SIPE core data. May be NULL\n * @param focus_uri (in) URI of conference focus. May be NULL\n *\n * @return pointer to session or NULL\n */\nstruct sip_session *\nsipe_session_find_conference(struct sipe_core_private *sipe_private,\n\t\t\t     const gchar *focus_uri);\n\n/**\n * Find IM session\n *\n * @param sipe_private (in) SIPE core data. May be NULL\n * @param who (in) remote partner. May be NULL\n *\n * @return pointer to session or NULL\n */\nstruct sip_session *\nsipe_session_find_im(struct sipe_core_private *sipe_private,\n\t\t     const gchar *who);\n\n/**\n * Find or add new IM session\n *\n * @param sipe_private (in) SIPE core data\n * @param who (in) remote partner\n *\n * @return pointer to session\n */\nstruct sip_session *\nsipe_session_find_or_add_im(struct sipe_core_private *sipe_private,\n\t\t\t    const gchar *who);\n\n/**\n * Find Chat by Call ID or IM session\n *\n * @param sipe_private (in) SIPE core data. May be NULL\n * @param callid (in) Call ID. May be NULL\n * @param who (in) remote partner. May be NULL\n *\n * @return pointer to session or NULL\n */\nstruct sip_session *\nsipe_session_find_chat_or_im(struct sipe_core_private *sipe_private,\n\t\t\t     const gchar *callid,\n\t\t\t     const gchar *who);\n\n/**\n * Close a session\n *\n * @param sipe_private (in) SIPE core data\n * @param session (in) pointer to session\n */\nvoid\nsipe_session_close(struct sipe_core_private *sipe_private,\n\t\t   struct sip_session *session);\n\n/**\n * Remove a session from a SIP account\n *\n * @param sipe_private (in) SIPE core data\n * @param session (in) pointer to session\n */\nvoid\nsipe_session_remove(struct sipe_core_private *sipe_private,\n\t\t    struct sip_session *session);\n\n/**\n * Add a message to outgoing queue.\n *\n * @param session (in) SIP session\n * @param body (in) message to send\n * @param content_type (in) content type of the message body\n */\nvoid\nsipe_session_enqueue_message(struct sip_session *session,\n\t\t\t     const gchar *body, const gchar *content_type);\n\n/**\n * Removes and deallocates the first item in outgoing message queue.\n *\n * @param session (in) SIP session\n *\n * @return pointer to new message queue head\n */\nGSList *\nsipe_session_dequeue_message(struct sip_session *session);\n"
  },
  {
    "path": "src/core/sipe-sign.c",
    "content": "/*\n * @file sipe-sign.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2019 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2008 Novell, Inc.\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA\n */\n\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipmsg.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-sign.h\"\n#include \"sipe-utils.h\"\n\nstatic gchar * const empty_string = \"\";\n\nvoid sipmsg_breakdown_parse(struct sipmsg_breakdown * msg, const gchar * realm, const gchar * target,\n\t\t\t    const gchar *protocol)\n{\n\tconst gchar * hdr;\n\tif (msg == NULL || msg->msg == NULL) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipmsg_breakdown_parse msg or msg->msg is NULL\");\n\t\treturn;\n\t}\n\n\tmsg->rand = msg->num = msg->realm = msg->target_name =\n\t\tmsg->cseq = msg->from_url = msg->from_tag = msg->to_url = msg->to_tag =\n\t\tmsg->p_assertet_identity_sip_uri = msg->p_assertet_identity_tel_uri = empty_string;\n\tmsg->call_id = msg->expires = empty_string;\n\n\tif ((hdr = sipmsg_find_header(msg->msg, \"Proxy-Authorization\")) ||\n\t    (hdr = sipmsg_find_header(msg->msg, \"Proxy-Authentication-Info\")) ||\n\t    (hdr = sipmsg_find_header(msg->msg, \"Authentication-Info\")) ) {\n\t\tmsg->protocol = sipmsg_find_part_of_header(hdr, NULL, \" \", empty_string);\n\t\tmsg->rand   = sipmsg_find_part_of_header(hdr, \"rand=\\\"\", \"\\\"\", empty_string);\n\t\tmsg->num    = sipmsg_find_part_of_header(hdr, \"num=\\\"\", \"\\\"\", empty_string);\n\t\tmsg->realm  = sipmsg_find_part_of_header(hdr, \"realm=\\\"\", \"\\\"\", empty_string);\n\t\tmsg->target_name = sipmsg_find_part_of_header(hdr, \"targetname=\\\"\", \"\\\"\", empty_string);\n\t} else {\n\t\tmsg->protocol = g_strdup(protocol);\n\t\tmsg->realm = g_strdup(realm);\n\t\tmsg->target_name = g_strdup(target);\n\t}\n\n\tmsg->call_id = sipmsg_find_call_id_header(msg->msg);\n\n\thdr = sipmsg_find_cseq_header(msg->msg);\n\tif (NULL != hdr) {\n\t\tmsg->cseq = sipmsg_find_part_of_header(hdr, NULL, \" \", empty_string);\n\t}\n\n\thdr = sipmsg_find_from_header(msg->msg);\n\tif (NULL != hdr) {\n\t\tgchar *address = parse_from(hdr);\n\t\tif (address)\n\t\t\tmsg->from_url = address;\n\t\tmsg->from_tag = sipmsg_find_part_of_header(hdr, \";tag=\", \";\", empty_string);\n\t}\n\n\thdr = sipmsg_find_to_header(msg->msg);\n\tif (NULL != hdr) {\n\t\tgchar *address = parse_from(hdr);\n\t\tif (address)\n\t\t\tmsg->to_url = address;\n\t\tmsg->to_tag = sipmsg_find_part_of_header(hdr, \";tag=\", \";\", empty_string);\n\t}\n\n\thdr = sipmsg_find_header(msg->msg, \"P-Asserted-Identity\");\n\tif (NULL == hdr) {\n\t\thdr = sipmsg_find_header(msg->msg, \"P-Preferred-Identity\");\n\t}\n\tif (NULL != hdr) {\n\t\tgchar *sip_uri = NULL;\n\t\tgchar *tel_uri = NULL;\n\n\t\tsipmsg_parse_p_asserted_identity(hdr, &sip_uri, &tel_uri);\n\t\tif (sip_uri)\n\t\t\tmsg->p_assertet_identity_sip_uri = sip_uri;\n\t\tif (tel_uri)\n\t\t\tmsg->p_assertet_identity_tel_uri = tel_uri;\n\t}\n\n\tmsg->expires = sipmsg_find_expires_header(msg->msg);\n}\n\nvoid\nsipmsg_breakdown_free(struct sipmsg_breakdown * msg)\n{\n\tif (msg->protocol != empty_string)\n\t\tg_free(msg->protocol);\n\tif (msg->rand != empty_string)\n\t\tg_free(msg->rand);\n\tif (msg->num != empty_string)\n\t\tg_free(msg->num);\n\tif (msg->realm != empty_string)\n\t\tg_free(msg->realm);\n\tif (msg->target_name != empty_string)\n\t\tg_free(msg->target_name);\n\n\t// straight from header\n\t//g_free(msg->call_id);\n\n\tif (msg->cseq != empty_string)\n\t\tg_free(msg->cseq);\n\tif (msg->from_url != empty_string)\n\t\tg_free(msg->from_url);\n\tif (msg->from_tag != empty_string)\n\t\tg_free(msg->from_tag);\n\tif (msg->to_url != empty_string)\n\t\tg_free(msg->to_url);\n\tif (msg->to_tag != empty_string)\n\t\tg_free(msg->to_tag);\n\n\tif (msg->p_assertet_identity_sip_uri != empty_string)\n\t\tg_free(msg->p_assertet_identity_sip_uri);\n\tif (msg->p_assertet_identity_tel_uri != empty_string)\n\t\tg_free(msg->p_assertet_identity_tel_uri);\n\n\t// straight from header\n\t//g_free (msg->expires);\n}\n\ngchar *\nsipmsg_breakdown_get_string(int version,\n\t\t\t    struct sipmsg_breakdown * msgbd)\n{\n\tgchar *response_str;\n\tgchar *msg;\n\tif (msgbd->realm == empty_string || msgbd->realm == NULL) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"realm NULL, so returning NULL signature string\");\n\t\treturn NULL;\n\t}\n\n\tresponse_str = msgbd->msg->response != 0 ? g_strdup_printf(\"<%d>\", msgbd->msg->response) : empty_string;\n\tif (version < 3) {\n\t\tmsg = g_strdup_printf(\n\t\t\t\"<%s><%s><%s><%s><%s><%s><%s><%s><%s><%s><%s>\" // 1 - 11\n\t\t\t\"<%s>%s\", // 12 - 13\n\t\t\tmsgbd->protocol, msgbd->rand, msgbd->num, msgbd->realm, msgbd->target_name, msgbd->call_id, msgbd->cseq,\n\t\t\tmsgbd->msg->method, msgbd->from_url, msgbd->from_tag, msgbd->to_tag,\n\t\t\tmsgbd->expires ? msgbd->expires : empty_string, response_str\n\t\t);\n\t} else {\n\t\tmsg = g_strdup_printf(\n\t\t\t\"<%s><%s><%s><%s><%s><%s><%s><%s><%s><%s><%s><%s><%s><%s>\" // 1 - 14\n\t\t\t\"<%s>%s\", // 15 - 16\n\t\t\tmsgbd->protocol, msgbd->rand, msgbd->num, msgbd->realm, msgbd->target_name, msgbd->call_id, msgbd->cseq,\n\t\t\tmsgbd->msg->method, msgbd->from_url, msgbd->from_tag, msgbd->to_url, msgbd->to_tag,\n\t\t\tmsgbd->p_assertet_identity_sip_uri, msgbd->p_assertet_identity_tel_uri,\n\t\t\tmsgbd->expires ? msgbd->expires : empty_string, response_str\n\t\t);\n\t}\n\n\tif (response_str != empty_string) {\n\t\tg_free(response_str);\n\t}\n\n\treturn msg;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-sign.h",
    "content": "/*\n * @file sipe-sign.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2019 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2008 Novell, Inc.\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA\n */\n\nstruct sipmsg_breakdown {\n\tstruct sipmsg * msg;\n\tgchar * protocol;\n\tgchar * rand;\n\tgchar * num;\n\tgchar * realm;\n\tgchar * target_name;\n\tconst gchar * call_id;\n\tgchar * cseq;\n\t//method\n\tgchar * from_url;\n\tgchar * from_tag;\n\t/** @since 3 */\n\tgchar * to_url;\n\tgchar * to_tag;\n\t/** @since 3 */\n\tgchar * p_assertet_identity_sip_uri;\n\t/** @since 3 */\n\tgchar * p_assertet_identity_tel_uri;\n\tconst gchar * expires;\n\t//response code\n};\n\nvoid sipmsg_breakdown_parse(struct sipmsg_breakdown * msg, const gchar * realm, const gchar * target,\n\t\t\t    const gchar *protocol);\ngchar*\nsipmsg_breakdown_get_string(int version,\n\t\t\t    struct sipmsg_breakdown * msgbd);\nvoid sipmsg_breakdown_free(struct sipmsg_breakdown * msg);\n"
  },
  {
    "path": "src/core/sipe-sipmsg-tests.c",
    "content": "/**\n * @file sipe-sipmsg-tests.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * Some non-NTLM tests code was factored out from sipe-sec-ntlm-test.c:\n *\n *------------- Copyright notices from \"sipe-sec-ntlm-tests.c\" -------------\n * Copyright (C) 2011-2016 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2010 pier11 <pier11@operamail.com>\n * Copyright (C) 2008 Novell, Inc.\n *------------- Copyright notices from \"sipe-sec-ntlm-tests.c\" -------------\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdint.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-crypt.h\"\n#include \"sipe-mime.h\"\n#include \"sipe-rtf.h\"\n#include \"sipe-sign.h\"\n#include \"sipe-utils.h\"\n#include \"sip-transport.h\"\n#include \"sipmsg.h\"\n\n#include \"uuid.h\"\n\n/*\n * Stubs\n */\ngboolean sipe_backend_debug_enabled(void)\n{\n\treturn(TRUE);\n}\n\nvoid sipe_backend_debug_literal(sipe_debug_level level,\n\t\t\t\tconst gchar *msg)\n{\n\tprintf(\"DEBUG(%d): %s\\n\", level, msg);\n}\n\nvoid sipe_backend_debug(sipe_debug_level level,\n\t\t\tconst gchar *format,\n\t\t\t...)\n{\n\tva_list ap;\n\tgchar *newformat = g_strdup_printf(\"DEBUG(%d): %s\\n\", level, format);\n\n\tva_start(ap, format);\n\tvprintf(newformat, ap);\n\tva_end(ap);\n\n\tg_free(newformat);\n}\n\ngchar *sipe_backend_markup_css_property(SIPE_UNUSED_PARAMETER const gchar *style,\n\t\t\t\t\tSIPE_UNUSED_PARAMETER const gchar *option)\n{\n\treturn(NULL);\n}\n\nvoid sipe_mime_parts_foreach(SIPE_UNUSED_PARAMETER const gchar *type,\n\t\t\t     SIPE_UNUSED_PARAMETER const gchar *body,\n\t\t\t     SIPE_UNUSED_PARAMETER sipe_mime_parts_cb callback,\n\t\t\t     SIPE_UNUSED_PARAMETER gpointer user_data)\n{\n}\n\ngchar *sipe_rtf_to_html(SIPE_UNUSED_PARAMETER const gchar *rtf)\n{\n\treturn(NULL);\n}\n\nconst gchar *sip_transport_epid(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private)\n{\n\treturn(NULL);\n}\n\nconst gchar *sip_transport_ip_address(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private)\n{\n\treturn(NULL);\n}\n\n/* needed when linking against NSS */\nvoid md4sum(const uint8_t *data, uint32_t length, uint8_t *digest);\nvoid md4sum(SIPE_UNUSED_PARAMETER const uint8_t *data,\n\t    SIPE_UNUSED_PARAMETER uint32_t length,\n\t    SIPE_UNUSED_PARAMETER uint8_t *digest)\n{\n}\n\n/*\n * Tester code\n */\nstatic guint succeeded = 0;\nstatic guint failed    = 0;\n\nstatic void assert_equal(const char *expected, const gchar *got)\n{\n\tif (sipe_strequal(expected, got)) {\n\t\tsucceeded++;\n\t} else {\n\t\tprintf(\"FAILED: %s\\n        %s\\n\", got, expected);\n\t\tfailed++;\n\t}\n}\n\nstatic void msg_tests(void) {\n\t/* Address parsing */\n\t{\n\t\tconst gchar *responses[] = {\n\t\t\t\"SIP/2.0 200 OK\\r\\n\"\n\t\t\t\"From: \\\"J.D. User\\\" <sip:foo.bar@company.com>;something else\\r\\n\"\n\t\t\t\"To: \\\"Test Recipient\\\" <SIP:test@recipient.com>\\r\\n\"\n\t\t\t\"X-Some-Header: <SiP:joe.header@test.com>\\r\\n\"\n\t\t\t\"Content-Length: 0\\r\\n\"\n\t\t\t\"\\r\\n\",\n\t\t\t\"SIP/2.0 200 OK\\r\\n\"\n\t\t\t\"From: sip:foo.bar@company.com;something else\\r\\n\"\n\t\t\t\"To: SIP:test@recipient.com\\r\\n\"\n\t\t\t\"X-Some-Header: SiP:joe.header@test.com\\r\\n\"\n\t\t\t\"Content-Length: 0\\r\\n\"\n\t\t\t\"\\r\\n\",\n\t\t\tNULL\n\t\t};\n\t\tconst gchar **resp;\n\n\t\tfor (resp = responses; *resp; resp++) {\n\t\t\tstruct sipmsg *msg = sipmsg_parse_msg(*resp);\n\t\t\tgchar *address;\n\n\t\t\taddress = sipmsg_parse_from_address(msg);\n\t\t\tassert_equal(\"sip:foo.bar@company.com\", address);\n\t\t\tg_free(address);\n\n\t\t\taddress = sipmsg_parse_to_address(msg);\n\t\t\tassert_equal(\"SIP:test@recipient.com\", address);\n\t\t\tg_free(address);\n\n\t\t\taddress = sipmsg_parse_address_from_header(msg, \"x-some-header\");\n\t\t\tassert_equal(\"SiP:joe.header@test.com\", address);\n\t\t\tg_free(address);\n\n\t\t\tsipmsg_free(msg);\n\t\t}\n\t}\n\n\t/* P-Asserted-Identity parsing */\n\t{\n\t\tconst struct {\n\t\t\tconst gchar *header;\n\t\t\tconst gchar *sip_uri;\n\t\t\tconst gchar *tel_uri;\n\t\t} testcases[] = {\n\t\t\t{\n\t\t\t\t\"\\\"Cullen Jennings\\\" <sip:fluffy@cisco.com>\",\n\t\t\t\t\"sip:fluffy@cisco.com\",\n\t\t\t\tNULL\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"tel:+14085264000\",\n\t\t\t\tNULL,\n\t\t\t\t\"tel:+14085264000\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"\\\"Lunch, Lucas\\\" <sip:llucas@cisco.com>,<tel:+420123456;ext=88463>\",\n\t\t\t\t\"sip:llucas@cisco.com\",\n\t\t\t\t\"tel:+420123456;ext=88463\"\n\t\t\t},\n\t\t\t{\n\t\t\t\tNULL,\n\t\t\t\tNULL,\n\t\t\t\tNULL\n\t\t\t},\n\t\t}, *testcase;\n\n\t\tfor (testcase = testcases; testcase->header; testcase++) {\n\t\t\tgchar *sip_uri = NULL;\n\t\t\tgchar *tel_uri = NULL;\n\n\t\t\tsipmsg_parse_p_asserted_identity(testcase->header,\n\t\t\t\t\t\t\t &sip_uri,\n\t\t\t\t\t\t\t &tel_uri);\n\t\t\tassert_equal(testcase->sip_uri, sip_uri);\n\t\t\tassert_equal(testcase->tel_uri, tel_uri);\n\n\t\t\tg_free(tel_uri);\n\t\t\tg_free(sip_uri);\n\t\t}\n\t}\n\n\t/* Test Authentication Algorithm's v4 Signature String */\n\t{\n\t\tconst gchar *response =\n\t\t\t\"SIP/2.0 180 Ringing\\r\\n\"\n\t\t\t\"Authentication-Info: NTLM rspauth=\\\"010000003EA8D688BA51D5CD64000000\\\", srand=\\\"1B6D47A1\\\", snum=\\\"11\\\", opaque=\\\"357E6F72\\\", qop=\\\"auth\\\", targetname=\\\"LOC-COMPANYT-FE03.COMPANY.COM\\\", realm=\\\"SIP Communications Service\\\"\\r\\n\"\n\t\t\t\"Via: SIP/2.0/tls 192.168.44.10:50230;received=10.117.245.254;ms-received-port=50230;ms-received-cid=37ABE00\\r\\n\"\n\t\t\t\"FROM: \\\"Sender\\\"<sip:sender@company.com>;tag=2420628112;epid=54392f1bbf01\\r\\n\"\n\t\t\t\"TO: \\\"recipient\\\"<sip:recipient@company.com>;tag=7aee15546a;epid=3102EB8BD1\\r\\n\"\n\t\t\t\"CSEQ: 1 INVITE\\r\\n\"\n\t\t\t\"CALL-ID: 41CEg82ECa0AC8i3DD7mE673t9CF4b19DAxF780x\\r\\n\"\n\t\t\t\"RECORD-ROUTE: <sip:LOC-COMPANYT-OCSR2P01.COMPANY.COM:5061;transport=tls;ms-fe=LOC-COMPANYT-FE03.COMPANY.COM;opaque=state:F:T:Eu:Ci.R37abe00;lr;ms-route-sig=gdOGgL7NiL3hv_oBc0NdrJOxZk_r-8naq-k_DtpgAA>\\r\\n\"\n\t\t\t\"CONTACT: <sip:recipient@company.com;opaque=user:epid:-gLwenLTVVqy-Ak8TJn1ZAAA;gruu>;text;audio;video\\r\\n\"\n\t\t\t\"CONTENT-LENGTH: 0\\r\\n\"\n\t\t\t\"SUPPORTED: gruu-10\\r\\n\"\n\t\t\t\"ALLOW: UPDATE\\r\\n\"\n\t\t\t\"P-ASSERTED-IDENTITY: \\\"recipient\\\"<SIP:recipient@company.com>\\r\\n\"\n\t\t\t\"SERVER: RTCC/3.5.0.0 MCXService/3.5.0.0 communicator.NOKIAS60R2.JVP.EN_US/1.0.6875.0\\r\\n\"\n\t\t\t\"\\r\\n\";\n\t\tconst gchar *response_sig = \"<NTLM><1B6D47A1><11><SIP Communications Service><LOC-COMPANYT-FE03.COMPANY.COM><41CEg82ECa0AC8i3DD7mE673t9CF4b19DAxF780x><1><INVITE><sip:sender@company.com><2420628112><sip:recipient@company.com><7aee15546a><SIP:recipient@company.com><><><180>\";\n\t\tstruct sipmsg_breakdown msgbd;\n\t\tgchar *msg_str;\n\n\t\tmsgbd.msg = sipmsg_parse_msg(response);\n\t\tsipmsg_breakdown_parse(&msgbd,\n\t\t\t\t       \"SIP Communications Service\",\n\t\t\t\t       \"LOC-COMPANYT-FE03.COMPANY.COM\",\n\t\t\t\t       NULL);\n\t\tmsg_str = sipmsg_breakdown_get_string(4, &msgbd);\n\n\t\tassert_equal(response_sig, msg_str);\n\n\t\tg_free(msg_str);\n\t\tsipmsg_free(msgbd.msg);\n\t\tsipmsg_breakdown_free(&msgbd);\n\t}\n\n\t/* Test parsing of address fields where URIs wrapped in \"<...>\" */\n\t{\n\t\tconst gchar *response =\n\t\t\t\"SIP/2.0 180 Ringing\\r\\n\"\n\t\t\t\"Authentication-Info: NTLM rspauth=\\\"010000003EA8D688BA51D5CD64000000\\\", srand=\\\"1B6D47A1\\\", snum=\\\"11\\\", opaque=\\\"357E6F72\\\", qop=\\\"auth\\\", targetname=\\\"bar\\\", realm=\\\"foo\\\"\\r\\n\"\n\t\t\t\"From: sip:sender@company.com;tag=2420628112;epid=54392f1bbf01\\r\\n\"\n\t\t\t\"To: sip:recipient@company.com;tag=7aee15546a;epid=3102EB8BD1\\r\\n\"\n\t\t\t\"CSeq: 1 INVITE\\r\\n\"\n\t\t\t\"Call-ID: 41CEg82ECa0AC8i3DD7mE673t9CF4b19DAxF780x\\r\\n\"\n\t\t\t\"Content-Length: 0\\r\\n\"\n\t\t\t\"P-Asserted-Identity: <SIP:recipient@company.com>\\r\\n\"\n\t\t\t\"\\r\\n\";\n\t\tconst gchar *response_sig = \"<NTLM><1B6D47A1><11><foo><bar><41CEg82ECa0AC8i3DD7mE673t9CF4b19DAxF780x><1><INVITE><sip:sender@company.com><2420628112><sip:recipient@company.com><7aee15546a><SIP:recipient@company.com><><><180>\";\n\t\tstruct sipmsg_breakdown msgbd;\n\t\tgchar *msg_str;\n\n\t\tmsgbd.msg = sipmsg_parse_msg(response);\n\t\tsipmsg_breakdown_parse(&msgbd,\n\t\t\t\t       \"foo\",\n\t\t\t\t       \"bar\",\n\t\t\t\t       NULL);\n\t\tmsg_str = sipmsg_breakdown_get_string(4, &msgbd);\n\n\t\tassert_equal(response_sig, msg_str);\n\n\t\tg_free(msg_str);\n\t\tsipmsg_free(msgbd.msg);\n\t\tsipmsg_breakdown_free(&msgbd);\n\t}\n\n\t/* UUID tests - begin tests from MS-SIPRE */\n\t{\n\t\tconst char *testEpid     = \"01010101\";\n\t\tconst char *expectedUUID = \"4b1682a8-f968-5701-83fc-7c6741dc6697\";\n\t\tgchar *gotUUID           = generateUUIDfromEPID(testEpid);\n\n\t\tassert_equal(expectedUUID, gotUUID);\n\n\t\tg_free(gotUUID);\n\t}\n}\n\nint main(SIPE_UNUSED_PARAMETER int argc,\n\t SIPE_UNUSED_PARAMETER char *argv[])\n{\n\t/* Initialization for crypto backend (test mode) */\n\tsipe_crypto_init(FALSE);\n\n\tmsg_tests();\n\n\tprintf(\"Result: %d PASSED %d FAILED\\n\", succeeded, failed);\n\treturn(failed);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-status.c",
    "content": "/**\n * @file sipe-status.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <time.h>\n\n#include <glib.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-cal.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-ocs2005.h\"\n#include \"sipe-ocs2007.h\"\n#include \"sipe-status.h\"\n#include \"sipe-utils.h\"\n\nstatic struct\n{\n\tconst gchar *status_id;\n\tconst gchar *desc;\n} const sipe_activity_map[SIPE_ACTIVITY_NUM_TYPES] = {\n/*\n * This has nothing to do with Availability numbers, like 3500 (online).\n * Just a mapping of Communicator Activities to tokens/translations\n */\n/* @TODO: NULL means \"default translation from Pidgin\"?\n *        What about other backends?                    */\n/* SIPE_ACTIVITY_UNSET       */ { \"unset\",                     NULL                            },\n/* SIPE_ACTIVITY_AVAILABLE   */ { \"available\",                 NULL                            },\n/* SIPE_ACTIVITY_ONLINE      */ { \"online\",                    NULL                            },\n/* SIPE_ACTIVITY_INACTIVE    */ { \"idle\",                      N_(\"Inactive\")                  },\n/* SIPE_ACTIVITY_BUSY        */ { \"busy\",                      N_(\"Busy\")                      },\n/* SIPE_ACTIVITY_BUSYIDLE    */ { \"busyidle\",                  N_(\"Busy-Idle\")                 },\n/* SIPE_ACTIVITY_DND         */ { \"do-not-disturb\",            NULL                            },\n/* SIPE_ACTIVITY_BRB         */ { \"be-right-back\",             N_(\"Be right back\")             },\n/* SIPE_ACTIVITY_AWAY        */ { \"away\",                      NULL                            },\n/* SIPE_ACTIVITY_LUNCH       */ { \"out-to-lunch\",              N_(\"Out to lunch\")              },\n/* SIPE_ACTIVITY_INVISIBLE   */ { \"invisible\",                 NULL                            },\n/* SIPE_ACTIVITY_OFFLINE     */ { \"offline\",                   NULL                            },\n/* SIPE_ACTIVITY_ON_PHONE    */ { \"on-the-phone\",              N_(\"In a call\")                 },\n/* SIPE_ACTIVITY_IN_CONF     */ { \"in-a-conference\",           N_(\"In a conference\")           },\n/* SIPE_ACTIVITY_IN_MEETING  */ { \"in-a-meeting\",              N_(\"In a meeting\")              },\n/* SIPE_ACTIVITY_OOF         */ { \"out-of-office\",             N_(\"Out of office\")             },\n/* SIPE_ACTIVITY_URGENT_ONLY */ { \"urgent-interruptions-only\", N_(\"Urgent interruptions only\") },\n/* SIPE_ACTIVITY_IN_PRES     */ { \"in-presentation\",           N_(\"Presenting\")                },\n};\n\nstatic GHashTable *token_map;\n\nvoid sipe_status_init(void)\n{\n\tguint index;\n\n\ttoken_map = g_hash_table_new(g_str_hash, g_str_equal);\n\tfor (index = SIPE_ACTIVITY_UNSET;\n\t     index < SIPE_ACTIVITY_NUM_TYPES;\n\t     index++) {\n\t\tg_hash_table_insert(token_map,\n\t\t\t\t    (gchar *) sipe_activity_map[index].status_id,\n\t\t\t\t    GUINT_TO_POINTER(index));\n\t}\n}\n\nvoid sipe_status_shutdown(void)\n{\n\tg_hash_table_destroy(token_map);\n}\n\n/* type == SIPE_ACTIVITY_xxx (see sipe-core.h) */\nconst gchar *sipe_status_activity_to_token(guint type)\n{\n\treturn(sipe_activity_map[type].status_id);\n}\n\nguint sipe_status_token_to_activity(const gchar *token)\n{\n\tif (!token) return(SIPE_ACTIVITY_UNSET);\n\treturn(GPOINTER_TO_UINT(g_hash_table_lookup(token_map, token)));\n}\n\nconst gchar *sipe_core_activity_description(guint type)\n{\n\treturn(gettext(sipe_activity_map[type].desc));\n}\n\nvoid sipe_status_set_token(struct sipe_core_private *sipe_private,\n\t\t\t   const gchar *status_id)\n{\n\tg_free(sipe_private->status);\n\tsipe_private->status = g_strdup(status_id);\n}\n\nvoid sipe_status_set_activity(struct sipe_core_private *sipe_private,\n\t\t\t      guint activity)\n{\n\tsipe_status_set_token(sipe_private,\n\t\t\t      sipe_status_activity_to_token(activity));\n}\n\nvoid sipe_core_reset_status(struct sipe_core_public *sipe_public)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_core_reset_status: start\");\n\n\tif (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007))\n\t\tsipe_ocs2007_reset_status(sipe_private);\n\telse\n\t\tsipe_ocs2005_reset_status(sipe_private);\n}\n\nvoid sipe_status_and_note(struct sipe_core_private *sipe_private,\n\t\t\t  const gchar *status_id)\n{\n\tguint activity;\n\n\tif (!status_id)\n\t\tstatus_id = sipe_private->status;\n\n\tSIPE_DEBUG_INFO(\"sipe_status_and_note: switch to '%s' for the account\", status_id);\n\n\tactivity = sipe_status_token_to_activity(status_id);\n\tif (sipe_backend_status_changed(SIPE_CORE_PUBLIC,\n\t\t\t\t\tactivity,\n\t\t\t\t\tsipe_private->note)) {\n\t\t/* status has changed */\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_status_and_note: updating backend status\");\n\n\t\t/* update backend status */\n\t\tsipe_backend_status_and_note(SIPE_CORE_PUBLIC,\n\t\t\t\t\t     activity,\n\t\t\t\t\t     sipe_private->note);\n\t}\n}\n\nvoid sipe_core_status_set(struct sipe_core_public *sipe_public,\n\t\t\t  gboolean set_by_user,\n\t\t\t  guint activity,\n\t\t\t  const gchar *note)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tgchar *tmp;\n\tconst gchar *status_id = sipe_status_activity_to_token(activity);\n\n\tSIPE_DEBUG_INFO(\"sipe_core_status_set: status: %s (%s)\",\n\t\t\tstatus_id,\n\t\t\tset_by_user ? \"USER\" : \"MACHINE\");\n\n\tsipe_private->status_set_by_user = set_by_user;\n\n\tsipe_status_set_token(sipe_private, status_id);\n\n\t/* hack to escape apostrof before comparison */\n\ttmp = note ? sipe_utils_str_replace(note, \"'\", \"&apos;\") : NULL;\n\n\t/* this will preserve OOF flag as well */\n\tif (!sipe_strequal(tmp, sipe_private->note)) {\n\t\tSIPE_CORE_PRIVATE_FLAG_UNSET(OOF_NOTE);\n\t\tg_free(sipe_private->note);\n\t\tsipe_private->note = g_strdup(note);\n\t\tsipe_private->note_since = time(NULL);\n\t}\n\tg_free(tmp);\n\n\tsipe_cal_presence_publish(sipe_private, FALSE);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-status.h",
    "content": "/**\n * @file sipe-status.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2015 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\n\n/* called by sipe-core.c during plugin initialization/destruction */\nvoid sipe_status_init(void);\nvoid sipe_status_shutdown(void);\n\n/* type == SIPE_ACTIVITY_xxx (see sipe-core.h) */\nconst gchar *sipe_status_activity_to_token(guint type);\nguint sipe_status_token_to_activity(const gchar *token);\n\nvoid sipe_status_set_token(struct sipe_core_private *sipe_private,\n\t\t\t   const gchar *status_id);\nvoid sipe_status_set_activity(struct sipe_core_private *sipe_private,\n\t\t\t      guint activity);\nvoid sipe_status_and_note(struct sipe_core_private *sipe_private,\n\t\t\t  const gchar *status_id);\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-subscriptions.c",
    "content": "/**\n * @file sipe-subscriptions.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipmsg.h\"\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-buddy.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-dialog.h\"\n#include \"sipe-mime.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-notify.h\"\n#include \"sipe-schedule.h\"\n#include \"sipe-subscriptions.h\"\n#include \"sipe-ucs.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n\n/* RFC3265 subscription */\nstruct sip_subscription {\n\tstruct sip_dialog dialog;\n\tgchar *event;\n\tGSList *buddies; /* batched subscriptions */\n};\n\nstatic void sipe_subscription_free(struct sip_subscription *subscription)\n{\n\n\tif (!subscription) return;\n\n\tg_free(subscription->event);\n\tsipe_utils_slist_free_full(subscription->buddies, g_free);\n\n\t/* NOTE: use cast to prevent BAD_FREE warning from Coverity */\n\tsipe_dialog_free((struct sip_dialog *) subscription);\n}\n\nvoid sipe_subscriptions_init(struct sipe_core_private *sipe_private)\n{\n\tsipe_private->subscriptions = g_hash_table_new_full(g_str_hash,\n\t\t\t\t\t\t\t    g_str_equal,\n\t\t\t\t\t\t\t    g_free,\n\t\t\t\t\t\t\t    (GDestroyNotify)sipe_subscription_free);\n}\n\nstatic void sipe_unsubscribe_cb(SIPE_UNUSED_PARAMETER gpointer key,\n\t\t\t\tgpointer value, gpointer user_data)\n{\n\tstruct sip_subscription *subscription = value;\n\tstruct sip_dialog *dialog = &subscription->dialog;\n\tstruct sipe_core_private *sipe_private = user_data;\n\tgchar *contact = get_contact(sipe_private);\n\tgchar *hdr = g_strdup_printf(\n\t\t\"Event: %s\\r\\n\"\n\t\t\"Expires: 0\\r\\n\"\n\t\t\"Contact: %s\\r\\n\", subscription->event, contact);\n\tg_free(contact);\n\n\t/* Rate limit to max. 25 requests per seconds */\n\tg_usleep(1000000 / 25);\n\n\tsip_transport_subscribe(sipe_private,\n\t\t\t\tdialog->with,\n\t\t\t\thdr,\n\t\t\t\tNULL,\n\t\t\t\tdialog,\n\t\t\t\tNULL);\n\n\tg_free(hdr);\n}\n\nvoid sipe_subscriptions_unsubscribe(struct sipe_core_private *sipe_private)\n{\n\t/* unsubscribe all */\n\tg_hash_table_foreach(sipe_private->subscriptions,\n\t\t\t     sipe_unsubscribe_cb,\n\t\t\t     sipe_private);\n\n}\n\nvoid sipe_subscriptions_destroy(struct sipe_core_private *sipe_private)\n{\n\tg_hash_table_destroy(sipe_private->subscriptions);\n}\n\nstatic void sipe_subscription_remove(struct sipe_core_private *sipe_private,\n\t\t\t\t     const gchar *key)\n{\n\tif (g_hash_table_lookup(sipe_private->subscriptions, key)) {\n\t\tg_hash_table_remove(sipe_private->subscriptions, key);\n\t\tSIPE_DEBUG_INFO(\"sipe_subscription_remove: %s\", key);\n\t}\n}\n\n/**\n * Generate subscription key\n *\n * @param event event name   (must not by @c NULL)\n * @param uri   presence URI (ignored if @c event != \"presence\")\n *\n * @return key string. Must be g_free()'d after use.\n */\nstatic gchar *sipe_subscription_key(const gchar *event,\n\t\t\t\t    const gchar *uri)\n{\n\tif (!g_ascii_strcasecmp(event, \"presence\"))\n\t\t/* Subscription is identified by <presence><uri> key */\n\t\treturn(sipe_utils_presence_key(uri));\n\telse\n\t\t/* Subscription is identified by <event> key */\n\t\treturn(g_strdup_printf(\"<%s>\", event));\n}\n\nstatic struct sip_dialog *sipe_subscribe_dialog(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\tconst gchar *key)\n{\n\tstruct sip_dialog *dialog = g_hash_table_lookup(sipe_private->subscriptions,\n\t\t\t\t\t\t\tkey);\n\tSIPE_DEBUG_INFO(\"sipe_subscribe_dialog: dialog for '%s' is %s\", key, dialog ? \"not NULL\" : \"NULL\");\n\treturn(dialog);\n}\n\nstatic void sipe_subscription_expiration(struct sipe_core_private *sipe_private,\n\t\t\t\t\t struct sipmsg *msg,\n\t\t\t\t\t const gchar *event);\nstatic gboolean process_subscribe_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\t   struct sipmsg *msg,\n\t\t\t\t\t   struct transaction *trans)\n{\n\tconst gchar *event = sipmsg_find_event_header(msg);\n\n\t/* No Event header - error or 2005 Public IM Connectivity (PIC) */\n\tif (!event) {\n\t\tstruct sipmsg *request_msg = trans->msg;\n\t\tevent = sipmsg_find_event_header(request_msg);\n\t}\n\n\tif (event) {\n\t\tgchar *with = sipmsg_parse_to_address(msg);\n\t\tconst gchar *subscription_state = sipmsg_find_header(msg, \"subscription-state\");\n\t\tgboolean terminated = subscription_state && strstr(subscription_state, \"terminated\");\n\t\tgchar *key = sipe_subscription_key(event, with);\n\n\t\t/*\n\t\t * @TODO: does the server send this only for one-off\n\t\t *        subscriptions, i.e. the ones which anyway\n\t\t *        have \"Expires: 0\"?\n\t\t */\n\t\tif (terminated)\n\t\t\tSIPE_DEBUG_INFO(\"process_subscribe_response: subscription '%s' to '%s' was terminated\",\n\t\t\t\t\tevent, with);\n\n\t\t/* 400 Bad request */\n\t\tif (msg->response == 400) {\n\n\t\t\tSIPE_DEBUG_INFO(\"process_subscribe_response: subscription '%s' to '%s' failed\",\n\t\t\t\t\tevent, with);\n\n\t\t\tsipe_subscription_remove(sipe_private, key);\n\n\t\t\tif (sipe_strcase_equal(event, \"presence\")) {\n\t\t\t\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t  _(\"Presence subscription failed!\"),\n\t\t\t\t\t\t\t  _(\"One or more buddies will therefore permanently show as offline.\\n\\nPlease check that there are no corrupted SIP URIs in your contacts list.\"));\n\t\t\t}\n\n\t\t/* 481 Call Leg Does Not Exist */\n\t\t} else if ((msg->response == 481) || terminated) {\n\t\t\tsipe_subscription_remove(sipe_private, key);\n\n\t\t/* 488 Not acceptable here */\n\t\t} else if (msg->response == 488) {\n\n\t\t\tSIPE_DEBUG_INFO(\"process_subscribe_response: subscription '%s' to '%s' was rejected\",\n\t\t\t\t\tevent, with);\n\n\t\t\tsipe_subscription_remove(sipe_private, key);\n\n\t\t\tif (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007) &&\n\t\t\t    sipe_strcase_equal(event, \"vnd-microsoft-roaming-contacts\")) {\n\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"no contact list available - assuming Lync 2013+ and Unified Contact Store (UCS)\");\n\t\t\t\tSIPE_CORE_PRIVATE_FLAG_SET(LYNC2013);\n\t\t\t\tsipe_ucs_init(sipe_private, TRUE);\n\t\t\t}\n\n\t\t/* create/store subscription dialog if not yet */\n\t\t} else if (msg->response == 200) {\n\t\t\tstruct sip_dialog *dialog = sipe_subscribe_dialog(sipe_private, key);\n\n\t\t\tif (!dialog) {\n\t\t\t\tstruct sip_subscription *subscription = g_new0(struct sip_subscription, 1);\n\n\t\t\t\tSIPE_DEBUG_INFO(\"process_subscribe_response: subscription dialog added for event '%s'\",\n\t\t\t\t\t\tkey);\n\n\t\t\t\tg_hash_table_insert(sipe_private->subscriptions,\n\t\t\t\t\t\t    key,\n\t\t\t\t\t\t    subscription);\n\t\t\t\tkey = NULL; /* table takes ownership of key */\n\n\t\t\t\tsubscription->dialog.callid = g_strdup(sipmsg_find_call_id_header(msg));\n\t\t\t\tsubscription->dialog.cseq   = sipmsg_parse_cseq(msg);\n\t\t\t\tsubscription->dialog.with   = g_strdup(with);\n\t\t\t\tsubscription->event         = g_strdup(event);\n\n\t\t\t\tdialog = &subscription->dialog;\n\t\t\t}\n\n\t\t\tsipe_dialog_parse(dialog, msg, TRUE);\n\n\t\t\tsipe_subscription_expiration(sipe_private, msg, event);\n\t\t}\n\t\tg_free(key);\n\t\tg_free(with);\n\t}\n\n\tif (sipmsg_find_header(msg, \"ms-piggyback-cseq\"))\n\t\tprocess_incoming_notify(sipe_private, msg);\n\n\treturn(TRUE);\n}\n\n/**\n * common subscription code\n */\nstatic void sipe_subscribe(struct sipe_core_private *sipe_private,\n\t\t\t   const gchar *uri,\n\t\t\t   const gchar *event,\n\t\t\t   const gchar *accept,\n\t\t\t   const gchar *addheaders,\n\t\t\t   const gchar *body,\n\t\t\t   struct sip_dialog *dialog)\n{\n\tgchar *contact = get_contact(sipe_private);\n\tgchar *hdr = g_strdup_printf(\n\t\t\"Event: %s\\r\\n\"\n\t\t\"Accept: %s\\r\\n\"\n\t\t\"Supported: com.microsoft.autoextend\\r\\n\"\n\t\t\"Supported: ms-benotify\\r\\n\"\n\t\t\"Proxy-Require: ms-benotify\\r\\n\"\n\t\t\"Supported: ms-piggyback-first-notify\\r\\n\"\n\t\t\"%s\"\n\t\t\"Contact: %s\\r\\n\",\n\t\tevent,\n\t\taccept,\n\t\taddheaders ? addheaders : \"\",\n\t\tcontact);\n\tg_free(contact);\n\n\tsip_transport_subscribe(sipe_private,\n\t\t\t\turi,\n\t\t\t\thdr,\n\t\t\t\tbody,\n\t\t\t\tdialog,\n\t\t\t\tprocess_subscribe_response);\n\tg_free(hdr);\n}\n\n/**\n * common subscription code for self-subscriptions\n */\nstatic void sipe_subscribe_self(struct sipe_core_private *sipe_private,\n\t\t\t\tconst gchar *event,\n\t\t\t\tconst gchar *accept,\n\t\t\t\tconst gchar *addheaders,\n\t\t\t\tconst gchar *body)\n{\n\tgchar *self = sip_uri_self(sipe_private);\n\tgchar *key = sipe_subscription_key(event, self);\n\tstruct sip_dialog *dialog = sipe_subscribe_dialog(sipe_private, key);\n\n\tsipe_subscribe(sipe_private,\n\t\t       self,\n\t\t       event,\n\t\t       accept,\n\t\t       addheaders,\n\t\t       body,\n\t\t       dialog);\n\tg_free(key);\n\tg_free(self);\n}\n\nstatic void sipe_subscribe_presence_wpending(struct sipe_core_private *sipe_private,\n\t\t\t\t\t     SIPE_UNUSED_PARAMETER void *unused)\n{\n\tsipe_subscribe_self(sipe_private,\n\t\t\t    \"presence.wpending\",\n\t\t\t    \"text/xml+msrtc.wpending\",\n\t\t\t    NULL,\n\t\t\t    NULL);\n}\n\n/**\n * Subscribe roaming ACL\n */\nstatic void sipe_subscribe_roaming_acl(struct sipe_core_private *sipe_private,\n\t\t\t\t       SIPE_UNUSED_PARAMETER void *unused)\n{\n\tsipe_subscribe_self(sipe_private,\n\t\t\t    \"vnd-microsoft-roaming-ACL\",\n\t\t\t    \"application/vnd-microsoft-roaming-acls+xml\",\n\t\t\t    NULL,\n\t\t\t    NULL);\n}\n\n/**\n * Subscribe roaming contacts\n */\nstatic void sipe_subscribe_roaming_contacts(struct sipe_core_private *sipe_private,\n\t\t\t\t\t    SIPE_UNUSED_PARAMETER void *unused)\n{\n\tconst gchar *addheaders = NULL;\n\n\t/* indicate that we support Unified Contact Store (UCS) */\n\tif (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007))\n\t\taddheaders = \"Supported: ms-ucs\\r\\n\";\n\tsipe_subscribe_self(sipe_private,\n\t\t\t    \"vnd-microsoft-roaming-contacts\",\n\t\t\t    \"application/vnd-microsoft-roaming-contacts+xml\",\n\t\t\t    addheaders,\n\t\t\t    NULL);\n}\n\n/**\n *  OCS 2005 version\n */\nstatic void sipe_subscribe_roaming_provisioning(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\tSIPE_UNUSED_PARAMETER void *unused)\n{\n\tsipe_subscribe_self(sipe_private,\n\t\t\t    \"vnd-microsoft-provisioning\",\n\t\t\t    \"application/vnd-microsoft-roaming-provisioning+xml\",\n\t\t\t    \"Expires: 0\\r\\n\",\n\t\t\t    NULL);\n}\n\n/**\n * Subscription for provisioning information to help with initial\n * configuration. This subscription is a one-time query (denoted by the\n * Expires header, which asks for 0 seconds for the subscription lifetime).\n * This subscription asks for server configuration, meeting policies, and\n * policy settings that Communicator must enforce.\n */\nstatic void sipe_subscribe_roaming_provisioning_v2(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t   SIPE_UNUSED_PARAMETER void *unused)\n{\n\tsipe_subscribe_self(sipe_private,\n\t\t\t    \"vnd-microsoft-provisioning-v2\",\n\t\t\t    \"application/vnd-microsoft-roaming-provisioning-v2+xml\",\n\t\t\t    \"Expires: 0\\r\\n\"\n\t\t\t    \"Content-Type: application/vnd-microsoft-roaming-provisioning-v2+xml\\r\\n\",\n\t\t\t    \"<provisioningGroupList xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/provisioninggrouplist\\\">\"\n\t\t\t    \" <provisioningGroup name=\\\"ServerConfiguration\\\"/>\"\n\t\t\t    \" <provisioningGroup name=\\\"meetingPolicy\\\"/>\"\n\t\t\t    \" <provisioningGroup name=\\\"persistentChatConfiguration\\\"/>\"\n\t\t\t    \" <provisioningGroup name=\\\"ucPolicy\\\"/>\"\n\t\t\t    \"</provisioningGroupList>\");\n}\n\n/**\n * To request for presence information about the user, access level settings\n * that have already been configured by the user to control who has access to\n * what information, and the list of contacts who currently have outstanding\n * subscriptions.\n *\n * We wait for (BE)NOTIFY messages with some info change (categories,\n * containers, subscribers)\n */\nstatic void sipe_subscribe_roaming_self(struct sipe_core_private *sipe_private,\n\t\t\t\t\tSIPE_UNUSED_PARAMETER void *unused)\n{\n\tsipe_subscribe_self(sipe_private,\n\t\t\t    \"vnd-microsoft-roaming-self\",\n\t\t\t    \"application/vnd-microsoft-roaming-self+xml\",\n\t\t\t    \"Content-Type: application/vnd-microsoft-roaming-self+xml\\r\\n\",\n\t\t\t    \"<roamingList xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/roaming-self\\\">\"\n\t\t\t    \"<roaming type=\\\"categories\\\"/>\"\n\t\t\t    \"<roaming type=\\\"containers\\\"/>\"\n\t\t\t    \"<roaming type=\\\"subscribers\\\"/></roamingList>\");\n}\n\nstatic void sipe_presence_timeout_mime_cb(gpointer user_data,\n\t\t\t\t\t  SIPE_UNUSED_PARAMETER const GSList *fields,\n\t\t\t\t\t  const gchar *body,\n\t\t\t\t\t  gsize length)\n{\n\tGSList **buddies = user_data;\n\tsipe_xml *xml = sipe_xml_parse(body, length);\n\n\tif (xml && !sipe_strequal(sipe_xml_name(xml), \"list\")) {\n\t\tconst gchar *uri = sipe_xml_attribute(xml, \"uri\");\n\t\tconst sipe_xml *xn_category;\n\n\t\t/**\n\t\t * automaton: presence is never expected to change\n\t\t *\n\t\t * see: http://msdn.microsoft.com/en-us/library/ee354295(office.13).aspx\n\t\t */\n\t\tfor (xn_category = sipe_xml_child(xml, \"category\");\n\t\t     xn_category;\n\t\t     xn_category = sipe_xml_twin(xn_category)) {\n\t\t\tif (sipe_strequal(sipe_xml_attribute(xn_category, \"name\"),\n\t\t\t\t\t  \"contactCard\")) {\n\t\t\t\tconst sipe_xml *node = sipe_xml_child(xn_category, \"contactCard/automaton\");\n\t\t\t\tif (node) {\n\t\t\t\t\tchar *boolean = sipe_xml_data(node);\n\t\t\t\t\tif (sipe_strequal(boolean, \"true\")) {\n\t\t\t\t\t\tSIPE_DEBUG_INFO(\"sipe_process_presence_timeout: %s is an automaton: - not subscribing to presence updates\",\n\t\t\t\t\t\t\t\turi);\n\t\t\t\t\t\turi = NULL;\n\t\t\t\t\t}\n\t\t\t\t\tg_free(boolean);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (uri) {\n\t\t\t*buddies = g_slist_append(*buddies, sip_uri(uri));\n\t\t}\n\t}\n\n\tsipe_xml_free(xml);\n}\n\nstatic void sipe_subscribe_presence_batched_schedule(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t     const gchar *action_name,\n\t\t\t\t\t\t     const gchar *who,\n\t\t\t\t\t\t     GSList *buddies,\n\t\t\t\t\t\t     int timeout);\nstatic void sipe_process_presence_timeout(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  struct sipmsg *msg,\n\t\t\t\t\t  const gchar *who,\n\t\t\t\t\t  int timeout)\n{\n\tconst char *ctype = sipmsg_find_content_type_header(msg);\n\tgchar *action_name = sipe_utils_presence_key(who);\n\n\tSIPE_DEBUG_INFO(\"sipe_process_presence_timeout: Content-Type: %s\", ctype ? ctype : \"\");\n\n\tif (ctype &&\n\t    strstr(ctype, \"multipart\") &&\n\t    (strstr(ctype, \"application/rlmi+xml\") ||\n\t     strstr(ctype, \"application/msrtc-event-categories+xml\"))) {\n\t\tGSList *buddies = NULL;\n\n\t\tsipe_mime_parts_foreach(ctype, msg->body, sipe_presence_timeout_mime_cb, &buddies);\n\n\t\tif (buddies)\n\t\t\tsipe_subscribe_presence_batched_schedule(sipe_private,\n\t\t\t\t\t\t\t\t action_name,\n\t\t\t\t\t\t\t\t who,\n\t\t\t\t\t\t\t\t buddies,\n\t\t\t\t\t\t\t\t timeout);\n\n\t} else {\n\t\tsipe_schedule_seconds(sipe_private,\n\t\t\t\t      action_name,\n\t\t\t\t      g_strdup(who),\n\t\t\t\t      timeout,\n\t\t\t\t      sipe_subscribe_presence_single_cb,\n\t\t\t\t      g_free);\n\t\tSIPE_DEBUG_INFO(\"Resubscription single contact with batched support(%s) in %d seconds\", who, timeout);\n\t}\n\tg_free(action_name);\n}\n\n/**\n * @param expires not respected if set to negative value (E.g. -1)\n */\nvoid sipe_subscribe_conference(struct sipe_core_private *sipe_private,\n\t\t\t       const gchar *id,\n\t\t\t       gboolean expires)\n{\n\tsipe_subscribe(sipe_private,\n\t\t       id,\n\t\t       \"conference\",\n\t\t       \"application/conference-info+xml\",\n\t\t       expires ? \"Expires: 0\\r\\n\" : NULL,\n\t\t       NULL,\n\t\t       NULL);\n}\n\n/**\n * code for presence subscription\n */\nstatic void sipe_subscribe_presence_buddy(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  const gchar *uri,\n\t\t\t\t\t  const gchar *request,\n\t\t\t\t\t  const gchar *body)\n{\n\tgchar *key = sipe_utils_presence_key(uri);\n\n\tsip_transport_subscribe(sipe_private,\n\t\t\t\turi,\n\t\t\t\trequest,\n\t\t\t\tbody,\n\t\t\t\tsipe_subscribe_dialog(sipe_private, key),\n\t\t\t\tprocess_subscribe_response);\n\n\tg_free(key);\n}\n\n/**\n * if to == NULL: initial single subscription\n *   OCS2005: send to URI\n *   OCS2007: send to self URI\n *\n * if to != NULL:\n * Single Category SUBSCRIBE [MS-PRES] ; To send when the server returns a 200 OK message with state=\"resubscribe\" in response.\n * The user sends a single SUBSCRIBE request to the subscribed contact.\n * The To-URI and the URI listed in the resource list MUST be the same for a single category SUBSCRIBE request.\n *\n */\nvoid sipe_subscribe_presence_single(struct sipe_core_private *sipe_private,\n\t\t\t\t    const gchar *uri,\n\t\t\t\t    const gchar *to)\n{\n\tgchar *self = NULL;\n\tgchar *contact = get_contact(sipe_private);\n\tgchar *request;\n\tgchar *content = NULL;\n\tconst gchar *additional = \"\";\n\tconst gchar *content_type = \"\";\n\tstruct sipe_buddy *sbuddy = sipe_buddy_find_by_uri(sipe_private,\n\t\t\t\t\t\t\t   uri);\n\n\tif (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {\n\t\tcontent_type = \"Content-Type: application/msrtc-adrl-categorylist+xml\\r\\n\";\n\t\tcontent = g_strdup_printf(\"<batchSub xmlns=\\\"http://schemas.microsoft.com/2006/01/sip/batch-subscribe\\\" uri=\\\"sip:%s\\\" name=\\\"\\\">\\n\"\n\t\t\t\t\t  \"<action name=\\\"subscribe\\\" id=\\\"63792024\\\"><adhocList>\\n\"\n\t\t\t\t\t  \"<resource uri=\\\"%s\\\"%s\\n\"\n\t\t\t\t\t  \"</adhocList>\\n\"\n\t\t\t\t\t  \"<categoryList xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/categorylist\\\">\\n\"\n\t\t\t\t\t  \"<category name=\\\"calendarData\\\"/>\\n\"\n\t\t\t\t\t  \"<category name=\\\"contactCard\\\"/>\\n\"\n\t\t\t\t\t  \"<category name=\\\"note\\\"/>\\n\"\n\t\t\t\t\t  \"<category name=\\\"state\\\"/>\\n\"\n\t\t\t\t\t  \"</categoryList>\\n\"\n\t\t\t\t\t  \"</action>\\n\"\n\t\t\t\t\t  \"</batchSub>\",\n\t\t\t\t\t  sipe_private->username,\n\t\t\t\t\t  uri,\n\t\t\t\t\t  sbuddy && sbuddy->just_added ? \"><context/></resource>\" : \"/>\");\n\t\tif (!to) {\n\t\t\tadditional = \"Require: adhoclist, categoryList\\r\\n\" \\\n\t\t\t\t     \"Supported: eventlist\\r\\n\";\n\t\t\tto = self = sip_uri_self(sipe_private);\n\t\t}\n\n\t} else {\n\t\tadditional = \"Supported: com.microsoft.autoextend\\r\\n\";\n\t\tif (!to)\n\t\t\tto = uri;\n\t}\n\n\tif (sbuddy)\n\t\tsbuddy->just_added = FALSE;\n\n\trequest = g_strdup_printf(\"Accept: application/msrtc-event-categories+xml, text/xml+msrtc.pidf, application/xpidf+xml, application/pidf+xml, application/rlmi+xml, multipart/related\\r\\n\"\n\t\t\t\t  \"Supported: ms-piggyback-first-notify\\r\\n\"\n\t\t\t\t  \"%s%sSupported: ms-benotify\\r\\n\"\n\t\t\t\t  \"Proxy-Require: ms-benotify\\r\\n\"\n\t\t\t\t  \"Event: presence\\r\\n\"\n\t\t\t\t  \"Contact: %s\\r\\n\",\n\t\t\t\t  additional,\n\t\t\t\t  content_type,\n\t\t\t\t  contact);\n\tg_free(contact);\n\n\tsipe_subscribe_presence_buddy(sipe_private, to, request, content);\n\n\tg_free(content);\n\tg_free(self);\n\tg_free(request);\n}\n\nvoid sipe_subscribe_presence_single_cb(struct sipe_core_private *sipe_private,\n\t\t\t\t       gpointer uri)\n{\n\tsipe_subscribe_presence_single(sipe_private, uri, NULL);\n}\n\n\n/**\n *   Support for Batch Category SUBSCRIBE [MS-PRES] - msrtc-event-categories+xml  OCS 2007\n *   Support for Batch Category SUBSCRIBE [MS-SIP] - adrl+xml LCS 2005\n *   The user sends an initial batched category SUBSCRIBE request against all contacts on his roaming list in only a request\n *   A batch category SUBSCRIBE request MUST have the same To-URI and From-URI.\n *   This header will be send only if adhoclist there is a \"Supported: adhoclist\" in REGISTER answer else will be send a Single Category SUBSCRIBE\n */\nstatic void sipe_subscribe_presence_batched_to(struct sipe_core_private *sipe_private,\n\t\t\t\t\t       gchar *resources_uri,\n\t\t\t\t\t       const gchar *to)\n{\n\tgchar *contact = get_contact(sipe_private);\n\tgchar *request;\n\tgchar *content;\n\tconst gchar *require = \"\";\n\tconst gchar *accept = \"\";\n\tconst gchar *autoextend = \"\";\n\tconst gchar *content_type;\n\n\tif (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {\n\t\trequire = \", categoryList\";\n\t\taccept = \", application/msrtc-event-categories+xml, application/xpidf+xml, application/pidf+xml\";\n                content_type = \"application/msrtc-adrl-categorylist+xml\";\n                content = g_strdup_printf(\"<batchSub xmlns=\\\"http://schemas.microsoft.com/2006/01/sip/batch-subscribe\\\" uri=\\\"sip:%s\\\" name=\\\"\\\">\\n\"\n\t\t\t\t\t  \"<action name=\\\"subscribe\\\" id=\\\"63792024\\\">\\n\"\n\t\t\t\t\t  \"<adhocList>\\n%s</adhocList>\\n\"\n\t\t\t\t\t  \"<categoryList xmlns=\\\"http://schemas.microsoft.com/2006/09/sip/categorylist\\\">\\n\"\n\t\t\t\t\t  \"<category name=\\\"calendarData\\\"/>\\n\"\n\t\t\t\t\t  \"<category name=\\\"contactCard\\\"/>\\n\"\n\t\t\t\t\t  \"<category name=\\\"note\\\"/>\\n\"\n\t\t\t\t\t  \"<category name=\\\"state\\\"/>\\n\"\n\t\t\t\t\t  \"</categoryList>\\n\"\n\t\t\t\t\t  \"</action>\\n\"\n\t\t\t\t\t  \"</batchSub>\",\n\t\t\t\t\t  sipe_private->username,\n\t\t\t\t\t  resources_uri);\n\t} else {\n                autoextend =  \"Supported: com.microsoft.autoextend\\r\\n\";\n\t\tcontent_type = \"application/adrl+xml\";\n        \tcontent = g_strdup_printf(\"<adhoclist xmlns=\\\"urn:ietf:params:xml:ns:adrl\\\" uri=\\\"sip:%s\\\" name=\\\"sip:%s\\\">\\n\"\n\t\t\t\t\t  \"<create xmlns=\\\"\\\">\\n%s</create>\\n\"\n\t\t\t\t\t  \"</adhoclist>\\n\",\n\t\t\t\t\t  sipe_private->username,\n\t\t\t\t\t  sipe_private->username,\n\t\t\t\t\t  resources_uri);\n\t}\n\tg_free(resources_uri);\n\n\trequest = g_strdup_printf(\"Require: adhoclist%s\\r\\n\"\n\t\t\t\t  \"Supported: eventlist\\r\\n\"\n\t\t\t\t  \"Accept:  application/rlmi+xml, multipart/related, text/xml+msrtc.pidf%s\\r\\n\"\n\t\t\t\t  \"Supported: ms-piggyback-first-notify\\r\\n\"\n\t\t\t\t  \"%sSupported: ms-benotify\\r\\n\"\n\t\t\t\t  \"Proxy-Require: ms-benotify\\r\\n\"\n\t\t\t\t  \"Event: presence\\r\\n\"\n\t\t\t\t  \"Content-Type: %s\\r\\n\"\n\t\t\t\t  \"Contact: %s\\r\\n\",\n\t\t\t\t  require,\n\t\t\t\t  accept,\n\t\t\t\t  autoextend,\n\t\t\t\t  content_type,\n\t\t\t\t  contact);\n\tg_free(contact);\n\n\tsipe_subscribe_presence_buddy(sipe_private, to, request, content);\n\n\tg_free(content);\n\tg_free(request);\n}\n\nstruct presence_batched_routed {\n\tgchar  *host;\n\tconst GSList *buddies; /* points to subscription->buddies */\n};\n\nstatic void sipe_subscribe_presence_batched_routed_free(gpointer payload)\n{\n\tstruct presence_batched_routed *data = payload;\n\tg_free(data->host);\n\tg_free(payload);\n}\n\nstatic void sipe_subscribe_presence_batched_routed(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t   gpointer payload)\n{\n\tstruct presence_batched_routed *data = payload;\n\tconst GSList *buddies = data->buddies;\n\tgchar *resources_uri = g_strdup(\"\");\n\twhile (buddies) {\n\t\tgchar *tmp = resources_uri;\n\t\tresources_uri = g_strdup_printf(\"%s<resource uri=\\\"%s\\\"/>\\n\", tmp, (char *) buddies->data);\n\t\tg_free(tmp);\n\t\tbuddies = buddies->next;\n\t}\n\tsipe_subscribe_presence_batched_to(sipe_private,\n\t\t\t\t\t   resources_uri,\n\t\t\t\t\t   data->host);\n}\n\nstatic void sipe_subscribe_presence_batched_schedule(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t     const gchar *action_name,\n\t\t\t\t\t\t     const gchar *who,\n\t\t\t\t\t\t     GSList *buddies,\n\t\t\t\t\t\t     int timeout)\n{\n\tstruct sip_subscription *subscription = g_hash_table_lookup(sipe_private->subscriptions,\n\t\t\t\t\t\t\t\t    action_name);\n\tstruct presence_batched_routed *payload = g_malloc(sizeof(struct presence_batched_routed));\n\n\tif (subscription->buddies) {\n\t\t/* merge old and new list */\n\t\tGSList *entry = buddies;\n\t\twhile (entry) {\n\t\t\tsubscription->buddies = sipe_utils_slist_insert_unique_sorted(subscription->buddies,\n\t\t\t\t\t\t\t\t\t\t      g_strdup(entry->data),\n\t\t\t\t\t\t\t\t\t\t      (GCompareFunc) g_ascii_strcasecmp,\n\t\t\t\t\t\t\t\t\t\t      g_free);\n\t\t\tentry = entry->next;\n\t\t}\n\t\tsipe_utils_slist_free_full(buddies, g_free);\n\t} else {\n\t\t/* no list yet, simply take ownership of whole list */\n\t\tsubscription->buddies = buddies;\n\t}\n\n\tpayload->host    = g_strdup(who);\n\tpayload->buddies = subscription->buddies;\n\tsipe_schedule_seconds(sipe_private,\n\t\t\t      action_name,\n\t\t\t      payload,\n\t\t\t      timeout,\n\t\t\t      sipe_subscribe_presence_batched_routed,\n\t\t\t      sipe_subscribe_presence_batched_routed_free);\n\tSIPE_DEBUG_INFO(\"Resubscription multiple contacts with batched support & route(%s) in %d\", who, timeout);\n}\n\nstatic void sipe_subscribe_resource_uri_with_context(const gchar *name,\n\t\t\t\t\t\t     gpointer value,\n\t\t\t\t\t\t     gchar **resources_uri)\n{\n\tstruct sipe_buddy *sbuddy = (struct sipe_buddy *)value;\n\tconst gchar *context = sbuddy && sbuddy->just_added ? \"><context/></resource>\" : \"/>\";\n\tgchar *tmp = *resources_uri;\n\n\t/* should be enough to include context one time */\n\tif (sbuddy)\n\t\tsbuddy->just_added = FALSE;\n\n\t*resources_uri = g_strdup_printf(\"%s<resource uri=\\\"%s\\\"%s\\n\", tmp, name, context);\n\tg_free(tmp);\n}\n\nstatic void sipe_subscribe_resource_uri(const char *name,\n\t\t\t\t\tSIPE_UNUSED_PARAMETER gpointer value,\n\t\t\t\t\tgchar **resources_uri)\n{\n\tgchar *tmp = *resources_uri;\n        *resources_uri = g_strdup_printf(\"%s<resource uri=\\\"%s\\\"/>\\n\", tmp, name);\n\tg_free(tmp);\n}\n\n/**\n  * A callback for g_hash_table_foreach\n  */\nstatic void schedule_buddy_resubscription_cb(char *buddy_name,\n\t\t\t\t\t     SIPE_UNUSED_PARAMETER struct sipe_buddy *buddy,\n\t\t\t\t\t     struct sipe_core_private *sipe_private)\n{\n\tguint time_range = (sipe_buddy_count(sipe_private) * 1000) / 25; /* time interval for 25 requests per sec. In msec. */\n\n\t/*\n\t * g_hash_table_size() can never return 0, otherwise this function\n\t * wouldn't be called :-) But to keep Coverity happy...\n\t */\n\tif (time_range) {\n\t\tgchar *action_name = sipe_utils_presence_key(buddy_name);\n\t\tguint timeout = ((guint) rand()) / (RAND_MAX / time_range) + 1; /* random period within the range but never 0! */\n\n\t\tsipe_schedule_mseconds(sipe_private,\n\t\t\t\t       action_name,\n\t\t\t\t       g_strdup(buddy_name),\n\t\t\t\t       timeout,\n\t\t\t\t       sipe_subscribe_presence_single_cb,\n\t\t\t\t       g_free);\n\t\tg_free(action_name);\n\t}\n}\n\nvoid sipe_subscribe_presence_initial(struct sipe_core_private *sipe_private)\n{\n\t/*\n\t * Subscribe to buddies, but only do it once.\n\t * We'll resubsribe to them based on the Expire field values.\n\t */\n\tif (!SIPE_CORE_PRIVATE_FLAG_IS(SUBSCRIBED_BUDDIES)) {\n\n\t\t/* Only try to subscribe if we have any buddies */\n\t\tif (sipe_buddy_count(sipe_private) > 0) {\n\t\t\tif (SIPE_CORE_PRIVATE_FLAG_IS(BATCHED_SUPPORT)) {\n\t\t\t\tgchar *to = sip_uri_self(sipe_private);\n\t\t\t\tgchar *resources_uri = g_strdup(\"\");\n\t\t\t\tif (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {\n\t\t\t\t\tsipe_buddy_foreach(sipe_private,\n\t\t\t\t\t\t\t   (GHFunc) sipe_subscribe_resource_uri_with_context,\n\t\t\t\t\t\t\t   &resources_uri);\n\t\t\t\t} else {\n\t\t\t\t\tsipe_buddy_foreach(sipe_private,\n\t\t\t\t\t\t\t   (GHFunc) sipe_subscribe_resource_uri,\n\t\t\t\t\t\t\t   &resources_uri);\n\t\t\t\t}\n\t\t\t\tsipe_subscribe_presence_batched_to(sipe_private, resources_uri, to);\n\t\t\t\tg_free(to);\n\n\t\t\t} else {\n\t\t\t\tsipe_buddy_foreach(sipe_private,\n\t\t\t\t\t\t   (GHFunc) schedule_buddy_resubscription_cb,\n\t\t\t\t\t\t   sipe_private);\n\t\t\t}\n\t\t}\n\n\t\tSIPE_CORE_PRIVATE_FLAG_SET(SUBSCRIBED_BUDDIES);\n\t}\n}\n\nvoid sipe_subscribe_poolfqdn_resource_uri(const char *host,\n\t\t\t\t\t  GSList *server,\n\t\t\t\t\t  struct sipe_core_private *sipe_private)\n{\n\tstruct presence_batched_routed *payload = g_malloc(sizeof(struct presence_batched_routed));\n\tSIPE_DEBUG_INFO(\"process_incoming_notify_rlmi_resub: pool(%s)\", host);\n\tpayload->host    = g_strdup(host);\n\tpayload->buddies = server;\n\tsipe_subscribe_presence_batched_routed(sipe_private,\n\t\t\t\t\t       payload);\n\tsipe_subscribe_presence_batched_routed_free(payload);\n\tsipe_utils_slist_free_full(server, g_free);\n}\n\n\n/*\n * subscription expiration handling\n */\nstruct event_subscription_data {\n\tconst gchar *event;\n\tsipe_schedule_action callback;\n\tguint flags;\n};\n\n#define EVENT_OCS2005 0x00000001\n#define EVENT_OCS2007 0x00000002\n\nstatic const struct event_subscription_data events_table[] =\n{\n\t/*\n\t * For 2007+ it does not make sence to subscribe to:\n\t *\n\t *   presence.wpending\n\t *   vnd-microsoft-roaming-ACL\n\t *   vnd-microsoft-provisioning (not v2)\n\t *\n\t * These are only needed as backward compatibility for older clients\n\t *\n\t * For 2005- we publish our initial statuses only after we received\n\t * our existing UserInfo data in response to self subscription.\n\t * Only in this case we won't override existing UserInfo data\n\t * set earlier or by other client on our behalf.\n\t *\n\t * For 2007+ we publish our initial statuses and calendar data only\n\t * after we received our existing publications in roaming_self.\n\t * Only in this case we know versions of current publications made\n\t * on our behalf.\n\t */\n\t{ \"presence.wpending\",              sipe_subscribe_presence_wpending,\n\t\t  EVENT_OCS2005                 },\n\t{ \"vnd-microsoft-roaming-ACL\",      sipe_subscribe_roaming_acl,\n\t\t  EVENT_OCS2005                 },\n\t{ \"vnd-microsoft-roaming-contacts\", sipe_subscribe_roaming_contacts,\n\t\t  EVENT_OCS2005 | EVENT_OCS2007 },\n\t{ \"vnd-microsoft-provisioning\",     sipe_subscribe_roaming_provisioning,\n\t\t  EVENT_OCS2005                 },\n\t{ \"vnd-microsoft-provisioning-v2\",  sipe_subscribe_roaming_provisioning_v2,\n\t\t  EVENT_OCS2007                 },\n\t{ \"vnd-microsoft-roaming-self\",     sipe_subscribe_roaming_self,\n\t\t  EVENT_OCS2007                 },\n\t{ NULL, NULL, 0 }\n};\n\nstatic void sipe_subscription_expiration(struct sipe_core_private *sipe_private,\n\t\t\t\t\t struct sipmsg *msg,\n\t\t\t\t\t const gchar *event)\n{\n\tconst gchar *expires_header = sipmsg_find_expires_header(msg);\n\tguint timeout = expires_header ? strtol(expires_header, NULL, 10) : 0;\n\n\tif (timeout) {\n\t\t/* 2 min ahead of expiration */\n\t\tif (timeout > 240) timeout -= 120;\n\n\t\tif (sipe_strcase_equal(event, \"presence\")) {\n\t\t\tgchar *who = sipmsg_parse_to_address(msg);\n\n\t\t\tif (SIPE_CORE_PRIVATE_FLAG_IS(BATCHED_SUPPORT)) {\n\t\t\t\tsipe_process_presence_timeout(sipe_private, msg, who, timeout);\n\t\t\t} else {\n\t\t\t\tgchar *action_name = sipe_utils_presence_key(who);\n\t\t\t\tsipe_schedule_seconds(sipe_private,\n\t\t\t\t\t\t      action_name,\n\t\t\t\t\t\t      g_strdup(who),\n\t\t\t\t\t\t      timeout,\n\t\t\t\t\t\t      sipe_subscribe_presence_single_cb,\n\t\t\t\t\t\t      g_free);\n\t\t\t\tg_free(action_name);\n\t\t\t\tSIPE_DEBUG_INFO(\"Resubscription single contact '%s' in %d seconds\", who, timeout);\n\t\t\t}\n\t\t\tg_free(who);\n\n\t\t} else {\n\t\t\tconst struct event_subscription_data *esd;\n\n\t\t\tfor (esd = events_table; esd->event; esd++) {\n\t\t\t\tif (sipe_strcase_equal(event, esd->event)) {\n\t\t\t\t\tgchar *action_name = g_strdup_printf(\"<%s>\", event);\n\t\t\t\t\tsipe_schedule_seconds(sipe_private,\n\t\t\t\t\t\t\t      action_name,\n\t\t\t\t\t\t\t      NULL,\n\t\t\t\t\t\t\t      timeout,\n\t\t\t\t\t\t\t      esd->callback,\n\t\t\t\t\t\t\t      NULL);\n\t\t\t\t\tg_free(action_name);\n\t\t\t\t\tSIPE_DEBUG_INFO(\"Resubscription to event '%s' in %d seconds\", event, timeout);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/*\n * Initial event subscription\n */\nvoid sipe_subscription_self_events(struct sipe_core_private *sipe_private)\n{\n\tconst guint mask = SIPE_CORE_PRIVATE_FLAG_IS(OCS2007) ? EVENT_OCS2007 : EVENT_OCS2005;\n\tconst struct event_subscription_data *esd;\n\n\t/* subscribe to those events which are selected for\n\t * this version and are allowed by the server */\n\tfor (esd = events_table; esd->event; esd++)\n\t\tif ((esd->flags & mask) &&\n\t\t    (g_slist_find_custom(sipe_private->allowed_events,\n\t\t\t\t\t esd->event,\n\t\t\t\t\t (GCompareFunc) g_ascii_strcasecmp) != NULL))\n\t\t\t(*esd->callback)(sipe_private, NULL);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-subscriptions.h",
    "content": "/**\n * @file sipe-subscriptions.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2013 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\nstruct sip_dialog;\n\n/**\n * Subscriptions subsystem\n */\nvoid sipe_subscriptions_init(struct sipe_core_private *sipe_private);\nvoid sipe_subscriptions_unsubscribe(struct sipe_core_private *sipe_private);\nvoid sipe_subscriptions_destroy(struct sipe_core_private *sipe_private);\n\n/**\n * Subscriptions\n */\nvoid sipe_subscribe_conference(struct sipe_core_private *sipe_private,\n\t\t\t       const gchar *id,\n\t\t\t       gboolean expires);\n\nvoid sipe_subscribe_presence_single(struct sipe_core_private *sipe_private,\n\t\t\t\t    const gchar *uri,\n\t\t\t\t    const gchar *to);\nvoid sipe_subscribe_presence_single_cb(struct sipe_core_private *sipe_private,\n\t\t\t\t       gpointer uri);\nvoid sipe_subscribe_presence_initial(struct sipe_core_private *sipe_private);\nvoid sipe_subscribe_poolfqdn_resource_uri(const gchar *host,\n\t\t\t\t\t  GSList *server,\n\t\t\t\t\t  struct sipe_core_private *sipe_private);\n\n/**\n * Subscribe to all events the server supports after first registration\n *\n * @param sipe_private SIPE core private data\n */\nvoid sipe_subscription_self_events(struct sipe_core_private *sipe_private);\n"
  },
  {
    "path": "src/core/sipe-svc.c",
    "content": "/**\n * @file sipe-svc.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2015 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * Specification references:\n *\n *   - [MS-SIPAE]:    http://msdn.microsoft.com/en-us/library/cc431510.aspx\n *   - [MS-OCAUTHWS]: http://msdn.microsoft.com/en-us/library/ff595592.aspx\n *   - MS Tech-Ed Europe 2010 \"UNC310: Microsoft Lync 2010 Technology Explained\"\n *     http://ecn.channel9.msdn.com/o9/te/Europe/2010/pptx/unc310.pptx\n */\n\n#include <stdlib.h>\n#include <string.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-http.h\"\n#include \"sipe-svc.h\"\n#include \"sipe-tls.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n#include \"uuid.h\"\n\n/* forward declaration */\nstruct svc_request;\ntypedef void (svc_callback)(struct sipe_core_private *sipe_private,\n\t\t\t    struct svc_request *data,\n\t\t\t    const gchar *raw,\n\t\t\t    sipe_xml *xml);\n\nstruct svc_request {\n\tsvc_callback *internal_cb;\n\tsipe_svc_callback *cb;\n\tgpointer *cb_data;\n\tstruct sipe_http_request *request;\n\tgchar *uri;\n};\n\nstruct sipe_svc {\n\tGSList *pending_requests;\n\tgboolean shutting_down;\n};\n\nstruct sipe_svc_session {\n\tstruct sipe_http_session *session;\n};\n\nstatic void sipe_svc_request_free(struct sipe_core_private *sipe_private,\n\t\t\t\t  struct svc_request *data)\n{\n\tif (data->request)\n\t\tsipe_http_request_cancel(data->request);\n\tif (data->cb)\n\t\t/* Callback: aborted */\n\t\t(*data->cb)(sipe_private, NULL, NULL, NULL, data->cb_data);\n\tg_free(data->uri);\n\tg_free(data);\n}\n\nvoid sipe_svc_free(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_svc *svc = sipe_private->svc;\n\tif (!svc)\n\t\treturn;\n\n\t/* Web Service stack is shutting down: reject all new requests */\n\tsvc->shutting_down = TRUE;\n\n\tif (svc->pending_requests) {\n\t\tGSList *entry = svc->pending_requests;\n\t\twhile (entry) {\n\t\t\tsipe_svc_request_free(sipe_private, entry->data);\n\t\t\tentry = entry->next;\n\t\t}\n\t\tg_slist_free(svc->pending_requests);\n\t}\n\n\tg_free(svc);\n\tsipe_private->svc = NULL;\n}\n\nstatic void sipe_svc_init(struct sipe_core_private *sipe_private)\n{\n\tif (sipe_private->svc)\n\t\treturn;\n\n\tsipe_private->svc = g_new0(struct sipe_svc, 1);\n}\n\nstruct sipe_svc_session *sipe_svc_session_start(void)\n{\n\tstruct sipe_svc_session *session = g_new0(struct sipe_svc_session, 1);\n\tsession->session = sipe_http_session_start();\n\treturn(session);\n}\n\nvoid sipe_svc_session_close(struct sipe_svc_session *session)\n{\n\tif (session) {\n\t\tsipe_http_session_close(session->session);\n\t\tg_free(session);\n\t}\n}\n\nstatic void sipe_svc_https_response(struct sipe_core_private *sipe_private,\n\t\t\t\t    guint status,\n\t\t\t\t    SIPE_UNUSED_PARAMETER GSList *headers,\n\t\t\t\t    const gchar *body,\n\t\t\t\t    gpointer callback_data)\n{\n\tstruct svc_request *data = callback_data;\n\tstruct sipe_svc *svc = sipe_private->svc;\n\n\tSIPE_DEBUG_INFO(\"sipe_svc_https_response: code %d\", status);\n\tdata->request = NULL;\n\n\tif ((status == SIPE_HTTP_STATUS_OK) && body) {\n\t\tsipe_xml *xml = sipe_xml_parse(body, strlen(body));\n\t\t/* Internal callback: success */\n\t\t(*data->internal_cb)(sipe_private, data, body, xml);\n\t\tsipe_xml_free(xml);\n\t} else {\n\t\t/* Internal callback: failed */\n\t\t(*data->internal_cb)(sipe_private, data, NULL, NULL);\n\t}\n\n\t/* Internal callback has already called this */\n\tdata->cb = NULL;\n\n\tsvc->pending_requests = g_slist_remove(svc->pending_requests,\n\t\t\t\t\t       data);\n\tsipe_svc_request_free(sipe_private, data);\n}\n\n/**\n * Send GET request when @c body is NULL, otherwise send POST request\n *\n * @param content_type MIME type for body content (ignored when body is @c NULL)\n * @param soap_action  SOAP action header value   (ignored when body is @c NULL)\n * @param body         body contents              (may be @c NULL)\n */\nstatic gboolean sipe_svc_https_request(struct sipe_core_private *sipe_private,\n\t\t\t\t       struct sipe_svc_session *session,\n\t\t\t\t       const gchar *uri,\n\t\t\t\t       const gchar *content_type,\n\t\t\t\t       const gchar *soap_action,\n\t\t\t\t       const gchar *body,\n\t\t\t\t       svc_callback *internal_callback,\n\t\t\t\t       sipe_svc_callback *callback,\n\t\t\t\t       gpointer callback_data)\n{\n\tstruct svc_request *data = g_new0(struct svc_request, 1);\n\tstruct sipe_http_request *request = NULL;\n\tstruct sipe_svc *svc;\n\n\tsipe_svc_init(sipe_private);\n\tsvc = sipe_private->svc;\n\n\tif (svc->shutting_down) {\n\t\tSIPE_DEBUG_ERROR(\"sipe_svc_https_request: new Web Service request during shutdown: THIS SHOULD NOT HAPPEN! Debugging information:\\n\"\n\t\t\t\t \"URI:    %s\\n\"\n\t\t\t\t \"Action: %s\\n\"\n\t\t\t\t \"Body:   %s\\n\",\n\t\t\t\t uri,\n\t\t\t\t soap_action ? soap_action : \"<NONE>\",\n\t\t\t\t body ? body : \"<EMPTY>\");\n\t} else {\n\t\tif (body) {\n\t\t\tgchar *headers = g_strdup_printf(\"SOAPAction: \\\"%s\\\"\\r\\n\",\n\t\t\t\t\t\t\t soap_action);\n\n\t\t\trequest = sipe_http_request_post(sipe_private,\n\t\t\t\t\t\t\t uri,\n\t\t\t\t\t\t\t headers,\n\t\t\t\t\t\t\t body,\n\t\t\t\t\t\t\t content_type,\n\t\t\t\t\t\t\t sipe_svc_https_response,\n\t\t\t\t\t\t\t data);\n\t\t\tg_free(headers);\n\n\t\t} else {\n\t\t\trequest = sipe_http_request_get(sipe_private,\n\t\t\t\t\t\t\turi,\n\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\tsipe_svc_https_response,\n\t\t\t\t\t\t\tdata);\n\t\t}\n\t}\n\n\tif (request) {\n\t\tdata->internal_cb = internal_callback;\n\t\tdata->cb          = callback;\n\t\tdata->cb_data     = callback_data;\n\t\tdata->request     = request;\n\t\tdata->uri         = g_strdup(uri);\n\n\t\tsvc->pending_requests = g_slist_prepend(svc->pending_requests,\n\t\t\t\t\t\t\tdata);\n\n\t\tsipe_http_request_session(request, session->session);\n\t\tsipe_http_request_ready(request);\n\n\t} else {\n\t\tSIPE_DEBUG_ERROR(\"failed to create HTTP connection to %s\", uri);\n\t\tg_free(data);\n\t}\n\n\treturn(request != NULL);\n}\n\nstatic gboolean sipe_svc_wsdl_request(struct sipe_core_private *sipe_private,\n\t\t\t\t      struct sipe_svc_session *session,\n\t\t\t\t      const gchar *uri,\n\t\t\t\t      const gchar *additional_ns,\n\t\t\t\t      const gchar *soap_action,\n\t\t\t\t      const gchar *wsse_security,\n\t\t\t\t      const gchar *soap_body,\n\t\t\t\t      const gchar *content_type,\n\t\t\t\t      svc_callback *internal_callback,\n\t\t\t\t      sipe_svc_callback *callback,\n\t\t\t\t      gpointer callback_data)\n{\n\t/* Only generate UUID & SOAP header if we have a security token */\n\tgchar *uuid = wsse_security ?\n\t\tgenerateUUIDfromEPID(wsse_security) :\n\t\tNULL;\n\tgchar *soap_header = wsse_security ?\n\t\tg_strdup_printf(\"<soap:Header>\"\n\t\t\t\t\" <wsa:To>%s</wsa:To>\"\n\t\t\t\t\" <wsa:ReplyTo>\"\n\t\t\t\t\"  <wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>\"\n\t\t\t\t\" </wsa:ReplyTo>\"\n\t\t\t\t\" <wsa:MessageID>uuid:%s</wsa:MessageID>\"\n\t\t\t\t\" <wsa:Action>%s</wsa:Action>\"\n\t\t\t\t\" <wsse:Security>%s</wsse:Security>\"\n\t\t\t\t\"</soap:Header>\",\n\t\t\t\turi,\n\t\t\t\tuuid,\n\t\t\t\tsoap_action,\n\t\t\t\twsse_security) :\n\t\tg_strdup(\"\");\n\tgchar *body = g_strdup_printf(\"<?xml version=\\\"1.0\\\"?>\\r\\n\"\n\t\t\t\t      \"<soap:Envelope %s\"\n\t\t\t\t      \" xmlns:auth=\\\"http://schemas.xmlsoap.org/ws/2006/12/authorization\\\"\"\n\t\t\t\t      \" xmlns:wsa=\\\"http://www.w3.org/2005/08/addressing\\\"\"\n\t\t\t\t      \" xmlns:wsp=\\\"http://schemas.xmlsoap.org/ws/2004/09/policy\\\"\"\n\t\t\t\t      \" xmlns:wsse=\\\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\\\"\"\n\t\t\t\t      \" xmlns:wsu=\\\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\\\"\"\n\t\t\t\t      \" >\"\n\t\t\t\t      \"%s\"\n\t\t\t\t      \" <soap:Body>%s</soap:Body>\"\n\t\t\t\t      \"</soap:Envelope>\",\n\t\t\t\t      additional_ns,\n\t\t\t\t      soap_header,\n\t\t\t\t      soap_body);\n\n\tgboolean ret = sipe_svc_https_request(sipe_private,\n\t\t\t\t\t      session,\n\t\t\t\t\t      uri,\n\t\t\t\t\t      content_type ? content_type : \"text/xml\",\n\t\t\t\t\t      soap_action,\n\t\t\t\t\t      body,\n\t\t\t\t\t      internal_callback,\n\t\t\t\t\t      callback,\n\t\t\t\t\t      callback_data);\n\tg_free(uuid);\n\tg_free(soap_header);\n\tg_free(body);\n\n\treturn(ret);\n}\n\nstatic gboolean new_soap_req(struct sipe_core_private *sipe_private,\n\t\t\t     struct sipe_svc_session *session,\n\t\t\t     const gchar *uri,\n\t\t\t     const gchar *soap_action,\n\t\t\t     const gchar *wsse_security,\n\t\t\t     const gchar *soap_body,\n\t\t\t     svc_callback *internal_callback,\n\t\t\t     sipe_svc_callback *callback,\n\t\t\t     gpointer callback_data)\n{\n\treturn(sipe_svc_wsdl_request(sipe_private,\n\t\t\t\t     session,\n\t\t\t\t     uri,\n\t\t\t\t     \"xmlns:saml=\\\"urn:oasis:names:tc:SAML:1.0:assertion\\\" \"\n\t\t\t\t     \"xmlns:soap=\\\"http://schemas.xmlsoap.org/soap/envelope/\\\" \"\n\t\t\t\t     \"xmlns:wst=\\\"http://docs.oasis-open.org/ws-sx/ws-trust/200512\\\"\",\n\t\t\t\t     soap_action,\n\t\t\t\t     wsse_security,\n\t\t\t\t     soap_body,\n\t\t\t\t     NULL,\n\t\t\t\t     internal_callback,\n\t\t\t\t     callback,\n\t\t\t\t     callback_data));\n}\n\nstatic void sipe_svc_wsdl_response(struct sipe_core_private *sipe_private,\n\t\t\t\t   struct svc_request *data,\n\t\t\t\t   const gchar *raw,\n\t\t\t\t   sipe_xml *xml)\n{\n\tif (xml) {\n\t\t/* Callback: success */\n\t\t(*data->cb)(sipe_private, data->uri, raw, xml, data->cb_data);\n\t} else {\n\t\t/* Callback: failed */\n\t\t(*data->cb)(sipe_private, data->uri, NULL, NULL, data->cb_data);\n\t}\n}\n\ngboolean sipe_svc_get_and_publish_cert(struct sipe_core_private *sipe_private,\n\t\t\t\t       struct sipe_svc_session *session,\n\t\t\t\t       const gchar *uri,\n\t\t\t\t       const gchar *wsse_security,\n\t\t\t\t       const gchar *certreq,\n\t\t\t\t       sipe_svc_callback *callback,\n\t\t\t\t       gpointer callback_data)\n{\n\tstruct sipe_tls_random id;\n\tgchar *id_base64;\n\tgchar *id_uuid;\n\tgchar *uuid = get_uuid(sipe_private);\n\tgchar *soap_body;\n\tgboolean ret;\n\n\t/* random request ID */\n\tsipe_tls_fill_random(&id, 256);\n\tid_base64 = g_base64_encode(id.buffer, id.length);\n\tsipe_tls_free_random(&id);\n\tid_uuid = generateUUIDfromEPID(id_base64);\n\tg_free(id_base64);\n\n\tsoap_body = g_strdup_printf(\"<GetAndPublishCert\"\n\t\t\t\t    \" xmlns=\\\"http://schemas.microsoft.com/OCS/AuthWebServices/\\\"\"\n\t\t\t\t    \" xmlns:wst=\\\"http://docs.oasis-open.org/ws-sx/ws-trust/200512/\\\"\"\n\t\t\t\t    \" xmlns:wstep=\\\"http://schemas.microsoft.com/windows/pki/2009/01/enrollment\\\"\"\n\t\t\t\t    \" DeviceId=\\\"{%s}\\\"\"\n\t\t\t\t    \" Entity=\\\"%s\\\"\"\n\t\t\t\t    \">\"\n\t\t\t\t    \" <wst:RequestSecurityToken>\"\n\t\t\t\t    \"  <wst:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3</wst:TokenType>\"\n\t\t\t\t    \"  <wst:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue</wst:RequestType>\"\n\t\t\t\t    \"  <wsse:BinarySecurityToken\"\n\t\t\t\t    \"   ValueType=\\\"http://schemas.microsoft.com/OCS/AuthWebServices.xsd#PKCS10\\\"\"\n\t\t\t\t    \"   EncodingType=\\\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd#Base64Binary\\\"\"\n\t\t\t\t    \"  >\\r\\n%s</wsse:BinarySecurityToken>\"\n\t\t\t\t    \"  <wstep:RequestID>%s</wstep:RequestID>\"\n\t\t\t\t    \" </wst:RequestSecurityToken>\"\n\t\t\t\t    \"</GetAndPublishCert>\",\n\t\t\t\t    uuid,\n\t\t\t\t    sipe_private->username,\n\t\t\t\t    certreq,\n\t\t\t\t    id_uuid);\n\tg_free(id_uuid);\n\tg_free(uuid);\n\n\tret = new_soap_req(sipe_private,\n\t\t\t   session,\n\t\t\t   uri,\n\t\t\t   \"http://schemas.microsoft.com/OCS/AuthWebServices/GetAndPublishCert\",\n\t\t\t   wsse_security,\n\t\t\t   soap_body,\n\t\t\t   sipe_svc_wsdl_response,\n\t\t\t   callback,\n\t\t\t   callback_data);\n\tg_free(soap_body);\n\n\treturn(ret);\n}\n\ngboolean sipe_svc_ab_entry_request(struct sipe_core_private *sipe_private,\n\t\t\t\t   struct sipe_svc_session *session,\n\t\t\t\t   const gchar *uri,\n\t\t\t\t   const gchar *wsse_security,\n\t\t\t\t   const gchar *search,\n\t\t\t\t   guint max_returns,\n\t\t\t\t   sipe_svc_callback *callback,\n\t\t\t\t   gpointer callback_data)\n{\n\tgboolean ret;\n\tgchar *soap_body = g_strdup_printf(\"<SearchAbEntry\"\n\t\t\t\t\t   \" xmlns=\\\"DistributionListExpander\\\"\"\n\t\t\t\t\t   \" xmlns:xsi=\\\"http://www.w3.org/2001/XMLSchema-instance\\\"\"\n\t\t\t\t\t   \" xmlns:soapenc=\\\"http://schemas.xmlsoap.org/soap/encoding/\\\"\"\n\t\t\t\t\t   \">\"\n\t\t\t\t\t   \" <AbEntryRequest>\"\n\t\t\t\t\t   \"  %s\"\n\t\t\t\t\t   \"  <Metadata>\"\n\t\t\t\t\t   \"   <FromDialPad>false</FromDialPad>\"\n\t\t\t\t\t   \"   <MaxResultNum>%d</MaxResultNum>\"\n\t\t\t\t\t   \"   <ReturnList>displayName,msRTCSIP-PrimaryUserAddress,title,telephoneNumber,homePhone,mobile,otherTelephone,mail,company,country,photoRelPath,photoSize,photoHash</ReturnList>\"\n\t\t\t\t\t   \"  </Metadata>\"\n\t\t\t\t\t   \" </AbEntryRequest>\"\n\t\t\t\t\t   \"</SearchAbEntry>\",\n\t\t\t\t\t   search,\n\t\t\t\t\t   max_returns);\n\n\tret = new_soap_req(sipe_private,\n\t\t\t   session,\n\t\t\t   uri,\n\t\t\t   \"DistributionListExpander/IAddressBook/SearchAbEntry\",\n\t\t\t   wsse_security,\n\t\t\t   soap_body,\n\t\t\t   sipe_svc_wsdl_response,\n\t\t\t   callback,\n\t\t\t   callback_data);\n\tg_free(soap_body);\n\n\treturn(ret);\n}\n\n/* Requests to login.microsoftonline.com & ADFS */\nstatic gboolean request_passport(struct sipe_core_private *sipe_private,\n\t\t\t\t struct sipe_svc_session *session,\n\t\t\t\t const gchar *service_uri,\n\t\t\t\t const gchar *auth_uri,\n\t\t\t\t const gchar *wsse_security,\n\t\t\t\t const gchar *content_type,\n\t\t\t\t const gchar *request_extension,\n\t\t\t\t sipe_svc_callback *callback,\n\t\t\t\t gpointer callback_data)\n{\n\tgchar *soap_body = g_strdup_printf(\"<wst:RequestSecurityToken>\"\n\t\t\t\t\t   \" <wst:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</wst:RequestType>\"\n\t\t\t\t\t   \" <wsp:AppliesTo>\"\n\t\t\t\t\t   \"  <wsa:EndpointReference>\"\n\t\t\t\t\t   \"   <wsa:Address>%s</wsa:Address>\"\n\t\t\t\t\t   \"  </wsa:EndpointReference>\"\n\t\t\t\t\t   \" </wsp:AppliesTo>\"\n\t\t\t\t\t   \" %s\"\n\t\t\t\t\t   \"</wst:RequestSecurityToken>\",\n\t\t\t\t\t   service_uri,\n\t\t\t\t\t   request_extension ? request_extension : \"\");\n\n\tgboolean ret = sipe_svc_wsdl_request(sipe_private,\n\t\t\t\t\t     session,\n\t\t\t\t\t     auth_uri,\n\t\t\t\t\t     \"xmlns:soap=\\\"http://www.w3.org/2003/05/soap-envelope\\\" \"\n\t\t\t\t\t     \"xmlns:wst=\\\"http://schemas.xmlsoap.org/ws/2005/02/trust\\\"\",\n\t\t\t\t\t     \"http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue\",\n\t\t\t\t\t     wsse_security,\n\t\t\t\t\t     soap_body,\n\t\t\t\t\t     content_type,\n\t\t\t\t\t     sipe_svc_wsdl_response,\n\t\t\t\t\t     callback,\n\t\t\t\t\t     callback_data);\n\tg_free(soap_body);\n\n\treturn(ret);\n}\n\nstatic gboolean request_user_password(struct sipe_core_private *sipe_private,\n\t\t\t\t      struct sipe_svc_session *session,\n\t\t\t\t      const gchar *service_uri,\n\t\t\t\t      const gchar *auth_uri,\n\t\t\t\t      const gchar *content_type,\n\t\t\t\t      const gchar *request_extension,\n\t\t\t\t      sipe_svc_callback *callback,\n\t\t\t\t      gpointer callback_data)\n{\n\t/* Only cleartext passwords seem to be accepted... */\n\tgchar *wsse_security = g_markup_printf_escaped(\"<wsse:UsernameToken>\"\n\t\t\t\t\t\t       \" <wsse:Username>%s</wsse:Username>\"\n\t\t\t\t\t\t       \" <wsse:Password>%s</wsse:Password>\"\n\t\t\t\t\t\t       \"</wsse:UsernameToken>\",\n\t\t\t\t\t\t       sipe_private->authuser ? sipe_private->authuser : sipe_private->username,\n\t\t\t\t\t\t       sipe_private->password ? sipe_private->password : \"\");\n\n\tgboolean ret = request_passport(sipe_private,\n\t\t\t\t\tsession,\n\t\t\t\t\tservice_uri,\n\t\t\t\t\tauth_uri,\n\t\t\t\t\twsse_security,\n\t\t\t\t\tcontent_type,\n\t\t\t\t\trequest_extension,\n\t\t\t\t\tcallback,\n\t\t\t\t\tcallback_data);\n\tg_free(wsse_security);\n\n\treturn(ret);\n}\n\ngboolean sipe_svc_webticket_adfs(struct sipe_core_private *sipe_private,\n\t\t\t\t struct sipe_svc_session *session,\n\t\t\t\t const gchar *adfs_uri,\n\t\t\t\t sipe_svc_callback *callback,\n\t\t\t\t gpointer callback_data)\n{\n\treturn(request_user_password(sipe_private,\n\t\t\t\t     session,\n\t\t\t\t     \"urn:federation:MicrosoftOnline\",\n\t\t\t\t     adfs_uri,\n\t\t\t\t     /* ADFS is special, *sigh* */\n\t\t\t\t     \"application/soap+xml; charset=utf-8\",\n\t\t\t\t     \"<wst:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</wst:KeyType>\",\n\t\t\t\t     callback,\n\t\t\t\t     callback_data));\n}\n\n#define LMC_URI \"https://login.microsoftonline.com:443/RST2.srf\"\n\ngboolean sipe_svc_webticket_lmc(struct sipe_core_private *sipe_private,\n\t\t\t\tstruct sipe_svc_session *session,\n\t\t\t\tconst gchar *service_uri,\n\t\t\t\tsipe_svc_callback *callback,\n\t\t\t\tgpointer callback_data)\n{\n\treturn(request_user_password(sipe_private,\n\t\t\t\t     session,\n\t\t\t\t     service_uri,\n\t\t\t\t     LMC_URI,\n\t\t\t\t     NULL,\n\t\t\t\t     NULL,\n\t\t\t\t     callback,\n\t\t\t\t     callback_data));\n}\n\ngboolean sipe_svc_webticket_lmc_federated(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  struct sipe_svc_session *session,\n\t\t\t\t\t  const gchar *wsse_security,\n\t\t\t\t\t  const gchar *service_uri,\n\t\t\t\t\t  sipe_svc_callback *callback,\n\t\t\t\t\t  gpointer callback_data)\n{\n\treturn(request_passport(sipe_private,\n\t\t\t\tsession,\n\t\t\t\tservice_uri,\n\t\t\t\tLMC_URI,\n\t\t\t\twsse_security,\n\t\t\t\tNULL,\n\t\t\t\tNULL,\n\t\t\t\tcallback,\n\t\t\t\tcallback_data));\n}\n\ngboolean sipe_svc_webticket(struct sipe_core_private *sipe_private,\n\t\t\t    struct sipe_svc_session *session,\n\t\t\t    const gchar *uri,\n\t\t\t    const gchar *wsse_security,\n\t\t\t    const gchar *service_uri,\n\t\t\t    const struct sipe_tls_random *entropy,\n\t\t\t    sipe_svc_callback *callback,\n\t\t\t    gpointer callback_data)\n{\n\tgchar *uuid = get_uuid(sipe_private);\n\tgchar *secret = g_base64_encode(entropy->buffer, entropy->length);\n\tgchar *soap_body = g_strdup_printf(\"<wst:RequestSecurityToken Context=\\\"%s\\\">\"\n\t\t\t\t\t   \" <wst:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1</wst:TokenType>\"\n\t\t\t\t\t   \" <wst:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</wst:RequestType>\"\n\t\t\t\t\t   \" <wsp:AppliesTo>\"\n\t\t\t\t\t   \"  <wsa:EndpointReference>\"\n\t\t\t\t\t   \"   <wsa:Address>%s</wsa:Address>\"\n\t\t\t\t\t   \"  </wsa:EndpointReference>\"\n\t\t\t\t\t   \" </wsp:AppliesTo>\"\n\t\t\t\t\t   \" <wst:Claims Dialect=\\\"urn:component:Microsoft.Rtc.WebAuthentication.2010:authclaims\\\">\"\n\t\t\t\t\t   \"  <auth:ClaimType Uri=\\\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/uri\\\" Optional=\\\"false\\\">\"\n\t\t\t\t\t   \"   <auth:Value>sip:%s</auth:Value>\"\n\t\t\t\t\t   \"  </auth:ClaimType>\"\n\t\t\t\t\t   \" </wst:Claims>\"\n\t\t\t\t\t   \" <wst:Entropy>\"\n\t\t\t\t\t   \"  <wst:BinarySecret>%s</wst:BinarySecret>\"\n\t\t\t\t\t   \" </wst:Entropy>\"\n\t\t\t\t\t   \" <wst:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/SymmetricKey</wst:KeyType>\"\n\t\t\t\t\t   \"</wst:RequestSecurityToken>\",\n\t\t\t\t\t   uuid,\n\t\t\t\t\t   service_uri,\n\t\t\t\t\t   sipe_private->username,\n\t\t\t\t\t   secret);\n\n\tgboolean ret = new_soap_req(sipe_private,\n\t\t\t\t    session,\n\t\t\t\t    uri,\n\t\t\t\t    \"http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue\",\n\t\t\t\t    wsse_security,\n\t\t\t\t    soap_body,\n\t\t\t\t    sipe_svc_wsdl_response,\n\t\t\t\t    callback,\n\t\t\t\t    callback_data);\n\tg_free(soap_body);\n\tg_free(secret);\n\tg_free(uuid);\n\n\treturn(ret);\n}\n\nstatic void sipe_svc_metadata_response(struct sipe_core_private *sipe_private,\n\t\t\t\t       struct svc_request *data,\n\t\t\t\t       const gchar *raw,\n\t\t\t\t       sipe_xml *xml)\n{\n\tif (xml) {\n\t\t/* Callback: success */\n\t\t(*data->cb)(sipe_private, data->uri, raw, xml, data->cb_data);\n\t} else {\n\t\t/* Callback: failed */\n\t\t(*data->cb)(sipe_private, data->uri, NULL, NULL, data->cb_data);\n\t}\n}\n\ngboolean sipe_svc_realminfo(struct sipe_core_private *sipe_private,\n\t\t\t    struct sipe_svc_session *session,\n\t\t\t    sipe_svc_callback *callback,\n\t\t\t    gpointer callback_data)\n{\n\t/*\n\t * For some users RealmInfo response is different for authuser and\n\t * username. Use authuser, but only if it looks like \"user@domain\".\n\t */\n\tgchar *realminfo_uri = g_strdup_printf(\"https://login.microsoftonline.com/getuserrealm.srf?login=%s&xml=1\",\n\t\t\t\t\t       sipe_private->authuser && strchr(sipe_private->authuser, '@') ?\n\t\t\t\t\t       sipe_private->authuser : sipe_private->username);\n\tgboolean ret = sipe_svc_https_request(sipe_private,\n\t\t\t\t\t      session,\n\t\t\t\t\t      realminfo_uri,\n\t\t\t\t\t      NULL,\n\t\t\t\t\t      NULL,\n\t\t\t\t\t      NULL,\n\t\t\t\t\t      sipe_svc_metadata_response,\n\t\t\t\t\t      callback,\n\t\t\t\t\t      callback_data);\n\tg_free(realminfo_uri);\n\treturn(ret);\n}\n\ngboolean sipe_svc_metadata(struct sipe_core_private *sipe_private,\n\t\t\t   struct sipe_svc_session *session,\n\t\t\t   const gchar *uri,\n\t\t\t   sipe_svc_callback *callback,\n\t\t\t   gpointer callback_data)\n{\n\tgchar *mex_uri = g_strdup_printf(\"%s/mex\", uri);\n\tgboolean ret = sipe_svc_https_request(sipe_private,\n\t\t\t\t\t      session,\n\t\t\t\t\t      mex_uri,\n\t\t\t\t\t      NULL,\n\t\t\t\t\t      NULL,\n\t\t\t\t\t      NULL,\n\t\t\t\t\t      sipe_svc_metadata_response,\n\t\t\t\t\t      callback,\n\t\t\t\t\t      callback_data);\n\tg_free(mex_uri);\n\treturn(ret);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-svc.h",
    "content": "/**\n * @file sipe-svc.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2014 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/*\n * Interface dependencies:\n *\n * <glib.h>\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\nstruct sipe_svc_session;\nstruct sipe_tls_random;\nstruct _sipe_xml;\n\n/**\n * Service XML callback\n *\n * @param sipe_private  SIPE core private data\n * @param uri           service URI     (NULL when request aborted)\n * @param raw           raw XML data    (NULL when request failed)\n * @param xml           parsed XML data (NULL when request failed)\n * @param callback_data callback data\n */\ntypedef void (sipe_svc_callback)(struct sipe_core_private *sipe_private,\n\t\t\t\t const gchar *uri,\n\t\t\t\t const gchar *raw,\n\t\t\t\t struct _sipe_xml *xml,\n\t\t\t\t gpointer callback_data);\n\n/**\n * Start a session of related service requests\n *\n * @return Opaque session pointer\n */\nstruct sipe_svc_session *sipe_svc_session_start(void);\n\n/**\n * Close a session of related service requests\n *\n * @param session Opaque session pointer\n */\nvoid sipe_svc_session_close(struct sipe_svc_session *session);\n\n/**\n * Trigger fetch of Get & Publish certificate\n *\n * @param sipe_private  SIPE core private data\n * @param session       opaque session pointer\n * @param uri           service URI\n * @param wsse_security predefined authentication token\n * @param certreq       certificate request (Base64 encoded)\n * @param callback      callback function\n * @param callback_data callback data\n * @return              @c TRUE if certificate fetch was triggered\n */\ngboolean sipe_svc_get_and_publish_cert(struct sipe_core_private *sipe_private,\n\t\t\t\t       struct sipe_svc_session *session,\n\t\t\t\t       const gchar *uri,\n\t\t\t\t       const gchar *wsse_security,\n\t\t\t\t       const gchar *certreq,\n\t\t\t\t       sipe_svc_callback *callback,\n\t\t\t\t       gpointer callback_data);\n\n/**\n * Trigger [MS-DLX] address book entry search\n *\n * @param sipe_private  SIPE core private data\n * @param session       opaque session pointer\n * @param uri           service URI\n * @param wsse_security predefined authentication token\n * @param search        [MS-DLX] AbEntryRequest.ChangeSearchQuery/BasicSearch in XML\n * @param max_returns   how many entries to return\n * @param callback      callback function\n * @param callback_data callback data\n * @return              @c TRUE if search was triggered\n */\ngboolean sipe_svc_ab_entry_request(struct sipe_core_private *sipe_private,\n\t\t\t\t   struct sipe_svc_session *session,\n\t\t\t\t   const gchar *uri,\n\t\t\t\t   const gchar *wsse_security,\n\t\t\t\t   const gchar *search,\n\t\t\t\t   guint max_returns,\n\t\t\t\t   sipe_svc_callback *callback,\n\t\t\t\t   gpointer callback_data);\n\n/**\n * Trigger fetch of WebTicket security token\n *\n * @param sipe_private  SIPE core private data\n * @param session       opaque session pointer\n * @param uri           service URI\n * @param wsse_security predefined authentication token. May be @c NULL\n * @param service_uri   request token for this service URI\n * @param entropy       random bytes buffer for entropy\n * @param callback      callback function\n * @param callback_data callback data\n * @return              @c TRUE if token fetch was triggered\n */\ngboolean sipe_svc_webticket(struct sipe_core_private *sipe_private,\n\t\t\t    struct sipe_svc_session *session,\n\t\t\t    const gchar *uri,\n\t\t\t    const gchar *wsse_security,\n\t\t\t    const gchar *service_uri,\n\t\t\t    const struct sipe_tls_random *entropy,\n\t\t\t    sipe_svc_callback *callback,\n\t\t\t    gpointer callback_data);\n\n/**\n * Trigger fetch of WebTicket security token from ADFS of a federated domain\n *\n * @param sipe_private  SIPE core private data\n * @param session       opaque session pointer\n * @param adfs_uri      ADFS authentication URI\n * @param callback      callback function\n * @param callback_data callback data\n * @return              @c TRUE if token fetch was triggered\n */\ngboolean sipe_svc_webticket_adfs(struct sipe_core_private *sipe_private,\n\t\t\t\t struct sipe_svc_session *session,\n\t\t\t\t const gchar *adfs_uri,\n\t\t\t\t sipe_svc_callback *callback,\n\t\t\t\t gpointer callback_data);\n\n/**\n * Trigger fetch of WebTicket security token from login.microsoftonline.com\n *\n * @param sipe_private  SIPE core private data\n * @param session       opaque session pointer\n * @param service_uri   request token for this service URI\n * @param callback      callback function\n * @param callback_data callback data\n * @return              @c TRUE if token fetch was triggered\n */\ngboolean sipe_svc_webticket_lmc(struct sipe_core_private *sipe_private,\n\t\t\t\tstruct sipe_svc_session *session,\n\t\t\t\tconst gchar *service_uri,\n\t\t\t\tsipe_svc_callback *callback,\n\t\t\t\tgpointer callback_data);\n\n/**\n * Trigger fetch of WebTicket security token from login.microsoftonline.com\n * using a Web Ticket acquired\n *\n * @param sipe_private  SIPE core private data\n * @param session       opaque session pointer\n * @param wsse_security predefined authentication token. May be @c NULL\n * @param service_uri   request token for this service URI\n * @param callback      callback function\n * @param callback_data callback data\n * @return              @c TRUE if token fetch was triggered\n */\ngboolean sipe_svc_webticket_lmc_federated(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  struct sipe_svc_session *session,\n\t\t\t\t\t  const gchar *wsse_security,\n\t\t\t\t\t  const gchar *service_uri,\n\t\t\t\t\t  sipe_svc_callback *callback,\n\t\t\t\t\t  gpointer callback_data);\n\n/**\n * Trigger fetch of RealmInfo data from login.microsoftonline.com\n *\n * @param sipe_private  SIPE core private data\n * @param session       opaque session pointer\n * @param callback      callback function\n * @param callback_data callback data\n * @return              @c TRUE if data fetch was triggered\n */\ngboolean sipe_svc_realminfo(struct sipe_core_private *sipe_private,\n\t\t\t    struct sipe_svc_session *session,\n\t\t\t    sipe_svc_callback *callback,\n\t\t\t    gpointer callback_data);\n\n/**\n * Trigger fetch of service metadata\n *\n * @param sipe_private  SIPE core private data\n * @param session       opaque session pointer\n * @param uri           service URI\n * @param callback      callback function\n * @param callback_data callback data\n * @return              @c TRUE if metadata fetch was triggered\n */\ngboolean sipe_svc_metadata(struct sipe_core_private *sipe_private,\n\t\t\t   struct sipe_svc_session *session,\n\t\t\t   const gchar *uri,\n\t\t\t   sipe_svc_callback *callback,\n\t\t\t   gpointer callback_data);\n\n/**\n * Free service data\n *\n * @param sipe_private SIPE core private data\n */\nvoid sipe_svc_free(struct sipe_core_private *sipe_private);\n"
  },
  {
    "path": "src/core/sipe-tls-analyzer.c",
    "content": "/**\n * @file sipe-tls-analyzer.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2015 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * Takes Base64-encoded gssapi-data= values from TLS-DSK authentication attempt\n * on the command line and prints out the TLS message contents in human readable\n * format.\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <stdarg.h>\n\n#include <glib.h>\n#include <glib/gprintf.h>\n\n#include \"sipe-common.h\"\n#include \"sipe-utils.h\"\n#define _SIPE_COMPILING_ANALYZER\n#include \"sipe-tls.c\"\n\n/* stub functions */\nvoid sipe_backend_debug_literal(SIPE_UNUSED_PARAMETER sipe_debug_level level,\n\t\t\t\tconst gchar *msg)\n{\n\tprintf(\"%s\", msg);\n}\n\nvoid sipe_backend_debug(SIPE_UNUSED_PARAMETER sipe_debug_level level,\n\t\t\tconst gchar *format,\n\t\t\t...)\n{\n\tva_list ap;\n\tva_start(ap, format);\n\tvprintf(format, ap);\n\tva_end(ap);\n}\n\nint main(int argc, char *argv[])\n{\n\tstruct tls_internal_state *state;\n\n\tif (argc < 2) {\n\t\tfprintf(stderr, \"Usage: %s <gssapi-data> ...\\n\", argv[0]);\n\t\treturn(1);\n\t}\n\n\tstate = g_new0(struct tls_internal_state, 1);\n\tstate->debug = g_string_new(\"\");\n\n\twhile (--argc > 0) {\n\t\tconst gchar *base64 = *++argv;\n\t\tguchar *buffer;\n\n\t\tprintf(\"Base64: %s\\n\", base64);\n\t\tbuffer = g_base64_decode(base64, &state->common.in_length);\n\t\tif (buffer && state->common.in_length) {\n\t\t\tprintf(\"Decoded %\" G_GSIZE_FORMAT \" bytes\\n\",\n\t\t\t       state->common.in_length);\n\t\t\tstate->common.in_buffer = buffer;\n\t\t\ttls_record_parse(state, TRUE, 0);\n\t\t\tfree_parse_data(state);\n\t\t\tprintf(\"-------------------------------------------------------------------------------\\n\");\n\t\t\tg_free(buffer);\n\t\t} else {\n\t\t\tprintf(\"Corrupted Base64 - skipping\\n\");\n\t\t}\n\t}\n\n\tg_string_free(state->debug, TRUE);\n\tg_free(state);\n\n\treturn(0);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-tls-tester.c",
    "content": "/**\n * @file sipe-tls-tester.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * TLS handshake implementation (sipe-tls.c) tester\n *\n * Example test setup using OpenSSL:\n *\n * - Setting up the server certificate:\n *\n *    $ openssl req -new -keyout server.pem -out server.req\n *    $ openssl x509 -req -in server.req -signkey server.pem -out server.cert\n *\n * - Running the test server in one shell with same parameters used by Lync:\n *\n *    $ openssl s_server -accept 8443 -debug -msg \\\n *              -cert server.cert -key server.pem \\\n *              -tls1 -verify 0 [ -cipher <c1>[:<c2>...] ]\n *\n *   ciphers: RC4-MD5, RC4-SHA, AES128-SHA, AES256-SHA\n *\n * - Running the test program in another shell:\n *\n *    $ sipe_tls_tester\n *\n *   You can add <host>[:<port>] to connect to a server on another machine\n */\n\n#include <stdlib.h>\n#include <string.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <stdint.h>\n#include <time.h>\n#include <unistd.h>\n#include <errno.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <netdb.h>\n#include <poll.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\" /* coverity[hfa: FALSE] */\n#include \"sipe-backend.h\"\n#include \"sipe-cert-crypto.h\"\n#include \"sipe-crypt.h\"\n#include \"sipe-tls.h\"\n\n/*\n * Stubs\n */\ngboolean sipe_backend_debug_enabled(void)\n{\n\treturn(TRUE);\n}\n\nvoid sipe_backend_debug_literal(sipe_debug_level level,\n\t\t\t\tconst gchar *msg)\n{\n\tprintf(\"DEBUG(%d): %s\\n\", level, msg);\n}\n\nvoid sipe_backend_debug(sipe_debug_level level,\n\t\t\tconst gchar *format,\n\t\t\t...)\n{\n\tva_list ap;\n\tgchar *newformat = g_strdup_printf(\"DEBUG(%d): %s\\n\", level, format);\n\n\tva_start(ap, format);\n\tvprintf(newformat, ap);\n\tva_end(ap);\n\n\tg_free(newformat);\n}\n\n/* needed when linking against NSS */\nvoid md4sum(const uint8_t *data, uint32_t length, uint8_t *digest);\nvoid md4sum(SIPE_UNUSED_PARAMETER const uint8_t *data,\n\t    SIPE_UNUSED_PARAMETER uint32_t length,\n\t    SIPE_UNUSED_PARAMETER uint8_t *digest)\n{\n}\n\n/*\n * Tester code\n */\nstruct record {\n\tgsize length;\n\tguchar *msg;\n};\n\nstatic guchar *read_tls_record(int fd,\n\t\t\t       gsize *in_length)\n{\n\tGSList *fragments = NULL;\n\tguchar *merged    = NULL;\n\tgsize length      = 0;\n\tstatic gchar buffer[10000];\n\n\twhile (1) {\n\t\tstruct pollfd fds[] = {\n\t\t\t{ fd, POLLIN, 0 }\n\t\t};\n\t\tint result;\n\t\tstruct record *record;\n\n\t\t/* Read one chunk */\n\t\tresult = poll(fds, 1, 500 /* [milliseconds] */);\n\t\tif (result < 0) {\n\t\t\tprintf(\"poll failed: %s\\n\", strerror(errno));\n\t\t\tbreak;\n\t\t}\n\t\tif (result == 0) {\n\t\t\tif (!fragments) {\n\t\t\t\tprintf(\"timeout.\\n\");\n\t\t\t\tcontinue;\n\t\t\t} else {\n\t\t\t\tprintf(\"reading done.\\n\");\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tresult = read(fd, buffer, sizeof(buffer));\n\t\tif (result < 0) {\n\t\t\tprintf(\"read failed: %s\\n\", strerror(errno));\n\t\t\tbreak;\n\t\t}\n\t\tif (result == 0) {\n\t\t\tprintf(\"server closed connection: %s\\n\",\n\t\t\t       strerror(errno));\n\t\t\tbreak;\n\t\t}\n\n\t\tprintf(\"received %d bytes from server\\n\", result);\n\t\trecord = g_new0(struct record, 1);\n\t\trecord->length  = result;\n\t\trecord->msg     = g_memdup(buffer, result);\n\t\tlength         += result;\n\t\tfragments = g_slist_append(fragments, record);\n\t}\n\n\tif (fragments) {\n\t\tGSList *elem = fragments;\n\t\tguchar *p;\n\n\t\tprintf(\"received a total of %\" G_GSIZE_FORMAT \" bytes.\\n\",\n\t\t       length);\n\n\t\tp = merged = g_malloc(length);\n\t\tif (merged) {\n\t\t\twhile (elem) {\n\t\t\t\tstruct record *record = elem->data;\n\n\t\t\t\tmemcpy(p, record->msg, record->length);\n\t\t\t\tp += record->length;\n\t\t\t\tg_free(record->msg);\n\t\t\t\tg_free(record);\n\n\t\t\t\telem = elem->next;\n\t\t\t}\n\t\t} else {\n\t\t\tprintf(\"can't allocate %\" G_GSIZE_FORMAT \" bytes.\\n\",\n\t\t\t       length);\n\t\t}\n\n\t\tg_slist_free(fragments);\n\t}\n\n\t*in_length = length;\n\treturn(merged);\n}\n\nstatic void tls_handshake(struct sipe_tls_state *state,\n\t\t\t  int fd)\n{\n\tgboolean success = FALSE;\n\n\tprintf(\"TLS handshake starting...\\n\");\n\n\t/* generate next handshake message */\n\twhile (sipe_tls_next(state)) {\n\t\tint sent;\n\n\t\t/* handshake completed? */\n\t\tif (!state->out_buffer) {\n\t\t\tsuccess = TRUE;\n\t\t\tbreak;\n\t\t}\n\n\t\t/* send buffer to server */\n\t\tsent = write(fd, state->out_buffer, state->out_length);\n\t\tif (sent < 0) {\n\t\t\tprintf(\"write to server failed: %s\\n\",\n\t\t\t       strerror(errno));\n\t\t\tbreak;\n\t\t} else if ((unsigned int) sent < state->out_length) {\n\t\t\tprintf(\"could only write %d bytes, out of %\" G_GSIZE_FORMAT \"\\n\",\n\t\t\t       sent, state->out_length);\n\t\t\tbreak;\n\t\t}\n\n\t\t/* message sent, drop buffer */\n\t\tg_free(state->out_buffer);\n\t\tstate->out_buffer = NULL;\n\n\t\tstate->in_buffer = read_tls_record(fd, &state->in_length);\n\t\tif (!state->in_buffer) {\n\t\t\tprintf(\"end of data.\\n\");\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tprintf(\"TLS handshake %s.\\n\", success ? \"SUCCESSFUL\" : \"FAILED\");\n}\n\n\nstatic int tls_connect(const gchar *param)\n{\n\tgchar **parts = g_strsplit(param, \":\", 2);\n\tint fd = -1;\n\n\tif (parts[0]) {\n\t\tconst gchar *host = parts[0];\n\t\tconst gchar *port = parts[1] ? parts[1] : \"443\";\n\t\tstruct addrinfo hints;\n\t\tstruct addrinfo *result;\n\t\tint status;\n\n\t\tprintf(\"TLS connect to host '%s', port %s...\\n\",\n\t\t       host, port);\n\n\t\tmemset(&hints, 0, sizeof(struct addrinfo));\n\t\thints.ai_family = AF_UNSPEC;\n\t\thints.ai_socktype = SOCK_STREAM;\n\t\thints.ai_flags = 0;\n\t\thints.ai_protocol = 0;\n\t\tstatus = getaddrinfo(host, port, &hints, &result);\n\n\t\tif (status == 0) {\n\t\t\tstruct addrinfo *rp;\n\n\t\t\tfor (rp = result; rp != NULL; rp = rp->ai_next) {\n\t\t\t\tint sock = socket(rp->ai_family,\n\t\t\t\t\t\t  rp->ai_socktype,\n\t\t\t\t\t\t  rp->ai_protocol);\n\n\t\t\t\tif (sock < 0) continue;\n\n\t\t\t\tif (connect(sock,\n\t\t\t\t\t    rp->ai_addr,\n\t\t\t\t\t    rp->ai_addrlen) >= 0) {\n\t\t\t\t\t/* connected */\n\t\t\t\t\tprintf(\"connected to host '%s', port %s.\\n\",\n\t\t\t\t\t       host, port);\n\t\t\t\t\tfd = sock;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tfprintf(stderr, \"failed to connect: %s\\n\",\n\t\t\t\t\tstrerror(errno));\n\n\t\t\t\tclose(sock);\n\t\t\t}\n\t\t\tfreeaddrinfo(result);\n\n\t\t\tif (rp == NULL) {\n\t\t\t\tfprintf(stderr, \"couldn't connect to host '%s'!\\n\",\n\t\t\t\t\thost);\n\t\t\t}\n\t\t} else {\n\t\t\tfprintf(stderr, \"couldn't find host '%s': %s\\n\",\n\t\t\t\thost, gai_strerror(status));\n\t\t}\n\t} else {\n\t\tfprintf(stderr, \"corrupted host[:port] '%s'!\\n\", param);\n\t}\n\tg_strfreev(parts);\n\n\treturn(fd);\n}\n\nint main(int argc, char *argv[])\n{\n\tstruct sipe_cert_crypto *scc;\n\n\tsipe_crypto_init(FALSE);\n\tsrand(time(NULL));\n\n\tscc = sipe_cert_crypto_init();\n\tif (scc) {\n\t\tgpointer certificate;\n\t\tstruct sipe_tls_state *state;\n\n\t\tprintf(\"SIPE cert crypto backend initialized.\\n\");\n\n\t\tcertificate = sipe_cert_crypto_test_certificate(scc);\n\t\tstate = sipe_tls_start(certificate);\n\t\tif (state) {\n\t\t\tint fd;\n\n\t\t\tprintf(\"SIPE TLS initialized.\\n\");\n\n\t\t\tfd = tls_connect((argc > 1) ? argv[1] : \"localhost:8443\");\n\t\t\tif (fd >= 0) {\n\t\t\t\ttls_handshake(state, fd);\n\t\t\t\tclose(fd);\n\t\t\t}\n\n\t\t\tsipe_tls_free(state);\n\t\t}\n\n\t\tsipe_cert_crypto_destroy(certificate);\n\t\tsipe_cert_crypto_free(scc);\n\t}\n\tsipe_crypto_shutdown();\n\n\treturn(0);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-tls.c",
    "content": "/**\n * @file sipe-tls.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * TLS Protocol Version 1.0/1.1/1.2 - Handshake Messages\n *\n * TLS-DSK uses the handshake messages during authentication and session key\n * exchange. This module *ONLY* implements this part of the TLS specification!\n *\n * Specification references:\n *\n *   - RFC2246: http://www.ietf.org/rfc/rfc2246.txt\n *   - RFC3546: http://www.ietf.org/rfc/rfc3546.txt\n *   - RFC4346: http://www.ietf.org/rfc/rfc4346.txt\n *   - RFC5246: http://www.ietf.org/rfc/rfc5246.txt\n */\n\n#include <stdlib.h>\n#include <string.h>\n#include <stdarg.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-cert-crypto.h\"\n#include \"sipe-crypt.h\"\n#include \"sipe-digest.h\"\n#include \"sipe-svc.h\"\n#include \"sipe-tls.h\"\n\n/*\n * Private part of TLS state tracking\n */\nenum tls_handshake_state {\n\tTLS_HANDSHAKE_STATE_START,\n\tTLS_HANDSHAKE_STATE_SERVER_HELLO,\n\tTLS_HANDSHAKE_STATE_FINISHED,\n\tTLS_HANDSHAKE_STATE_COMPLETED,\n\tTLS_HANDSHAKE_STATE_FAILED\n};\n\nstruct tls_internal_state {\n\tstruct sipe_tls_state common;\n\tgpointer certificate;\n\tenum tls_handshake_state state;\n\tguchar *msg_current;\n\tgsize msg_remainder;\n\tGHashTable *data;\n\tGString *debug;\n\tgpointer md5_context;\n\tgpointer sha1_context;\n\tgpointer server_certificate;\n\tstruct sipe_tls_random client_random;\n\tstruct sipe_tls_random server_random;\n\tstruct sipe_tls_random pre_master_secret;\n\tgsize mac_length;\n\tgsize key_length;\n\tguchar *master_secret;\n\tguchar *key_block;\n\tguchar *tls_dsk_key_block;\n\tconst guchar *client_write_mac_secret;\n\tconst guchar *server_write_mac_secret;\n\tconst guchar *client_write_secret;\n\tconst guchar *server_write_secret;\n\tconst guchar *client_write_iv;\n\tconst guchar *server_write_iv;\n\tvoid (*mac_func)(const guchar *key, gsize key_length,\n\t\t\t const guchar *data, gsize data_length,\n\t\t\t guchar *digest);\n\tgpointer cipher_context;\n\tguint64 sequence_number;\n\tgboolean stream_cipher;\n\tgboolean encrypted;\n\tgboolean expected;\n};\n\n/*\n * TLS messages & layout descriptors\n */\n\n/* constants */\n#define TLS_VECTOR_MAX8       255 /* 2^8  - 1 */\n#define TLS_VECTOR_MAX16    65535 /* 2^16 - 1 */\n#define TLS_VECTOR_MAX24 16777215 /* 2^24 - 1 */\n\n#define TLS_PROTOCOL_VERSION_1_0 0x0301\n#define TLS_PROTOCOL_VERSION_1_1 0x0302\n#define TLS_PROTOCOL_VERSION_1_2 0x0303\n\n/* CipherSuites */\n#define TLS_RSA_EXPORT_WITH_RC4_40_MD5 0x0003\n#define TLS_RSA_WITH_RC4_128_MD5       0x0004\n#define TLS_RSA_WITH_RC4_128_SHA       0x0005\n#define TLS_RSA_WITH_AES_128_CBC_SHA   0x002F\n#define TLS_RSA_WITH_AES_256_CBC_SHA   0x0035\n\n#define TLS_AES_CBC_BLOCK_LENGTH 16 /* bytes */\n\n/* CompressionMethods */\n#define TLS_COMP_METHOD_NULL 0\n\n/* various array lengths */\n#define TLS_ARRAY_RANDOM_LENGTH        32\n#define TLS_ARRAY_MASTER_SECRET_LENGTH 48\n#define TLS_ARRAY_VERIFY_LENGTH        12\n\n#define TLS_RECORD_HEADER_LENGTH            5\n#define TLS_RECORD_OFFSET_TYPE              0\n#define TLS_RECORD_TYPE_CHANGE_CIPHER_SPEC 20\n#define TLS_RECORD_TYPE_HANDSHAKE          22\n#define TLS_RECORD_OFFSET_VERSION           1\n#define TLS_RECORD_OFFSET_LENGTH            3\n\n#define TLS_HANDSHAKE_HEADER_LENGTH             4\n#define TLS_HANDSHAKE_OFFSET_TYPE               0\n#define TLS_HANDSHAKE_TYPE_CLIENT_HELLO         1\n#define TLS_HANDSHAKE_TYPE_SERVER_HELLO         2\n#define TLS_HANDSHAKE_TYPE_CERTIFICATE         11\n#define TLS_HANDSHAKE_TYPE_CERTIFICATE_REQ     13\n#define TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE   14\n#define TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY  15\n#define TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE 16\n#define TLS_HANDSHAKE_TYPE_FINISHED            20\n#define TLS_HANDSHAKE_OFFSET_LENGTH             1\n\nstruct layout_descriptor;\ntypedef gboolean parse_func(struct tls_internal_state *state,\n\t\t\t    const struct layout_descriptor *desc);\n\n/* Defines the strictest alignment requirement */\nstruct tls_compile_integer;\ntypedef void compile_func(struct tls_internal_state *state,\n\t\t\t  const struct layout_descriptor *desc,\n\t\t\t  const struct tls_compile_integer *data);\n\nstruct layout_descriptor {\n\tconst gchar *label;\n\tparse_func *parser;\n\tcompile_func *compiler;\n\tgsize min; /* 0 for fixed/array */\n\tgsize max;\n\tgsize offset;\n};\n\n#define TLS_LAYOUT_DESCRIPTOR_END { NULL, NULL, NULL, 0, 0, 0 }\n#define TLS_LAYOUT_IS_VALID(desc) (desc->label)\n\nstruct msg_descriptor  {\n\tconst struct msg_descriptor *next;\n\tconst gchar *description;\n\tconst struct layout_descriptor *layouts;\n\tguint type;\n};\n\n/* parsed data */\nstruct tls_parsed_integer {\n\tguint value;\n};\n\nstruct tls_parsed_array {\n\tgsize length; /* bytes */\n\tconst guchar data[0];\n};\n\n/* compile data */\nstruct tls_compile_integer {\n\tgsize value;\n};\n\nstruct tls_compile_array {\n\tgsize elements; /* unused */\n\tguchar placeholder[];\n};\n\nstruct tls_compile_random {\n\tgsize elements; /* unused */\n\tguchar random[TLS_ARRAY_RANDOM_LENGTH];\n};\n\nstruct tls_compile_verify {\n\tgsize elements; /* unused */\n\tguchar verify[TLS_ARRAY_VERIFY_LENGTH];\n};\n\nstruct tls_compile_vector {\n\tgsize elements; /* VECTOR */\n\tguint placeholder[];\n};\n\nstruct tls_compile_sessionid {\n\tgsize elements; /* VECTOR */\n};\n\nstruct tls_compile_cipher {\n\tgsize elements; /* VECTOR */\n\tguint suites[5];\n};\n\nstruct tls_compile_compression {\n\tgsize elements; /* VECTOR */\n\tguint methods[1];\n};\n\n/* compiled message */\nstruct tls_compiled_message {\n\tgsize size;\n\tguchar data[];\n};\n\n/*\n * Random byte buffers\n */\nvoid sipe_tls_fill_random(struct sipe_tls_random *random,\n\t\t\t  guint bits)\n{\n\tguint bytes = ((bits + 15) / 16) * 2;\n\tguint16 *p  = g_malloc(bytes);\n\n\tSIPE_DEBUG_INFO(\"sipe_tls_fill_random: %d bits -> %d bytes\",\n\t\t\tbits, bytes);\n\n\trandom->buffer = (guint8*) p;\n\trandom->length = bytes;\n\n\tfor (bytes /= 2; bytes; bytes--)\n\t\t*p++ = rand() & 0xFFFF;\n}\n\nvoid sipe_tls_free_random(struct sipe_tls_random *random)\n{\n\tg_free(random->buffer);\n}\n\n/*\n * TLS message debugging\n */\nstatic void debug_hex(struct tls_internal_state *state,\n\t\t      gsize alternative_length)\n{\n\tGString *str = state->debug;\n\tconst guchar *bytes;\n\tgsize length;\n\tgint count;\n\n\tif (!str) return;\n\n\tbytes  = state->msg_current;\n\tlength = alternative_length ? alternative_length : state->msg_remainder;\n\tcount  = -1;\n\n\twhile (length-- > 0) {\n\t\tif (++count == 0) {\n\t\t\t/* do nothing */;\n\t\t} else if ((count % 16) == 0) {\n\t\t\tg_string_append(str, \"\\n\");\n\t\t} else if ((count %  8) == 0) {\n\t\t\tg_string_append(str, \"  \");\n\t\t}\n\t\tg_string_append_printf(str, \" %02X\", *bytes++);\n\t}\n\tg_string_append(str, \"\\n\");\n}\n\n#define debug_print(state, string) \\\n\tif (state->debug) g_string_append(state->debug, string)\n#define debug_printf(state, format, ...) \\\n\tif (state->debug) g_string_append_printf(state->debug, format, __VA_ARGS__)\n\n/* Analyzer only needs the debugging functions */\n#ifndef _SIPE_COMPILING_ANALYZER\n\nstatic void debug_secrets(struct tls_internal_state *state,\n\t\t\t  const gchar *label,\n\t\t\t  const guchar *secret,\n\t\t\t  gsize secret_length)\n{\n\tif (state->debug && secret) {\n\t\tg_string_append_printf(state->debug, \"%s (%3\" G_GSIZE_FORMAT \") = \",\n\t\t\t\t       label, secret_length);\n\t\twhile (secret_length--)\n\t\t\tg_string_append_printf(state->debug, \"%02X\", *secret++);\n\t\tSIPE_DEBUG_INFO_NOFORMAT(state->debug->str);\n\t\tg_string_truncate(state->debug, 0);\n\t}\n}\n\n/*\n * TLS Pseudorandom Function (PRF) - RFC2246, Section 5\n */\nstatic guchar *sipe_tls_p_md5(const guchar *secret,\n\t\t\t      gsize secret_length,\n\t\t\t      const guchar *seed,\n\t\t\t      gsize seed_length,\n\t\t\t      gsize output_length)\n{\n\tguchar *output = NULL;\n\n\t/*\n\t * output_length ==  0     -> illegal\n\t * output_length ==  1..16 -> iterations = 1\n\t * output_length == 17..32 -> iterations = 2\n\t */\n\tif (secret && seed && (output_length > 0)) {\n\t\tguint iterations = (output_length + SIPE_DIGEST_HMAC_MD5_LENGTH - 1) / SIPE_DIGEST_HMAC_MD5_LENGTH;\n\t\tguchar *concat   = g_malloc(SIPE_DIGEST_HMAC_MD5_LENGTH + seed_length);\n\t\tguchar A[SIPE_DIGEST_HMAC_MD5_LENGTH];\n\t\tguchar *p;\n\n\t\tSIPE_DEBUG_INFO(\"p_md5: secret %\" G_GSIZE_FORMAT \" bytes, seed %\" G_GSIZE_FORMAT \" bytes\",\n\t\t\t\tsecret_length, seed_length);\n\t\tSIPE_DEBUG_INFO(\"p_md5: output %\" G_GSIZE_FORMAT \" bytes -> %d iterations\",\n\t\t\t\toutput_length, iterations);\n\n\t\t/* A(1) = HMAC_MD5(secret, A(0)), A(0) = seed */\n\t\tsipe_digest_hmac_md5(secret, secret_length,\n\t\t\t\t      seed, seed_length,\n\t\t\t\t      A);\n\n\t\t/* Each iteration adds SIPE_DIGEST_HMAC_MD5_LENGTH bytes */\n\t\tp = output = g_malloc(iterations * SIPE_DIGEST_HMAC_MD5_LENGTH);\n\n\t\twhile (iterations-- > 0) {\n\t\t\t/* P_MD5(i) = HMAC_MD5(secret, A(i) + seed), i = 1, 2, ... */\n\t\t\tguchar P[SIPE_DIGEST_HMAC_MD5_LENGTH];\n\t\t\tmemcpy(concat, A, SIPE_DIGEST_HMAC_MD5_LENGTH);\n\t\t\tmemcpy(concat + SIPE_DIGEST_HMAC_MD5_LENGTH, seed, seed_length);\n\t\t\tsipe_digest_hmac_md5(secret, secret_length,\n\t\t\t\t\t      concat, SIPE_DIGEST_HMAC_MD5_LENGTH + seed_length,\n\t\t\t\t\t      P);\n\t\t\tmemcpy(p, P, SIPE_DIGEST_HMAC_MD5_LENGTH);\n\t\t\tp += SIPE_DIGEST_HMAC_MD5_LENGTH;\n\n\t\t\t/* A(i+1) = HMAC_MD5(secret, A(i)) */\n\t\t\tsipe_digest_hmac_md5(secret, secret_length,\n\t\t\t\t\t      A, SIPE_DIGEST_HMAC_MD5_LENGTH,\n\t\t\t\t\t      A);\n\t\t}\n\t\tg_free(concat);\n\t}\n\n\treturn(output);\n}\n\nguchar *sipe_tls_p_sha1(const guchar *secret,\n\t\t\tgsize secret_length,\n\t\t\tconst guchar *seed,\n\t\t\tgsize seed_length,\n\t\t\tgsize output_length)\n{\n\tguchar *output = NULL;\n\n\t/*\n\t * output_length ==  0     -> illegal\n\t * output_length ==  1..20 -> iterations = 1\n\t * output_length == 21..40 -> iterations = 2\n\t */\n\tif (secret && seed && (output_length > 0)) {\n\t\tguint iterations = (output_length + SIPE_DIGEST_HMAC_SHA1_LENGTH - 1) / SIPE_DIGEST_HMAC_SHA1_LENGTH;\n\t\tguchar *concat   = g_malloc(SIPE_DIGEST_HMAC_SHA1_LENGTH + seed_length);\n\t\tguchar A[SIPE_DIGEST_HMAC_SHA1_LENGTH];\n\t\tguchar *p;\n\n\t\tSIPE_DEBUG_INFO(\"p_sha1: secret %\" G_GSIZE_FORMAT \" bytes, seed %\" G_GSIZE_FORMAT \" bytes\",\n\t\t\t\tsecret_length, seed_length);\n\t\tSIPE_DEBUG_INFO(\"p_sha1: output %\" G_GSIZE_FORMAT \" bytes -> %d iterations\",\n\t\t\t\toutput_length, iterations);\n\n\t\t/* A(1) = HMAC_SHA1(secret, A(0)), A(0) = seed */\n\t\tsipe_digest_hmac_sha1(secret, secret_length,\n\t\t\t\t      seed, seed_length,\n\t\t\t\t      A);\n\n\t\t/* Each iteration adds SIPE_DIGEST_HMAC_SHA1_LENGTH bytes */\n\t\tp = output = g_malloc(iterations * SIPE_DIGEST_HMAC_SHA1_LENGTH);\n\n\t\twhile (iterations-- > 0) {\n\t\t\t/* P_SHA1(i) = HMAC_SHA1(secret, A(i) + seed), i = 1, 2, ... */\n\t\t\tguchar P[SIPE_DIGEST_HMAC_SHA1_LENGTH];\n\t\t\tmemcpy(concat, A, SIPE_DIGEST_HMAC_SHA1_LENGTH);\n\t\t\tmemcpy(concat + SIPE_DIGEST_HMAC_SHA1_LENGTH, seed, seed_length);\n\t\t\tsipe_digest_hmac_sha1(secret, secret_length,\n\t\t\t\t\t      concat, SIPE_DIGEST_HMAC_SHA1_LENGTH + seed_length,\n\t\t\t\t\t      P);\n\t\t\tmemcpy(p, P, SIPE_DIGEST_HMAC_SHA1_LENGTH);\n\t\t\tp += SIPE_DIGEST_HMAC_SHA1_LENGTH;\n\n\t\t\t/* A(i+1) = HMAC_SHA1(secret, A(i)) */\n\t\t\tsipe_digest_hmac_sha1(secret, secret_length,\n\t\t\t\t\t      A, SIPE_DIGEST_HMAC_SHA1_LENGTH,\n\t\t\t\t\t      A);\n\t\t}\n\t\tg_free(concat);\n\t}\n\n\treturn(output);\n}\n\nstatic guchar *sipe_tls_prf(SIPE_UNUSED_PARAMETER struct tls_internal_state *state,\n\t\t\t    const guchar *secret,\n\t\t\t    gsize secret_length,\n\t\t\t    const guchar *label,\n\t\t\t    gsize label_length,\n\t\t\t    const guchar *seed,\n\t\t\t    gsize seed_length,\n\t\t\t    gsize output_length)\n{\n\tgsize half           = (secret_length + 1) / 2;\n\tgsize newseed_length = label_length + seed_length;\n\t/* secret: used as S1; secret2: last half of original secret (S2) */\n\tguchar *secret2 = g_memdup(secret + secret_length - half, half);\n\tguchar *newseed = g_malloc(newseed_length);\n\tguchar *md5, *dest;\n\tguchar *sha1, *src;\n\tgsize count;\n\n\t/* make Coverity happy - lengths could be 0 */\n\tif (!secret2 || !newseed) {\n\t\tg_free(secret2);\n\t\tg_free(newseed);\n\t\treturn(NULL);\n\t}\n\n\t/*\n\t * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR\n\t *                            P_SHA-1(S2, label + seed);\n\t */\n\tmemcpy(newseed, label, label_length);\n\tmemcpy(newseed + label_length, seed, seed_length);\n#undef __SIPE_TLS_CRYPTO_DEBUG\n#ifdef __SIPE_TLS_CRYPTO_DEBUG\n\tdebug_secrets(state, \"sipe_tls_prf: secret                    \",\n\t\t      secret,  secret_length);\n\tdebug_secrets(state, \"sipe_tls_prf: combined seed             \",\n\t\t      newseed, newseed_length);\n\tSIPE_DEBUG_INFO(\"total seed length %\" G_GSIZE_FORMAT,\n\t\t\tnewseed_length);\n\tdebug_secrets(state, \"sipe_tls_prf: S1                        \",\n\t\t      secret,  half);\n\tdebug_secrets(state, \"sipe_tls_prf: S2                        \",\n\t\t      secret2, half);\n#endif\n\tmd5  = sipe_tls_p_md5(secret,   half, newseed, newseed_length, output_length);\n\tsha1 = sipe_tls_p_sha1(secret2, half, newseed, newseed_length, output_length);\n#ifdef __SIPE_TLS_CRYPTO_DEBUG\n\tdebug_secrets(state, \"sipe_tls_prf: P_md5()                   \",\n\t\t      md5,  output_length);\n\tdebug_secrets(state, \"sipe_tls_prf: P_sha1()                  \",\n\t\t      sha1, output_length);\n#endif\n\tfor (dest = md5, src = sha1, count = output_length;\n\t     count > 0;\n\t     count--)\n\t\t*dest++ ^= *src++;\n\n\tg_free(sha1);\n\tg_free(newseed);\n\tg_free(secret2);\n\n#ifdef __SIPE_TLS_CRYPTO_DEBUG\n\tdebug_secrets(state, \"sipe_tls_prf: PRF()                     \",\n\t\t      md5,  output_length);\n#endif\n\n\treturn(md5);\n}\n\n#endif /* !_SIPE_COMPILING_ANALYZER */\n\n/*\n * TLS data parsers\n *\n * Low-level data conversion routines\n *\n *  - host alignment agnostic, i.e. can fetch a word from uneven address\n *  - TLS -> host endianess conversion\n *  - no length check, caller has to do it\n *  - don't modify state\n */\nstatic guint lowlevel_integer_to_host(const guchar *bytes,\n\t\t\t\t      gsize length)\n{\n\tguint sum = 0;\n\twhile (length--) sum = (sum << 8) + *bytes++;\n\treturn(sum);\n}\n\n/*\n * Generic data type parser routines\n */\nstatic gboolean msg_remainder_check(struct tls_internal_state *state,\n\t\t\t\t   const gchar *label,\n\t\t\t\t   gsize length)\n{\n\tif (length > state->msg_remainder) {\n\t\tSIPE_DEBUG_ERROR(\"msg_remainder_check: '%s' expected %\" G_GSIZE_FORMAT \" bytes, remaining %\" G_GSIZE_FORMAT,\n\t\t\t\t label, length, state->msg_remainder);\n\t\treturn(FALSE);\n\t}\n\treturn(TRUE);\n}\n\nstatic gboolean parse_integer_quiet(struct tls_internal_state *state,\n\t\t\t\t    const gchar *label,\n\t\t\t\t    gsize length,\n\t\t\t\t    guint *result)\n{\n\tif (!msg_remainder_check(state, label, length)) return(FALSE);\n\t*result = lowlevel_integer_to_host(state->msg_current, length);\n\tstate->msg_current   += length;\n\tstate->msg_remainder -= length;\n\treturn(TRUE);\n}\n\nstatic gboolean parse_integer(struct tls_internal_state *state,\n\t\t\t      const struct layout_descriptor *desc)\n{\n\tguint value;\n\tif (!parse_integer_quiet(state, desc->label, desc->max, &value))\n\t\treturn(FALSE);\n\tdebug_printf(state, \"%s/INTEGER%\" G_GSIZE_FORMAT \" = %d\\n\",\n\t\t     desc->label, desc->max, value);\n\tif (state->data) {\n\t\tstruct tls_parsed_integer *save = g_new0(struct tls_parsed_integer, 1);\n\t\tsave->value = value;\n\t\tg_hash_table_insert(state->data, (gpointer) desc->label, save);\n\t}\n\treturn(TRUE);\n}\n\nstatic gboolean parse_array(struct tls_internal_state *state,\n\t\t\t    const struct layout_descriptor *desc)\n{\n\tif (!msg_remainder_check(state, desc->label, desc->max))\n\t\treturn(FALSE);\n\tdebug_printf(state, \"%s/ARRAY[%\" G_GSIZE_FORMAT \"]\\n\",\n\t\t     desc->label, desc->max);\n#ifdef _SIPE_COMPILING_ANALYZER\n\tif (desc->max)\n\t\tdebug_hex(state, desc->max);\n#endif\n\tif (state->data) {\n\t\tstruct tls_parsed_array *save = g_malloc0(sizeof(struct tls_parsed_array) +\n\t\t\t\t\t\t\t  desc->max);\n\t\tsave->length = desc->max;\n\t\tmemcpy((guchar *)save->data, state->msg_current, desc->max);\n\t\tg_hash_table_insert(state->data, (gpointer) desc->label, save);\n\n\t}\n\tstate->msg_current   += desc->max;\n\tstate->msg_remainder -= desc->max;\n\treturn(TRUE);\n}\n\nstatic gboolean parse_vector(struct tls_internal_state *state,\n\t\t\t     const struct layout_descriptor *desc)\n{\n\tguint length;\n\tif (!parse_integer_quiet(state, desc->label,\n\t\t\t\t (desc->max > TLS_VECTOR_MAX16) ? 3 :\n\t\t\t\t (desc->max > TLS_VECTOR_MAX8)  ? 2 : 1,\n\t\t\t\t &length))\n\t\treturn(FALSE);\n\tif (length < desc->min) {\n\t\tSIPE_DEBUG_ERROR(\"parse_vector: '%s' too short %d, expected %\" G_GSIZE_FORMAT,\n\t\t\t\t desc->label, length, desc->min);\n\t\treturn(FALSE);\n\t}\n\tdebug_printf(state, \"%s/VECTOR<%d>\\n\", desc->label, length);\n#ifdef _SIPE_COMPILING_ANALYZER\n\tif (length)\n\t\tdebug_hex(state, length);\n#endif\n\tif (state->data) {\n\t\tstruct tls_parsed_array *save = g_malloc0(sizeof(struct tls_parsed_array) +\n\t\t\t\t\t\t\t  length);\n\t\tsave->length = length;\n\t\tmemcpy((guchar *)save->data, state->msg_current, length);\n\t\tg_hash_table_insert(state->data, (gpointer) desc->label, save);\n\t}\n\tstate->msg_current   += length;\n\tstate->msg_remainder -= length;\n\treturn(TRUE);\n}\n\n/*\n * Specific data type parser routines\n */\n\n/* TBD... */\n\n/*\n * TLS data compilers\n *\n * Low-level data conversion routines\n *\n *  - host alignment agnostic, i.e. can fetch a word from uneven address\n *  - host -> TLS host endianess conversion\n *  - don't modify state\n */\nstatic void lowlevel_integer_to_tls(guchar *bytes,\n\t\t\t\t    gsize length,\n\t\t\t\t    guint value)\n{\n\twhile (length--) {\n\t\tbytes[length] = value & 0xFF;\n\t\tvalue >>= 8;\n\t}\n}\n\n/*\n * Generic data type compiler routines\n */\nstatic void compile_integer(struct tls_internal_state *state,\n\t\t\t    const struct layout_descriptor *desc,\n\t\t\t    const struct tls_compile_integer *data)\n{\n\tlowlevel_integer_to_tls(state->msg_current, desc->max, data->value);\n\tstate->msg_current += desc->max;\n}\n\nstatic void compile_array(struct tls_internal_state *state,\n\t\t\t  const struct layout_descriptor *desc,\n\t\t\t  const struct tls_compile_integer *data)\n{\n\tconst struct tls_compile_array *array = (struct tls_compile_array *) data;\n\tmemcpy(state->msg_current, array->placeholder, desc->max);\n\tstate->msg_current += desc->max;\n}\n\nstatic void compile_vector(struct tls_internal_state *state,\n\t\t\t   const struct layout_descriptor *desc,\n\t\t\t   const struct tls_compile_integer *data)\n{\n\tconst struct tls_compile_vector *vector = (struct tls_compile_vector *) data;\n\tgsize length = vector->elements;\n\tgsize length_field = (desc->max > TLS_VECTOR_MAX16) ? 3 :\n\t\t             (desc->max > TLS_VECTOR_MAX8)  ? 2 : 1;\n\n\tlowlevel_integer_to_tls(state->msg_current, length_field, length);\n\tstate->msg_current += length_field;\n\tmemcpy(state->msg_current, vector->placeholder, length);\n\tstate->msg_current += length;\n}\n\nstatic void compile_vector_int2(struct tls_internal_state *state,\n\t\t\t\tconst struct layout_descriptor *desc,\n\t\t\t\tconst struct tls_compile_integer *data)\n{\n\tconst struct tls_compile_vector *vector = (struct tls_compile_vector *) data;\n\tgsize elements = vector->elements;\n\tgsize length   = elements * sizeof(guint16);\n\tgsize length_field = (desc->max > TLS_VECTOR_MAX16) ? 3 :\n\t\t             (desc->max > TLS_VECTOR_MAX8)  ? 2 : 1;\n\tconst guint *p = vector->placeholder;\n\n\tlowlevel_integer_to_tls(state->msg_current, length_field, length);\n\tstate->msg_current += length_field;\n\twhile (elements--) {\n\t\tlowlevel_integer_to_tls(state->msg_current, sizeof(guint16), *p++);\n\t\tstate->msg_current += sizeof(guint16);\n\t}\n}\n\n/*\n * Specific data type compiler routines\n */\n\n/* TBD... */\n\n/*\n * TLS handshake message layout descriptors\n */\nstruct ClientHello_host {\n\tstruct tls_compile_integer protocol_version;\n\tstruct tls_compile_random random;\n\tstruct tls_compile_sessionid sessionid;\n\tstruct tls_compile_cipher cipher;\n\tstruct tls_compile_compression compression;\n};\n#define CLIENTHELLO_OFFSET(a) offsetof(struct ClientHello_host, a)\n\nstatic const struct layout_descriptor ClientHello_l[] = {\n\t{ \"Client Protocol Version\", parse_integer, compile_integer,     0,  2,                      CLIENTHELLO_OFFSET(protocol_version) },\n\t{ \"Random\",                  parse_array,   compile_array,       0, TLS_ARRAY_RANDOM_LENGTH, CLIENTHELLO_OFFSET(random) },\n\t{ \"SessionID\",               parse_vector,  compile_vector,      0, 32,                      CLIENTHELLO_OFFSET(sessionid) },\n\t{ \"CipherSuite\",             parse_vector,  compile_vector_int2, 2, TLS_VECTOR_MAX16,        CLIENTHELLO_OFFSET(cipher)},\n\t{ \"CompressionMethod\",       parse_vector,  compile_vector,      1, TLS_VECTOR_MAX8,         CLIENTHELLO_OFFSET(compression) },\n\tTLS_LAYOUT_DESCRIPTOR_END\n};\nstatic const struct msg_descriptor ClientHello_m = {\n\tNULL, \"Client Hello\", ClientHello_l, TLS_HANDSHAKE_TYPE_CLIENT_HELLO\n};\n\nstatic const struct layout_descriptor ServerHello_l[] = {\n\t{ \"Server Protocol Version\", parse_integer, NULL, 0,  2,                      0 },\n\t{ \"Random\",                  parse_array,   NULL, 0, TLS_ARRAY_RANDOM_LENGTH, 0 },\n\t{ \"SessionID\",               parse_vector,  NULL, 0, 32,                      0 },\n\t{ \"CipherSuite\",             parse_integer, NULL, 0,  2,                      0 },\n\t{ \"CompressionMethod\",       parse_integer, NULL, 0,  1,                      0 },\n\tTLS_LAYOUT_DESCRIPTOR_END\n};\nstatic const struct msg_descriptor ServerHello_m = {\n\t&ClientHello_m, \"Server Hello\", ServerHello_l, TLS_HANDSHAKE_TYPE_SERVER_HELLO\n};\n\nstruct Certificate_host {\n\tstruct tls_compile_vector certificate;\n};\n#define CERTIFICATE_OFFSET(a) offsetof(struct Certificate_host, a)\n\nstatic const struct layout_descriptor Certificate_l[] = {\n\t{ \"Certificate\",             parse_vector, compile_vector, 0, TLS_VECTOR_MAX24, CERTIFICATE_OFFSET(certificate) },\n\tTLS_LAYOUT_DESCRIPTOR_END\n};\nstatic const struct msg_descriptor Certificate_m = {\n\t&ServerHello_m, \"Certificate\", Certificate_l, TLS_HANDSHAKE_TYPE_CERTIFICATE\n};\n\nstatic const struct layout_descriptor CertificateRequest_l[] = {\n\t{ \"CertificateType\",         parse_vector, NULL, 1, TLS_VECTOR_MAX8,  0 },\n\t{ \"DistinguishedName\",       parse_vector, NULL, 0, TLS_VECTOR_MAX16, 0 },\n\tTLS_LAYOUT_DESCRIPTOR_END\n};\nstatic const struct msg_descriptor CertificateRequest_m = {\n\t&Certificate_m, \"Certificate Request\", CertificateRequest_l, TLS_HANDSHAKE_TYPE_CERTIFICATE_REQ\n};\n\nstatic const struct layout_descriptor ServerHelloDone_l[] = {\n\tTLS_LAYOUT_DESCRIPTOR_END\n};\nstatic const struct msg_descriptor ServerHelloDone_m = {\n\t&CertificateRequest_m, \"Server Hello Done\", ServerHelloDone_l, TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE\n};\n\nstruct ClientKeyExchange_host {\n\tstruct tls_compile_vector secret;\n};\n#define CLIENTKEYEXCHANGE_OFFSET(a) offsetof(struct ClientKeyExchange_host, a)\n\nstatic const struct layout_descriptor ClientKeyExchange_l[] = {\n\t{ \"Exchange Keys\",           parse_vector, compile_vector, 0, TLS_VECTOR_MAX16, CLIENTKEYEXCHANGE_OFFSET(secret) },\n\tTLS_LAYOUT_DESCRIPTOR_END\n};\nstatic const struct msg_descriptor ClientKeyExchange_m = {\n\t&ServerHelloDone_m, \"Client Key Exchange\", ClientKeyExchange_l, TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE\n};\n\nstruct CertificateVerify_host {\n\tstruct tls_compile_vector signature;\n};\n#define CERTIFICATEVERIFY_OFFSET(a) offsetof(struct CertificateVerify_host, a)\n\nstatic const struct layout_descriptor CertificateVerify_l[] = {\n\t{ \"Signature\",               parse_vector, compile_vector, 0, TLS_VECTOR_MAX16, CERTIFICATEVERIFY_OFFSET(signature) },\n\tTLS_LAYOUT_DESCRIPTOR_END\n};\nstatic const struct msg_descriptor CertificateVerify_m = {\n\t&ClientKeyExchange_m, \"Certificate Verify\", CertificateVerify_l, TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY\n};\n\nstruct Finished_host {\n\tstruct tls_compile_verify verify;\n};\n#define FINISHED_OFFSET(a) offsetof(struct Finished_host, a)\n\nstatic const struct layout_descriptor Finished_l[] = {\n\t{ \"Verify Data\",             parse_array, compile_array, 0, TLS_ARRAY_VERIFY_LENGTH, FINISHED_OFFSET(verify) },\n\tTLS_LAYOUT_DESCRIPTOR_END\n};\nstatic const struct msg_descriptor Finished_m = {\n\t&CertificateVerify_m, \"Finished\", Finished_l, TLS_HANDSHAKE_TYPE_FINISHED\n};\n\n#define HANDSHAKE_MSG_DESCRIPTORS &Finished_m\n\n/*\n * TLS message parsers\n */\nstatic gboolean handshake_parse(struct tls_internal_state *state,\n\t\t\t\tguint expected_type)\n{\n\tconst guchar *bytes = state->msg_current;\n\tgsize length        = state->msg_remainder;\n\tgboolean success    = FALSE;\n\n\twhile (length > 0) {\n\t\tconst struct msg_descriptor *desc;\n\t\tgsize msg_length;\n\t\tguint msg_type;\n\n\t\t/* header check */\n\t\tif (length < TLS_HANDSHAKE_HEADER_LENGTH) {\n\t\t\tdebug_print(state, \"CORRUPTED HANDSHAKE HEADER\");\n\t\t\tbreak;\n\t\t}\n\n \t\t/* msg length check */\n\t\tmsg_length = lowlevel_integer_to_host(bytes + TLS_HANDSHAKE_OFFSET_LENGTH,\n\t\t\t\t\t\t      3);\n\t\tif (msg_length > length) {\n\t\t\tdebug_print(state, \"HANDSHAKE MESSAGE TOO LONG\");\n\t\t\tbreak;\n\t\t}\n\n\t\t/* msg type */\n\t\tmsg_type = bytes[TLS_HANDSHAKE_OFFSET_TYPE];\n\t\tfor (desc = HANDSHAKE_MSG_DESCRIPTORS;\n\t\t     desc;\n\t\t     desc = desc->next)\n\t\t\tif (msg_type == desc->type)\n\t\t\t\tbreak;\n\n\t\tdebug_printf(state, \"TLS handshake (%\" G_GSIZE_FORMAT \" bytes) (%d)\",\n\t\t\t     msg_length, msg_type);\n\n\t\tif (msg_type == expected_type)\n\t\t\tstate->expected = TRUE;\n\n\t\tstate->msg_current   = (guchar *) bytes + TLS_HANDSHAKE_HEADER_LENGTH;\n\t\tstate->msg_remainder = msg_length;\n\n\t\tif (desc && desc->layouts) {\n\t\t\tconst struct layout_descriptor *ldesc = desc->layouts;\n\n\t\t\tdebug_printf(state, \"%s\\n\", desc->description);\n\n\t\t\twhile (TLS_LAYOUT_IS_VALID(ldesc)) {\n\t\t\t\tsuccess = ldesc->parser(state, ldesc);\n\t\t\t\tif (!success)\n\t\t\t\t\tbreak;\n\t\t\t\tldesc++;\n\t\t\t}\n\t\t\tif (!success)\n\t\t\t\tbreak;\n\t\t} else {\n\t\t\tdebug_print(state, \"ignored\\n\");\n\t\t\tdebug_hex(state, 0);\n\t\t}\n\n\t\t/* next message */\n\t\tbytes  += TLS_HANDSHAKE_HEADER_LENGTH + msg_length;\n\t\tlength -= TLS_HANDSHAKE_HEADER_LENGTH + msg_length;\n\t\tif (length > 0) {\n\t\t\tdebug_print(state, \"------\\n\");\n\t\t} else {\n\t\t\tsuccess = TRUE;\n\t\t}\n\t}\n\n\treturn(success);\n}\n\nstatic void free_parse_data(struct tls_internal_state *state)\n{\n\tif (state->data) {\n\t\tg_hash_table_destroy(state->data);\n\t\tstate->data = NULL;\n\t}\n}\n\nstatic gboolean tls_record_parse(struct tls_internal_state *state,\n\t\t\t\t gboolean incoming,\n\t\t\t\t guint expected)\n{\n\tconst guchar *bytes  = incoming ? state->common.in_buffer : state->common.out_buffer;\n\tgsize length         = incoming ? state->common.in_length : state->common.out_length;\n\tguint version;\n\tconst gchar *version_str;\n\tgsize record_length;\n\tgboolean success = TRUE;\n\n\t/* reject empty incoming messages */\n\tif (incoming && (length == 0)) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"tls_record_parse: empty TLS message received\");\n\t\treturn(FALSE);\n\t}\n\n#ifndef _SIPE_COMPILING_ANALYZER\n\tdebug_printf(state, \"TLS MESSAGE %s\\n\", incoming ? \"INCOMING\" : \"OUTGOING\");\n#endif\n\n\t/* Collect parser data for incoming messages */\n\tif (incoming)\n\t\tstate->data = g_hash_table_new_full(g_str_hash, g_str_equal,\n\t\t\t\t\t\t    NULL, g_free);\n\n\tstate->expected = FALSE;\n\twhile (success && (length > 0)) {\n\n\t\t/* truncated header check */\n\t\tif (length < TLS_RECORD_HEADER_LENGTH) {\n\t\t\tSIPE_DEBUG_ERROR(\"tls_record_parse: too short TLS record header (%\" G_GSIZE_FORMAT \" bytes)\",\n\t\t\t\t\t length);\n\t\t\tsuccess = FALSE;\n\t\t\tbreak;\n\t\t}\n\n\t\t/* protocol version check */\n\t\tversion = lowlevel_integer_to_host(bytes + TLS_RECORD_OFFSET_VERSION, 2);\n\t\tif (version < TLS_PROTOCOL_VERSION_1_0) {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"tls_record_parse: SSL1/2/3 not supported\");\n\t\t\tsuccess = FALSE;\n\t\t\tbreak;\n\t\t}\n\t\tswitch (version) {\n\t\tcase TLS_PROTOCOL_VERSION_1_0:\n\t\t\tversion_str = \"1.0 (RFC2246)\";\n\t\t\tbreak;\n\t\tcase TLS_PROTOCOL_VERSION_1_1:\n\t\t\tversion_str = \"1.1 (RFC4346)\";\n\t\t\tbreak;\n\t\tcase TLS_PROTOCOL_VERSION_1_2:\n\t\t\tversion_str = \"1.2 (RFC5246)\";\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tversion_str = \"<future protocol version>\";\n\t\t\tbreak;\n\t\t}\n\n\t\t/* record length check */\n\t\trecord_length = TLS_RECORD_HEADER_LENGTH +\n\t\t\tlowlevel_integer_to_host(bytes + TLS_RECORD_OFFSET_LENGTH, 2);\n\t\tif (record_length > length) {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"tls_record_parse: record too long\");\n\t\t\tsuccess = FALSE;\n\t\t\tbreak;\n\t\t}\n\n\t\t/* TLS record header OK */\n\t\tdebug_printf(state, \"TLS %s record (%\" G_GSIZE_FORMAT \" bytes)\\n\",\n\t\t\t     version_str, record_length);\n\t\tstate->msg_current   = (guchar *) bytes + TLS_RECORD_HEADER_LENGTH;\n\t\tstate->msg_remainder = record_length - TLS_RECORD_HEADER_LENGTH;\n\n/* Analyzer only needs the debugging functions */\n#ifndef _SIPE_COMPILING_ANALYZER\n\t\t/* Add incoming message contents to digest contexts */\n\t\tif (incoming) {\n\t\t\tsipe_digest_md5_update(state->md5_context,\n\t\t\t\t\t       state->msg_current,\n\t\t\t\t\t       state->msg_remainder);\n\t\t\tsipe_digest_sha1_update(state->sha1_context,\n\t\t\t\t\t\tstate->msg_current,\n\t\t\t\t\t\tstate->msg_remainder);\n\t\t}\n#endif /* !_SIPE_COMPILING_ANALYZER */\n\n\t\tswitch (bytes[TLS_RECORD_OFFSET_TYPE]) {\n\t\tcase TLS_RECORD_TYPE_CHANGE_CIPHER_SPEC:\n\t\t\tdebug_print(state, \"Change Cipher Spec\\n\");\n\t\t\tif (incoming)\n\t\t\t\tstate->encrypted = TRUE;\n\t\t\tif (expected == TLS_RECORD_TYPE_CHANGE_CIPHER_SPEC)\n\t\t\t\tstate->expected = TRUE;\n\t\t\tbreak;\n\n\t\tcase TLS_RECORD_TYPE_HANDSHAKE:\n\t\t\tif (incoming && state->encrypted) {\n\t\t\t\tdebug_print(state, \"Encrypted handshake message\\n\");\n\t\t\t\tdebug_hex(state, 0);\n\t\t\t} else {\n\t\t\t\tsuccess = handshake_parse(state, expected);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tdebug_print(state, \"Unsupported TLS message\\n\");\n\t\t\tdebug_hex(state, 0);\n\t\t\tbreak;\n\t\t}\n\n\t\t/* next fragment */\n\t\tbytes  += record_length;\n\t\tlength -= record_length;\n\t}\n\n#ifndef _SIPE_COMPILING_ANALYZER\n\tif (incoming && !state->expected) {\n\t\tSIPE_DEBUG_ERROR(\"tls_record_parse: did not find expected msg type %d\",\n\t\t\t\t expected);\n\t\tsuccess = FALSE;\n\t}\n#endif\n\n\tif (!success)\n\t\tfree_parse_data(state);\n\n\tif (state->debug) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(state->debug->str);\n\t\tg_string_truncate(state->debug, 0);\n\t}\n\n\treturn(success);\n}\n\n/* Analyzer only needs the debugging functions */\n#ifndef _SIPE_COMPILING_ANALYZER\n\n/*\n * TLS message compiler\n */\nstatic void compile_tls_record(struct tls_internal_state *state,\n\t\t\t       ...)\n{\n\tgsize total_size = 0;\n\tguchar *current;\n\tva_list ap;\n\n\t/* calculate message size */\n\tva_start(ap, state);\n\twhile (1) {\n\t\tconst struct tls_compiled_message *msg = va_arg(ap, struct tls_compiled_message *);\n\t\tif (!msg) break;\n\t\ttotal_size += msg->size;\n\t}\n\tva_end(ap);\n\n\tSIPE_DEBUG_INFO(\"compile_tls_record: total size %\" G_GSIZE_FORMAT,\n\t\t\ttotal_size);\n\n\tstate->common.out_buffer = current = g_malloc(total_size + TLS_RECORD_HEADER_LENGTH);\n\tstate->common.out_length = total_size + TLS_RECORD_HEADER_LENGTH;\n\n\t/* add TLS record header */\n\tcurrent[TLS_RECORD_OFFSET_TYPE] = TLS_RECORD_TYPE_HANDSHAKE;\n\tlowlevel_integer_to_tls(current + TLS_RECORD_OFFSET_VERSION, 2,\n\t\t\t\tTLS_PROTOCOL_VERSION_1_0);\n\tlowlevel_integer_to_tls(current + TLS_RECORD_OFFSET_LENGTH, 2,\n\t\t\t\ttotal_size);\n\tcurrent += TLS_RECORD_HEADER_LENGTH;\n\n\t/* copy messages */\n\tva_start(ap, state);\n\twhile (1) {\n\t\tconst struct tls_compiled_message *msg = va_arg(ap, struct tls_compiled_message *);\n\t\tif (!msg) break;\n\n\t\tmemcpy(current, msg->data, msg->size);\n\t\tcurrent += msg->size;\n\t}\n\tva_end(ap);\n}\n\nstatic void compile_encrypted_tls_record(struct tls_internal_state *state,\n\t\t\t\t\t const struct tls_compiled_message *msg)\n{\n\tguchar *plaintext;\n\tgsize plaintext_length; /* header + content        */\n\tguchar *mac;\n\tgsize mac_length;\n\tguchar *message;\n\tguchar *encrypted;\n\tgsize message_length;   /* header + content + MAC  */\n\tgsize padding_length;   /* for block cipher        */\n\tgsize encrypted_length; /* header + encrypted data */\n\n\t/* Create plaintext TLS record */\n\tcompile_tls_record(state, msg, NULL);\n\tplaintext        = state->common.out_buffer;\n\tplaintext_length = state->common.out_length;\n\tif (plaintext_length == 0) /* make Coverity happy */\n\t\treturn;\n\n\t/* Prepare encryption buffer */\n\tmessage_length = plaintext_length + state->mac_length;\n\tif (state->stream_cipher) {\n\t\tpadding_length   = 0;\n\t\tencrypted_length = message_length;\n\t} else {\n\t\tif (message_length < TLS_RECORD_HEADER_LENGTH) /* make Coverity happy */\n\t\t\treturn;\n\t\tpadding_length   = TLS_AES_CBC_BLOCK_LENGTH - (message_length - TLS_RECORD_HEADER_LENGTH + 1) % TLS_AES_CBC_BLOCK_LENGTH;\n\t\tencrypted_length = message_length + padding_length + 1;\n\t}\n\tSIPE_DEBUG_INFO(\"compile_encrypted_tls_record: total size %\" G_GSIZE_FORMAT,\n\t\t\tencrypted_length - TLS_RECORD_HEADER_LENGTH);\n\tmessage = g_malloc(message_length);\n\tmemcpy(message, plaintext, plaintext_length);\n\tlowlevel_integer_to_tls(message + TLS_RECORD_OFFSET_LENGTH, 2,\n\t\t\t\tencrypted_length - TLS_RECORD_HEADER_LENGTH);\n\n\t/*\n\t * Calculate MAC and append to message\n\t *\n\t * HMAC_hash(client_write_mac_secret,\n\t *           sequence_number + type + version + length + fragment)\n\t *                             \\---  == original TLS record  ---/\n\t */\n\tmac_length = sizeof(guint64) + plaintext_length;\n\tmac        = g_malloc(mac_length);\n\tlowlevel_integer_to_tls(mac,\n\t\t\t\tsizeof(guint64),\n\t\t\t\tstate->sequence_number++);\n\tmemcpy(mac + sizeof(guint64), plaintext, plaintext_length);\n\tg_free(plaintext);\n\tstate->mac_func(state->client_write_mac_secret,\n\t\t\tstate->mac_length,\n\t\t\tmac,\n\t\t\tmac_length,\n\t\t\tmessage + plaintext_length);\n\tg_free(mac);\n\n\tencrypted = g_malloc(encrypted_length);\n\t/* header (unencrypted) */\n\tmemcpy(encrypted, message, TLS_RECORD_HEADER_LENGTH);\n\tif (state->stream_cipher) {\n\t\t/* ENCRYPT(content + MAC) */\n\t\tsipe_crypt_tls_stream(state->cipher_context,\n\t\t\t\t      message + TLS_RECORD_HEADER_LENGTH,\n\t\t\t\t      encrypted_length - TLS_RECORD_HEADER_LENGTH,\n\t\t\t\t      encrypted + TLS_RECORD_HEADER_LENGTH);\n\t} else {\n\t\t/* TLS 1.0 GenericBlockCipher */\n\t\t/* content + MAC */\n\t\tmemcpy(encrypted + TLS_RECORD_HEADER_LENGTH,\n\t\t       message + TLS_RECORD_HEADER_LENGTH,\n\t\t       message_length - TLS_RECORD_HEADER_LENGTH);\n\n\t\t/* padding + padding_length */\n\t\tmemset(encrypted + message_length,\n\t\t       padding_length,\n\t\t       padding_length + 1);\n\n\t\t/* ENCRYPT(content + MAC + padding + padding_length) */\n\t\tsipe_crypt_tls_block(state->client_write_secret,\n\t\t\t\t     state->key_length,\n\t\t\t\t     state->client_write_iv,\n\t\t\t\t     TLS_AES_CBC_BLOCK_LENGTH,\n\t\t\t\t     encrypted + TLS_RECORD_HEADER_LENGTH,\n\t\t\t\t     encrypted_length - TLS_RECORD_HEADER_LENGTH,\n\t\t\t\t     encrypted + TLS_RECORD_HEADER_LENGTH);\n\t}\n\tg_free(message);\n\n\t/* swap buffers */\n\tstate->common.out_buffer = encrypted;\n\tstate->common.out_length = encrypted_length;\n}\n\nstatic struct tls_compiled_message *compile_handshake_msg(struct tls_internal_state *state,\n\t\t\t\t\t\t\t  const struct msg_descriptor *desc,\n\t\t\t\t\t\t\t  gpointer data,\n\t\t\t\t\t\t\t  gsize size)\n{\n\t/*\n\t * Estimate the size of the compiled message\n\t *\n\t * The data structures in the host format have zero or more padding\n\t * bytes added by the compiler to ensure correct element alignments.\n\t * So the sizeof() of the data structure is always equal or greater\n\t * than the space needed for the compiled data. By adding the space\n\t * required for the headers we arrive at a safe estimate\n\t *\n\t * Therefore we don't need space checks in the compiler functions\n\t */\n\tgsize total_size = sizeof(struct tls_compiled_message) +\n\t\tsize + TLS_HANDSHAKE_HEADER_LENGTH;\n\tstruct tls_compiled_message *msg = g_malloc(total_size);\n\tguchar *handshake = msg->data;\n\tconst struct layout_descriptor *ldesc = desc->layouts;\n\tgsize length;\n\n\tSIPE_DEBUG_INFO(\"compile_handshake_msg: buffer size %\" G_GSIZE_FORMAT,\n\t\t\ttotal_size);\n\n\t/* add TLS handshake header */\n\thandshake[TLS_HANDSHAKE_OFFSET_TYPE] = desc->type;\n\tstate->msg_current = handshake  + TLS_HANDSHAKE_HEADER_LENGTH;\n\n\twhile (TLS_LAYOUT_IS_VALID(ldesc)) {\n\t\t/*\n\t\t * Avoid \"cast increases required alignment\" errors\n\t\t *\n\t\t * (void *) tells the compiler that we know what we're\n\t\t * doing, i.e. we know that the calculated address\n\t\t * points to correctly aligned data.\n\t\t */\n\t\tldesc->compiler(state, ldesc,\n\t\t\t\t(void *) ((guchar *) data + ldesc->offset));\n\t\tldesc++;\n\t}\n\n\tlength = state->msg_current - handshake - TLS_HANDSHAKE_HEADER_LENGTH;\n\tlowlevel_integer_to_tls(handshake + TLS_HANDSHAKE_OFFSET_LENGTH,\n\t\t\t\t3, length);\n\tSIPE_DEBUG_INFO(\"compile_handshake_msg: (%d)%s, size %\" G_GSIZE_FORMAT,\n\t\t\tdesc->type, desc->description, length);\n\n\tmsg->size = length + TLS_HANDSHAKE_HEADER_LENGTH;\n\n\t/* update digest contexts */\n\tsipe_digest_md5_update(state->md5_context, handshake, msg->size);\n\tsipe_digest_sha1_update(state->sha1_context, handshake, msg->size);\n\n\treturn(msg);\n}\n\n/*\n * Specific TLS data verficiation & message compilers\n */\nstatic struct tls_compiled_message *tls_client_certificate(struct tls_internal_state *state)\n{\n\tstruct Certificate_host *certificate;\n\tgsize certificate_length = sipe_cert_crypto_raw_length(state->certificate);\n\tstruct tls_compiled_message *msg;\n\n\t/* setup our response */\n\t/* Client Certificate is VECTOR_MAX24 of VECTOR_MAX24s */\n\tcertificate = g_malloc0(sizeof(struct Certificate_host) + 3 +\n\t\t\t\tcertificate_length);\n\tcertificate->certificate.elements = certificate_length + 3;\n\tlowlevel_integer_to_tls((guchar *) certificate->certificate.placeholder, 3,\n\t\t\t\tcertificate_length);\n\tmemcpy((guchar *) certificate->certificate.placeholder + 3,\n\t       sipe_cert_crypto_raw(state->certificate),\n\t       certificate_length);\n\n\tmsg = compile_handshake_msg(state, &Certificate_m, certificate,\n\t\t\t\t    sizeof(struct Certificate_host) + certificate_length + 3);\n\tg_free(certificate);\n\n\treturn(msg);\n}\n\nstatic gboolean check_cipher_suite(struct tls_internal_state *state)\n{\n\tstruct tls_parsed_integer *cipher_suite = g_hash_table_lookup(state->data,\n\t\t\t\t\t\t\t\t      \"CipherSuite\");\n\tconst gchar *label_mac    = NULL;\n\tconst gchar *label_cipher = NULL;\n\n\tif (!cipher_suite) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"check_cipher_suite: server didn't specify the cipher suite\");\n\t\treturn(FALSE);\n\t}\n\n\tswitch (cipher_suite->value) {\n\tcase TLS_RSA_EXPORT_WITH_RC4_40_MD5:\n\t\tstate->mac_length       = SIPE_DIGEST_HMAC_MD5_LENGTH;\n\t\tstate->key_length       = 40 / 8;\n\t\tstate->mac_func         = sipe_digest_hmac_md5;\n\t\tstate->stream_cipher    = TRUE;\n\t\tlabel_mac               = \"MD5\";\n\t\tlabel_cipher            = \"RC4 stream\";\n\t\tstate->common.algorithm = SIPE_TLS_DIGEST_ALGORITHM_MD5;\n\t\tbreak;\n\n\tcase TLS_RSA_WITH_RC4_128_MD5:\n\t\tstate->mac_length       = SIPE_DIGEST_HMAC_MD5_LENGTH;\n\t\tstate->key_length       = 128 / 8;\n\t\tstate->mac_func         = sipe_digest_hmac_md5;\n\t\tstate->stream_cipher    = TRUE;\n\t\tlabel_mac               = \"MD5\";\n\t\tlabel_cipher            = \"RC4 stream\";\n\t\tstate->common.algorithm = SIPE_TLS_DIGEST_ALGORITHM_MD5;\n\t\tbreak;\n\n\tcase TLS_RSA_WITH_RC4_128_SHA:\n\t\tstate->mac_length       = SIPE_DIGEST_HMAC_SHA1_LENGTH;\n\t\tstate->key_length       = 128 / 8;\n\t\tstate->mac_func         = sipe_digest_hmac_sha1;\n\t\tstate->stream_cipher    = TRUE;\n\t\tlabel_mac               = \"SHA-1\";\n\t\tlabel_cipher            = \"RC4 stream\";\n\t\tstate->common.algorithm = SIPE_TLS_DIGEST_ALGORITHM_SHA1;\n\t\tbreak;\n\n\tcase TLS_RSA_WITH_AES_128_CBC_SHA:\n\t\tstate->mac_length       = SIPE_DIGEST_HMAC_SHA1_LENGTH;\n\t\tstate->key_length       = 128 / 8;\n\t\tstate->mac_func         = sipe_digest_hmac_sha1;\n\t\tstate->stream_cipher    = FALSE;\n\t\tlabel_mac               = \"SHA-1\";\n\t\tlabel_cipher            = \"AES-CBC block\";\n\t\tstate->common.algorithm = SIPE_TLS_DIGEST_ALGORITHM_SHA1;\n\t\tbreak;\n\n\tcase TLS_RSA_WITH_AES_256_CBC_SHA:\n\t\tstate->mac_length       = SIPE_DIGEST_HMAC_SHA1_LENGTH;\n\t\tstate->key_length       = 256 / 8;\n\t\tstate->mac_func         = sipe_digest_hmac_sha1;\n\t\tstate->stream_cipher    = FALSE;\n\t\tlabel_mac               = \"SHA-1\";\n\t\tlabel_cipher            = \"AES-CBC block\";\n\t\tstate->common.algorithm = SIPE_TLS_DIGEST_ALGORITHM_SHA1;\n\t\tbreak;\n\n\tdefault:\n\t\tSIPE_DEBUG_ERROR(\"check_cipher_suite: unsupported cipher suite %d\",\n\t\t\t\t cipher_suite->value);\n\t\tbreak;\n\t}\n\n\tif (label_cipher && label_mac)\n\t\tSIPE_DEBUG_INFO(\"check_cipher_suite: KEY(%s cipher) %\" G_GSIZE_FORMAT \", MAC(%s) %\" G_GSIZE_FORMAT,\n\t\t\t\tlabel_cipher, state->key_length,\n\t\t\t\tlabel_mac, state->mac_length);\n\n\treturn(label_cipher && label_mac);\n}\n\nstatic void tls_calculate_secrets(struct tls_internal_state *state)\n{\n\tgsize length = 2 * (state->mac_length + state->key_length +\n\t\t\t    (state->stream_cipher ? 0 : TLS_AES_CBC_BLOCK_LENGTH));\n\tguchar *random;\n\n\t/* Generate pre-master secret */\n\tsipe_tls_fill_random(&state->pre_master_secret,\n\t\t\t     TLS_ARRAY_MASTER_SECRET_LENGTH * 8); /* bits */\n\tlowlevel_integer_to_tls(state->pre_master_secret.buffer, 2,\n\t\t\t\tTLS_PROTOCOL_VERSION_1_0);\n\tdebug_secrets(state, \"tls_calculate_secrets: pre-master secret\",\n\t\t      state->pre_master_secret.buffer,\n\t\t      state->pre_master_secret.length);\n\n\t/*\n\t * Calculate master secret\n\t *\n\t * master_secret = PRF(pre_master_secret,\n\t *                     \"master secret\",\n\t *                     ClientHello.random + ServerHello.random)\n\t */\n\trandom = g_malloc(TLS_ARRAY_RANDOM_LENGTH * 2);\n\tmemcpy(random,\n\t       state->client_random.buffer,\n\t       TLS_ARRAY_RANDOM_LENGTH);\n\tmemcpy(random + TLS_ARRAY_RANDOM_LENGTH,\n\t       state->server_random.buffer,\n\t       TLS_ARRAY_RANDOM_LENGTH);\n\tstate->master_secret = sipe_tls_prf(state,\n\t\t\t\t\t    state->pre_master_secret.buffer,\n\t\t\t\t\t    state->pre_master_secret.length,\n\t\t\t\t\t    (guchar *) \"master secret\",\n\t\t\t\t\t    13,\n\t\t\t\t\t    random,\n\t\t\t\t\t    TLS_ARRAY_RANDOM_LENGTH * 2,\n\t\t\t\t\t    TLS_ARRAY_MASTER_SECRET_LENGTH);\n\tdebug_secrets(state, \"tls_calculate_secrets: master secret    \",\n\t\t      state->master_secret,\n\t\t      TLS_ARRAY_MASTER_SECRET_LENGTH);\n\n\t/*\n\t * Calculate session key material\n\t *\n\t * key_block = PRF(master_secret,\n\t *                 \"key expansion\",\n\t *                 ServerHello.random + ClientHello.random)\n\t */\n\tSIPE_DEBUG_INFO(\"tls_calculate_secrets: key_block length %\" G_GSIZE_FORMAT,\n\t\t\tlength);\n\tmemcpy(random,\n\t       state->server_random.buffer,\n\t       TLS_ARRAY_RANDOM_LENGTH);\n\tmemcpy(random + TLS_ARRAY_RANDOM_LENGTH,\n\t       state->client_random.buffer,\n\t       TLS_ARRAY_RANDOM_LENGTH);\n\tstate->key_block = sipe_tls_prf(state,\n\t\t\t\t\tstate->master_secret,\n\t\t\t\t\tTLS_ARRAY_MASTER_SECRET_LENGTH,\n\t\t\t\t\t(guchar *) \"key expansion\",\n\t\t\t\t\t13,\n\t\t\t\t\trandom,\n\t\t\t\t\tTLS_ARRAY_RANDOM_LENGTH * 2,\n\t\t\t\t\tlength);\n\tg_free(random);\n\tdebug_secrets(state, \"tls_calculate_secrets: key block        \",\n\t\t      state->key_block, length);\n\n\t/* partition key block */\n\tstate->client_write_mac_secret = state->key_block;\n\tstate->server_write_mac_secret = state->key_block + state->mac_length;\n\tstate->client_write_secret     = state->key_block + 2 * state->mac_length;\n\tstate->server_write_secret     = state->key_block + 2 * state->mac_length + state->key_length;\n\n\t/* initialize stream cipher context */\n\tif (state->stream_cipher) {\n\t\tstate->cipher_context = sipe_crypt_tls_start(state->client_write_secret,\n\t\t\t\t\t\t\t     state->key_length);\n\t} else {\n\t\tstate->client_write_iv = state->key_block + 2 * (state->mac_length + state->key_length);\n\t\tstate->server_write_iv = state->key_block + 2 * (state->mac_length + state->key_length) + TLS_AES_CBC_BLOCK_LENGTH;\n\t}\n}\n\n#if 0 /* NOT NEEDED? */\n/* signing */\nstatic guchar *tls_pkcs1_private_padding(SIPE_UNUSED_PARAMETER struct tls_internal_state *state,\n\t\t\t\t\t const guchar *data,\n\t\t\t\t\t gsize data_length,\n\t\t\t\t\t gsize buffer_length)\n{\n\tgsize pad_length;\n\tguchar *pad_buffer;\n\n\tif (data_length + 3 > buffer_length) ||\n\t    (buffer_length == 0)) /* this is dead code, but makes Coverity happy */)\n\t\treturn(NULL);\n\n\tpad_length = buffer_length - data_length - 3;\n\tpad_buffer = g_malloc(buffer_length);\n\n\t/* PKCS1 private key block padding */\n\tpad_buffer[0]                       = 0; /* +1 */\n\tpad_buffer[1]                       = 1; /* +2 */\n\tmemset(pad_buffer + 2,              0xFF, pad_length);\n\tpad_buffer[2 + pad_length]          = 0; /* +3 */\n\tmemcpy(pad_buffer + 3 + pad_length, data, data_length);\n\n#ifdef __SIPE_TLS_CRYPTO_DEBUG\n\tdebug_secrets(state, \"tls_pkcs1_private_padding:              \",\n\t\t      pad_buffer, buffer_length);\n#endif\n\n\treturn(pad_buffer);\n}\n#endif\n\n/* encryption */\nstatic guchar *tls_pkcs1_public_padding(SIPE_UNUSED_PARAMETER struct tls_internal_state *state,\n\t\t\t\t\tconst guchar *data,\n\t\t\t\t\tgsize data_length,\n\t\t\t\t\tgsize buffer_length)\n{\n\tgsize pad_length, random_count;\n\tguchar *pad_buffer, *random;\n\n\tif ((data_length + 3 > buffer_length) ||\n\t    (buffer_length == 0)) /* this is dead code, but makes Coverity happy */\n\t\treturn(NULL);\n\n\tpad_length = buffer_length - data_length - 3;\n\tpad_buffer = g_malloc(buffer_length);\n\n\t/* PKCS1 public key block padding */\n\tpad_buffer[0]                       = 0; /* +1 */\n\tpad_buffer[1]                       = 2; /* +2 */\n\tfor (random = pad_buffer + 2, random_count = pad_length;\n\t     random_count > 0;\n\t     random_count--) {\n\t\tguchar byte;\n\t\t/* non-zero random byte */\n\t\twhile ((byte = rand() & 0xFF) == 0);\n\t\t*random++ = byte;\n\t}\n\tpad_buffer[2 + pad_length]          = 0; /* +3 */\n\tmemcpy(pad_buffer + 3 + pad_length, data, data_length);\n\n#ifdef __SIPE_TLS_CRYPTO_DEBUG\n\tdebug_secrets(state, \"tls_pkcs1_private_padding:              \",\n\t\t      pad_buffer, buffer_length);\n#endif\n\n\treturn(pad_buffer);\n}\n\nstatic struct tls_compiled_message *tls_client_key_exchange(struct tls_internal_state *state)\n{\n\tstruct tls_parsed_array *server_random;\n\tstruct tls_parsed_array *server_certificate;\n\tstruct ClientKeyExchange_host *exchange;\n\tgsize server_certificate_length;\n\tguchar *padded;\n\tstruct tls_compiled_message *msg;\n\n\t/* check for required data fields */\n\tif (!check_cipher_suite(state))\n\t\treturn(NULL);\n\tserver_random = g_hash_table_lookup(state->data, \"Random\");\n\tif (!server_random) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"tls_client_key_exchange: no server random\");\n\t\treturn(NULL);\n\t}\n\tserver_certificate = g_hash_table_lookup(state->data, \"Certificate\");\n\t/* Server Certificate is VECTOR_MAX24 of VECTOR_MAX24s */\n\tif (!server_certificate || (server_certificate->length < 3)) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"tls_client_key_exchange: no server certificate\");\n\t\treturn(FALSE);\n\t}\n\tSIPE_DEBUG_INFO(\"tls_client_key_exchange: server certificate list %\" G_GSIZE_FORMAT\" bytes\",\n\t\t\tserver_certificate->length);\n\t/* first certificate is the server certificate */\n\tserver_certificate_length = lowlevel_integer_to_host(server_certificate->data,\n\t\t\t\t\t\t\t     3);\n\tSIPE_DEBUG_INFO(\"tls_client_key_exchange: server certificate %\" G_GSIZE_FORMAT\" bytes\",\n\t\t\tserver_certificate_length);\n\tif ((server_certificate_length + 3) > server_certificate->length) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"tls_client_key_exchange: truncated server certificate\");\n\t}\n\tstate->server_certificate = sipe_cert_crypto_import(server_certificate->data + 3,\n\t\t\t\t\t\t\t    server_certificate_length);\n\tif (!state->server_certificate) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"tls_client_key_exchange: corrupted server certificate\");\n\t\treturn(FALSE);\n\t}\n\t/* server public key modulus length */\n\tserver_certificate_length = sipe_cert_crypto_modulus_length(state->server_certificate);\n\tif (server_certificate_length < TLS_ARRAY_MASTER_SECRET_LENGTH) {\n\t\tSIPE_DEBUG_ERROR(\"tls_client_key_exchange: server public key strength too low (%\" G_GSIZE_FORMAT \")\",\n\t\t\t\t server_certificate_length);\n\t\treturn(FALSE);\n\t}\n\tSIPE_DEBUG_INFO(\"tls_client_key_exchange: server public key strength = %\" G_GSIZE_FORMAT,\n\t\t\tserver_certificate_length);\n\n\t/* found all the required fields */\n\tstate->server_random.length = server_random->length;\n\tstate->server_random.buffer = g_memdup(server_random->data,\n\t\t\t\t\t       server_random->length);\n\ttls_calculate_secrets(state);\n\n\t/* ClientKeyExchange */\n\tpadded = tls_pkcs1_public_padding(state,\n\t\t\t\t\t  state->pre_master_secret.buffer,\n\t\t\t\t\t  state->pre_master_secret.length,\n\t\t\t\t\t  server_certificate_length);\n\tif (!padded) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"tls_client_key_exchange: padding of pre-master secret failed\");\n\t\treturn(NULL);\n\t}\n\texchange = g_malloc0(sizeof(struct ClientKeyExchange_host) +\n\t\t\t     server_certificate_length);\n\texchange->secret.elements = server_certificate_length;\n\tif (!sipe_crypt_rsa_encrypt(sipe_cert_crypto_public_key(state->server_certificate),\n\t\t\t\t    server_certificate_length,\n\t\t\t\t    padded,\n\t\t\t\t    (guchar *) exchange->secret.placeholder)) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"tls_client_key_exchange: encryption of pre-master secret failed\");\n\t\tg_free(exchange);\n\t\tg_free(padded);\n\t\treturn(NULL);\n\t}\n\tg_free(padded);\n\n#ifdef __SIPE_TLS_CRYPTO_DEBUG\n\tdebug_secrets(state, \"tls_client_key_exchange: secret (encr)  \",\n\t\t      (guchar *) exchange->secret.placeholder,\n\t\t      server_certificate_length);\n#endif\n\n\tmsg = compile_handshake_msg(state, &ClientKeyExchange_m, exchange,\n\t\t\t\t    sizeof(struct ClientKeyExchange_host) + server_certificate_length);\n\tg_free(exchange);\n\n\treturn(msg);\n}\n\nstatic struct tls_compiled_message *tls_certificate_verify(struct tls_internal_state *state)\n{\n\tstruct CertificateVerify_host *verify;\n\tstruct tls_compiled_message *msg;\n\tguchar *digests = g_malloc(SIPE_DIGEST_MD5_LENGTH + SIPE_DIGEST_SHA1_LENGTH);\n\tguchar *signature;\n\tgsize length;\n\n\t/* calculate digests */\n\tsipe_digest_md5_end(state->md5_context, digests);\n\tsipe_digest_sha1_end(state->sha1_context, digests + SIPE_DIGEST_MD5_LENGTH);\n\n\t/* sign digests */\n\tsignature = sipe_crypt_rsa_sign(sipe_cert_crypto_private_key(state->certificate),\n\t\t\t\t\tdigests,\n\t\t\t\t\tSIPE_DIGEST_MD5_LENGTH + SIPE_DIGEST_SHA1_LENGTH,\n\t\t\t\t\t&length);\n\tg_free(digests);\n\tif (!signature) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"tls_certificate_verify: signing of handshake digests failed\");\n\t\treturn(NULL);\n\t}\n\n\t/* CertificateVerify */\n\tverify = g_malloc0(sizeof(struct CertificateVerify_host) +\n\t\t\t   length);\n\tverify->signature.elements = length;\n\tmemcpy(verify->signature.placeholder, signature, length);\n\tg_free(signature);\n\n\tmsg = compile_handshake_msg(state, &CertificateVerify_m, verify,\n\t\t\t\t    sizeof(struct CertificateVerify_host) + length);\n\tg_free(verify);\n\n\treturn(msg);\n}\n\nstatic struct tls_compiled_message *tls_client_finished(struct tls_internal_state *state)\n{\n\tguchar *digests = g_malloc(SIPE_DIGEST_MD5_LENGTH + SIPE_DIGEST_SHA1_LENGTH);\n\tguchar *verify;\n\tstruct tls_compiled_message *cmsg;\n\tstruct Finished_host msg;\n\n\t/* calculate digests */\n\tsipe_digest_md5_end(state->md5_context, digests);\n\tsipe_digest_sha1_end(state->sha1_context, digests + SIPE_DIGEST_MD5_LENGTH);\n\n\t/*\n\t * verify_data = PRF(master_secret, \"client finished\",\n\t *                   MD5(handshake_messages) +\n\t *                   SHA-1(handshake_messages)) [0..11];\n\t */\n\tverify = sipe_tls_prf(state,\n\t\t\t      state->master_secret,\n\t\t\t      TLS_ARRAY_MASTER_SECRET_LENGTH,\n\t\t\t      (guchar *) \"client finished\",\n\t\t\t      15,\n\t\t\t      digests,\n\t\t\t      SIPE_DIGEST_MD5_LENGTH + SIPE_DIGEST_SHA1_LENGTH,\n\t\t\t      TLS_ARRAY_VERIFY_LENGTH);\n\tg_free(digests);\n\tmemcpy(msg.verify.verify, verify, TLS_ARRAY_VERIFY_LENGTH);\n\tg_free(verify);\n\n\tcmsg = compile_handshake_msg(state, &Finished_m, &msg, sizeof(msg));\n\n\treturn(cmsg);\n}\n\n/*\n * TLS state handling\n */\n\nstatic gboolean tls_client_hello(struct tls_internal_state *state)\n{\n\tguint32 now   = time(NULL);\n\tguint32 now_N = GUINT32_TO_BE(now);\n\tstruct ClientHello_host msg = {\n\t\t{ TLS_PROTOCOL_VERSION_1_0 },\n\t\t{ 0, { 0 } },\n\t\t{ 0 /* empty SessionID */ },\n\t\t{ 5,\n\t\t  {\n\t\t\t  TLS_RSA_WITH_RC4_128_MD5,\n\t\t\t  TLS_RSA_WITH_RC4_128_SHA,\n\t\t\t  TLS_RSA_WITH_AES_128_CBC_SHA,\n\t\t\t  TLS_RSA_WITH_AES_256_CBC_SHA,\n\t\t\t  TLS_RSA_EXPORT_WITH_RC4_40_MD5\n\t\t  }\n\t\t},\n\t\t{ 1,\n\t\t  {\n\t\t\t  TLS_COMP_METHOD_NULL\n\t\t  }\n\t\t}\n\t};\n\tstruct tls_compiled_message *cmsg;\n\n\t/* First 4 bytes of client_random is the current timestamp */\n\tsipe_tls_fill_random(&state->client_random,\n\t\t\t     TLS_ARRAY_RANDOM_LENGTH * 8); /* -> bits */\n\tmemcpy(state->client_random.buffer, &now_N, sizeof(now_N));\n\tmemcpy(msg.random.random, state->client_random.buffer,\n\t       TLS_ARRAY_RANDOM_LENGTH);\n\n\tcmsg = compile_handshake_msg(state, &ClientHello_m, &msg, sizeof(msg));\n        compile_tls_record(state, cmsg, NULL);\n\tg_free(cmsg);\n\n\tif (sipe_backend_debug_enabled())\n\t\tstate->debug = g_string_new(\"\");\n\n\tstate->state = TLS_HANDSHAKE_STATE_SERVER_HELLO;\n\treturn(tls_record_parse(state, FALSE, 0));\n}\n\nstatic gboolean tls_server_hello(struct tls_internal_state *state)\n{\n\tstruct tls_compiled_message *certificate = NULL;\n\tstruct tls_compiled_message *exchange    = NULL;\n\tstruct tls_compiled_message *verify      = NULL;\n\tstruct tls_compiled_message *finished    = NULL;\n\tgboolean success = FALSE;\n\n\tif (!tls_record_parse(state, TRUE, TLS_HANDSHAKE_TYPE_SERVER_HELLO))\n\t\treturn(FALSE);\n\n\tif (((certificate = tls_client_certificate(state))  != NULL) &&\n\t    ((exchange    = tls_client_key_exchange(state)) != NULL) &&\n\t    ((verify      = tls_certificate_verify(state))  != NULL) &&\n\t    ((finished    = tls_client_finished(state))     != NULL)) {\n\n\t\t/* Part 1 */\n\t\tcompile_tls_record(state, certificate, exchange, verify, NULL);\n\n\t\tsuccess = tls_record_parse(state, FALSE,  0);\n\t\tif (success) {\n\t\t\tguchar *part1      = state->common.out_buffer;\n\t\t\tgsize part1_length = state->common.out_length;\n\t\t\tguchar *part3;\n\t\t\tgsize part3_length;\n\t\t\tguchar *merged;\n\t\t\tgsize length;\n\t\t\t/* ChangeCipherSpec is always the same */\n\t\t\tstatic const guchar part2[] = {\n\t\t\t\tTLS_RECORD_TYPE_CHANGE_CIPHER_SPEC,\n\t\t\t\t(TLS_PROTOCOL_VERSION_1_0 >> 8) & 0xFF,\n\t\t\t\tTLS_PROTOCOL_VERSION_1_0 & 0xFF,\n\t\t\t\t0x00, 0x01, /* length: 1 byte        */\n\t\t\t\t0x01        /* change_cipher_spec(1) */\n\t\t\t};\n\n\t\t\tstate->common.out_buffer = NULL;\n\n\t\t\t/* Part 3 - this is the first encrypted record */\n\t\t\tcompile_encrypted_tls_record(state, finished);\n\t\t\tpart3        = state->common.out_buffer;\n\t\t\tpart3_length = state->common.out_length;\n\n\t\t\t\t/* merge TLS records */\n\t\t\tlength = part1_length + sizeof(part2) + part3_length;\n\t\t\tmerged = g_malloc(length);\n\n\t\t\tmemcpy(merged,                                part1, part1_length);\n\t\t\tmemcpy(merged + part1_length,                 part2, sizeof(part2));\n\t\t\tmemcpy(merged + part1_length + sizeof(part2), part3, part3_length);\n\t\t\tg_free(part3);\n\t\t\tg_free(part1);\n\n\t\t\t/* replace output buffer with merged message */\n\t\t\tstate->common.out_buffer = merged;\n\t\t\tstate->common.out_length = length;\n\n\t\t\tstate->state = TLS_HANDSHAKE_STATE_FINISHED;\n\t\t}\n\t}\n\n\tg_free(finished);\n\tg_free(verify);\n\tg_free(exchange);\n\tg_free(certificate);\n\tfree_parse_data(state);\n\n\treturn(success);\n}\n\nstatic gboolean tls_finished(struct tls_internal_state *state)\n{\n\tguchar *random;\n\n\tif (!tls_record_parse(state, TRUE, TLS_RECORD_TYPE_CHANGE_CIPHER_SPEC))\n\t\treturn(FALSE);\n\n\t/* we don't need the data */\n\tfree_parse_data(state);\n\n\t/*\n\t * Calculate session keys [MS-SIPAE section 3.2.5.1]\n\t *\n\t * key_material = PRF (master_secret,\n\t *                     \"client EAP encryption\",\n\t *                     ClientHello.random + ServerHello.random)[128]\n\t *              = 4 x 32 Bytes\n\t *\n\t * client key = key_material[3rd 32 Bytes]\n\t * server key = key_material[4th 32 Bytes]\n\t */\n\trandom = g_malloc(TLS_ARRAY_RANDOM_LENGTH * 2);\n\tmemcpy(random,\n\t       state->client_random.buffer,\n\t       TLS_ARRAY_RANDOM_LENGTH);\n\tmemcpy(random + TLS_ARRAY_RANDOM_LENGTH,\n\t       state->server_random.buffer,\n\t       TLS_ARRAY_RANDOM_LENGTH);\n\tstate->tls_dsk_key_block = sipe_tls_prf(state,\n\t\t\t\t\t\tstate->master_secret,\n\t\t\t\t\t\tTLS_ARRAY_MASTER_SECRET_LENGTH,\n\t\t\t\t\t\t(guchar *) \"client EAP encryption\",\n\t\t\t\t\t\t21,\n\t\t\t\t\t\trandom,\n\t\t\t\t\t\tTLS_ARRAY_RANDOM_LENGTH * 2,\n\t\t\t\t\t\t4 * 32);\n\tg_free(random);\n\n#ifdef __SIPE_TLS_CRYPTO_DEBUG\n\tdebug_secrets(state, \"tls_finished: TLS-DSK key block         \",\n\t\t      state->tls_dsk_key_block, 4 * 32);\n#endif\n\n\tstate->common.client_key = state->tls_dsk_key_block + 2 * 32;\n\tstate->common.server_key = state->tls_dsk_key_block + 3 * 32;\n\tstate->common.key_length = 32;\n\n\tdebug_secrets(state, \"tls_finished: TLS-DSK client key        \",\n\t\t      state->common.client_key,\n\t\t      state->common.key_length);\n\tdebug_secrets(state, \"tls_finished: TLS-DSK server key        \",\n\t\t      state->common.server_key,\n\t\t      state->common.key_length);\n\n\tstate->common.out_buffer = NULL;\n\tstate->common.out_length = 0;\n\tstate->state             = TLS_HANDSHAKE_STATE_COMPLETED;\n\n\treturn(TRUE);\n}\n\n/*\n * TLS public API\n */\n\nstruct sipe_tls_state *sipe_tls_start(gpointer certificate)\n{\n\tstruct tls_internal_state *state;\n\n\tif (!certificate)\n\t\treturn(NULL);\n\n\tstate = g_new0(struct tls_internal_state, 1);\n\tstate->certificate  = certificate;\n\tstate->state        = TLS_HANDSHAKE_STATE_START;\n\tstate->md5_context  = sipe_digest_md5_start();\n\tstate->sha1_context = sipe_digest_sha1_start();\n\tstate->common.algorithm = SIPE_TLS_DIGEST_ALGORITHM_NONE;\n\n\treturn((struct sipe_tls_state *) state);\n}\n\ngboolean sipe_tls_next(struct sipe_tls_state *state)\n{\n\t/* Avoid \"cast increases required alignment\" errors */\n\tstruct tls_internal_state *internal = (void *) state;\n\tgboolean success = FALSE;\n\n\tif (!state)\n\t\treturn(FALSE);\n\n\tstate->out_buffer = NULL;\n\n\tswitch (internal->state) {\n\tcase TLS_HANDSHAKE_STATE_START:\n\t\tsuccess = tls_client_hello(internal);\n\t\tbreak;\n\n\tcase TLS_HANDSHAKE_STATE_SERVER_HELLO:\n\t\tsuccess = tls_server_hello(internal);\n\t\tbreak;\n\n\tcase TLS_HANDSHAKE_STATE_FINISHED:\n\t\tsuccess = tls_finished(internal);\n\t\tbreak;\n\n\tcase TLS_HANDSHAKE_STATE_COMPLETED:\n\tcase TLS_HANDSHAKE_STATE_FAILED:\n\t\t/* This should not happen */\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_tls_next: called in incorrect state!\");\n\t\tbreak;\n\t}\n\n\tif (!success) {\n\t\tinternal->state = TLS_HANDSHAKE_STATE_FAILED;\n\t}\n\n\treturn(success);\n}\n\nguint sipe_tls_expires(struct sipe_tls_state *state)\n{\n\t/* Avoid \"cast increases required alignment\" errors */\n\tstruct tls_internal_state *internal = (void *) state;\n\n\tif (!state)\n\t\treturn(0);\n\n\treturn(sipe_cert_crypto_expires(internal->certificate));\n}\n\nvoid sipe_tls_free(struct sipe_tls_state *state)\n{\n\tif (state) {\n\t\t/* Avoid \"cast increases required alignment\" errors */\n\t\tstruct tls_internal_state *internal = (void *) state;\n\n\t\tfree_parse_data(internal);\n\t\tif (internal->debug)\n\t\t\tg_string_free(internal->debug, TRUE);\n\t\tg_free(internal->tls_dsk_key_block);\n\t\tg_free(internal->key_block);\n\t\tg_free(internal->master_secret);\n\t\tsipe_tls_free_random(&internal->pre_master_secret);\n\t\tsipe_tls_free_random(&internal->client_random);\n\t\tsipe_tls_free_random(&internal->server_random);\n\t\tif (internal->cipher_context)\n\t\t\tsipe_crypt_tls_destroy(internal->cipher_context);\n\t\tif (internal->md5_context)\n\t\t\tsipe_digest_md5_destroy(internal->md5_context);\n\t\tif (internal->sha1_context)\n\t\t\tsipe_digest_sha1_destroy(internal->sha1_context);\n\t\tsipe_cert_crypto_destroy(internal->server_certificate);\n\t\tg_free(state->out_buffer);\n\t\tg_free(state);\n\t}\n}\n\n#endif /* !_SIPE_COMPILING_ANALYZER */\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-tls.h",
    "content": "/**\n * @file sipe-tls.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-12 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/*\n * Interface dependencies:\n *\n * <glib.h>\n */\n\n/**\n * Random bytes buffer\n */\nstruct sipe_tls_random {\n  guchar *buffer;\n  guint length;   /* in bytes */\n};\n\n/**\n * Allocate a buffer with N random bits\n *\n * @param random pointer to random bytes buffer\n * @param bits   number of random bits (will be rounded up be dividable by 16)\n */\nvoid sipe_tls_fill_random(struct sipe_tls_random *random,\n\t\t\t  guint bits);\n\n/**\n * Free a random bytes buffer\n *\n * @param random pointer to random bytes buffer\n */\nvoid sipe_tls_free_random(struct sipe_tls_random *random);\n\n\n/**\n * Public part of TLS state tracking\n *\n * If @c session_key != @c NULL then handshake is complete\n */\nenum sipe_tls_digest_algorithm {\n  SIPE_TLS_DIGEST_ALGORITHM_NONE,\n  SIPE_TLS_DIGEST_ALGORITHM_MD5,\n  SIPE_TLS_DIGEST_ALGORITHM_SHA1\n};\nstruct sipe_tls_state {\n  const guchar *in_buffer;\n  guchar *out_buffer;\n  gsize in_length;\n  gsize out_length;\n  enum sipe_tls_digest_algorithm algorithm;\n  const guchar *client_key;\n  const guchar *server_key;\n  gsize key_length;\n};\n\n/**\n * TLS data expansion function P_SHA1(secret, seed)\n *\n * @param secret        pointer to binary secret\n * @param secret_length length of secret\n * @param seed          pointer to binary seed\n * @param seed_length   length of seed\n * @param output_length how much data to generate\n *\n * @return generated data. Must be g_free()'d\n */\nguchar *sipe_tls_p_sha1(const guchar *secret,\n\t\t\tgsize secret_length,\n\t\t\tconst guchar *seed,\n\t\t\tgsize seed_length,\n\t\t\tgsize output_length);\n\n/**\n * Initialize TLS state\n *\n * @param certificate opaque pointer to the user certificate\n *\n * @return TLS state structure\n */\nstruct sipe_tls_state *sipe_tls_start(gpointer certificate);\n\n/**\n * Proceed to next TLS state\n *\n * @param state     pointer to TLS state structure\n * @param incoming  pointer to incoming message (NULL for initial transition)\n * @param in_length length of incoming message\n *\n * @return TLS state structure\n */\ngboolean sipe_tls_next(struct sipe_tls_state *state);\n\n/**\n * Extract expiration time from TLS certificate\n *\n * @param state     pointer to TLS state structure\n *\n * @return expiration time in seconds\n */\nguint sipe_tls_expires(struct sipe_tls_state *state);\n\n/**\n * Free TLS state\n *\n * @param state pointer to TLS state structure\n */\nvoid sipe_tls_free(struct sipe_tls_state *state);\n"
  },
  {
    "path": "src/core/sipe-ucs.c",
    "content": "/**\n * @file sipe-ucs.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * Implementation for Unified Contact Store [MS-OXWSCOS]\n *  <http://msdn.microsoft.com/en-us/library/jj194130.aspx>\n * EWS Reference\n *  <http://msdn.microsoft.com/en-us/library/office/bb204119.aspx>\n * Photo Web Service Protocol [MS-OXWSPHOTO]\n *  <http://msdn.microsoft.com/en-us/library/jj194353.aspx>\n * FindPeople operation\n *  <http://msdn.microsoft.com/en-us/library/office/jj191039.aspx>\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <string.h>\n\n#include <glib.h>\n#include <time.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-buddy.h\"\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-ews-autodiscover.h\"\n#include \"sipe-group.h\"\n#include \"sipe-http.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-subscriptions.h\"\n#include \"sipe-ucs.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n\nstruct sipe_ucs_transaction {\n\tGSList *pending_requests;\n};\n\ntypedef void (ucs_callback)(struct sipe_core_private *sipe_private,\n\t\t\t    struct sipe_ucs_transaction *trans,\n\t\t\t    const sipe_xml *body,\n\t\t\t    gpointer callback_data);\n\nstruct ucs_request {\n\tgchar *body;\n\tucs_callback *cb;\n\tgpointer cb_data;\n\tstruct sipe_ucs_transaction *transaction;\n\tstruct sipe_http_request *request;\n};\n\nstruct sipe_ucs {\n\tstruct ucs_request *active_request;\n\tGSList *transactions;\n\tGSList *default_transaction;\n\tgchar *ews_url;\n\ttime_t last_response;\n\tguint group_id;\n\tgboolean migrated;\n\tgboolean shutting_down;\n};\n\nstatic void sipe_ucs_request_free(struct sipe_core_private *sipe_private,\n\t\t\t\t  struct ucs_request *data)\n{\n\tstruct sipe_ucs *ucs = sipe_private->ucs;\n\tstruct sipe_ucs_transaction *trans = data->transaction;\n\n\t/* remove request from transaction */\n\ttrans->pending_requests = g_slist_remove(trans->pending_requests,\n\t\t\t\t\t\t data);\n\tsipe_private->ucs->active_request = NULL;\n\n\t/* remove completed transactions (except default transaction) */\n\tif (!trans->pending_requests &&\n\t    (trans != ucs->default_transaction->data)) {\n\t\tucs->transactions = g_slist_remove(ucs->transactions,\n\t\t\t\t\t\t   trans);\n\t\tg_free(trans);\n\t}\n\n\tif (data->request)\n\t\tsipe_http_request_cancel(data->request);\n\tif (data->cb)\n\t\t/* Callback: aborted */\n\t\t(*data->cb)(sipe_private, NULL, NULL, data->cb_data);\n\tg_free(data->body);\n\tg_free(data);\n}\n\nstatic void sipe_ucs_next_request(struct sipe_core_private *sipe_private);\nstatic void sipe_ucs_http_response(struct sipe_core_private *sipe_private,\n\t\t\t\t   guint status,\n\t\t\t\t   SIPE_UNUSED_PARAMETER GSList *headers,\n\t\t\t\t   const gchar *body,\n\t\t\t\t   gpointer callback_data)\n{\n\tstruct ucs_request *data = callback_data;\n\n\tSIPE_DEBUG_INFO(\"sipe_ucs_http_response: code %d\", status);\n\tdata->request = NULL;\n\n\tif ((status == SIPE_HTTP_STATUS_OK) && body) {\n\t\tsipe_xml *xml = sipe_xml_parse(body, strlen(body));\n\t\tconst sipe_xml *soap_body = sipe_xml_child(xml, \"Body\");\n\t\t/* Callback: success */\n\t\t(*data->cb)(sipe_private,\n\t\t\t    data->transaction,\n\t\t\t    soap_body,\n\t\t\t    data->cb_data);\n\t\tsipe_xml_free(xml);\n\t} else {\n\t\t/* Callback: failed */\n\t\t(*data->cb)(sipe_private, NULL, NULL, data->cb_data);\n\t}\n\n\t/* already been called */\n\tdata->cb = NULL;\n\n\tsipe_ucs_request_free(sipe_private, data);\n\tsipe_ucs_next_request(sipe_private);\n}\n\nstatic void sipe_ucs_next_request(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_ucs *ucs = sipe_private->ucs;\n\tstruct sipe_ucs_transaction *trans;\n\n\tif (ucs->active_request || ucs->shutting_down || !ucs->ews_url)\n\t\treturn;\n\n\ttrans = ucs->transactions->data;\n\twhile (trans->pending_requests) {\n\t\tstruct ucs_request *data = trans->pending_requests->data;\n\t\tgchar *soap = g_strdup_printf(\"<?xml version=\\\"1.0\\\"?>\\r\\n\"\n\t\t\t\t\t      \"<soap:Envelope\"\n\t\t\t\t\t      \" xmlns:m=\\\"http://schemas.microsoft.com/exchange/services/2006/messages\\\"\"\n\t\t\t\t\t      \" xmlns:soap=\\\"http://schemas.xmlsoap.org/soap/envelope/\\\"\"\n\t\t\t\t\t      \" xmlns:t=\\\"http://schemas.microsoft.com/exchange/services/2006/types\\\"\"\n\t\t\t\t\t      \" >\"\n\t\t\t\t\t      \" <soap:Header>\"\n\t\t\t\t\t      \"  <t:RequestServerVersion Version=\\\"Exchange2013\\\" />\"\n\t\t\t\t\t      \" </soap:Header>\"\n\t\t\t\t\t      \" <soap:Body>\"\n\t\t\t\t\t      \"  %s\"\n\t\t\t\t\t      \" </soap:Body>\"\n\t\t\t\t\t      \"</soap:Envelope>\",\n\t\t\t\t\t      data->body);\n\t\tstruct sipe_http_request *request = sipe_http_request_post(sipe_private,\n\t\t\t\t\t\t\t\t\t   ucs->ews_url,\n\t\t\t\t\t\t\t\t\t   NULL,\n\t\t\t\t\t\t\t\t\t   soap,\n\t\t\t\t\t\t\t\t\t   \"text/xml; charset=UTF-8\",\n\t\t\t\t\t\t\t\t\t   sipe_ucs_http_response,\n\t\t\t\t\t\t\t\t\t   data);\n\t\tg_free(soap);\n\n\t\tif (request) {\n\t\t\tg_free(data->body);\n\t\t\tdata->body    = NULL;\n\t\t\tdata->request = request;\n\n\t\t\tucs->active_request = data;\n\n\t\t\tsipe_core_email_authentication(sipe_private,\n\t\t\t\t\t\t       request);\n\t\t\tsipe_http_request_allow_redirect(request);\n\t\t\tsipe_http_request_ready(request);\n\n\t\t\tbreak;\n\t\t} else {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_ucs_next_request: failed to create HTTP connection\");\n\t\t\tsipe_ucs_request_free(sipe_private, data);\n\t\t}\n\t}\n}\n\nstatic gboolean sipe_ucs_http_request(struct sipe_core_private *sipe_private,\n\t\t\t\t      struct sipe_ucs_transaction *trans,\n\t\t\t\t      gchar *body,  /* takes ownership */\n\t\t\t\t      ucs_callback *callback,\n\t\t\t\t      gpointer callback_data)\n{\n\tstruct sipe_ucs *ucs = sipe_private->ucs;\n\n\tif (!ucs || ucs->shutting_down) {\n\t\tSIPE_DEBUG_ERROR(\"sipe_ucs_http_request: new UCS request during shutdown: THIS SHOULD NOT HAPPEN! Debugging information:\\n\"\n\t\t\t\t \"Body:   %s\\n\",\n\t\t\t\t body ? body : \"<EMPTY>\");\n\t\tg_free(body);\n\t\treturn(FALSE);\n\n\t} else {\n\t\tstruct ucs_request *data = g_new0(struct ucs_request, 1);\n\n\t\tdata->cb      = callback;\n\t\tdata->cb_data = callback_data;\n\t\tdata->body    = body;\n\n\t\tif (!trans)\n\t\t\ttrans = ucs->default_transaction->data;\n\t\tdata->transaction = trans;\n\t\ttrans->pending_requests = g_slist_append(trans->pending_requests,\n\t\t\t\t\t\t\t data);\n\n\t\tsipe_ucs_next_request(sipe_private);\n\t\treturn(TRUE);\n\t}\n}\n\nstruct sipe_ucs_transaction *sipe_ucs_transaction(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_ucs *ucs = sipe_private->ucs;\n\tstruct sipe_ucs_transaction *trans;\n\n\tif (!ucs)\n\t\treturn(NULL);\n\n\t/* always insert new transactions before default transaction */\n\ttrans = g_new0(struct sipe_ucs_transaction, 1);\n\tucs->transactions = g_slist_insert_before(ucs->transactions,\n\t\t\t\t\t\t  ucs->default_transaction,\n\t\t\t\t\t\t  trans);\n\n\treturn(trans);\n}\n\nstatic void sipe_ucs_search_response(struct sipe_core_private *sipe_private,\n\t\t\t\t     SIPE_UNUSED_PARAMETER struct sipe_ucs_transaction *trans,\n\t\t\t\t     const sipe_xml *body,\n\t\t\t\t     gpointer callback_data)\n{\n\tconst sipe_xml *persona_node;\n\tstruct sipe_backend_search_results *results = NULL;\n\tguint match_count = 0;\n\n\tfor (persona_node = sipe_xml_child(body,\n\t\t\t\t\t   \"FindPeopleResponse/People/Persona\");\n\t     persona_node;\n\t     persona_node = sipe_xml_twin(persona_node)) {\n\t\tconst sipe_xml *address = sipe_xml_child(persona_node,\n\t\t\t\t\t\t\t \"ImAddress\");\n\n\t\t/* only display Persona nodes which have an \"ImAddress\" node */\n\t\tif (address) {\n\t\t\tgchar *uri;\n\t\t\tgchar *displayname;\n\t\t\tgchar *company;\n\t\t\tgchar *email;\n\n\t\t\t/* OK, we found something - show the results to the user */\n\t\t\tmatch_count++;\n\t\t\tif (!results) {\n\t\t\t\tresults = sipe_backend_search_results_start(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t\t    callback_data);\n\t\t\t\tif (!results) {\n\t\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_ucs_search_response: Unable to display the search results.\");\n\t\t\t\t\tsipe_backend_search_failed(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\t   callback_data,\n\t\t\t\t\t\t\t\t   _(\"Unable to display the search results\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\turi         = sipe_xml_data(address);\n\t\t\tdisplayname = sipe_xml_data(sipe_xml_child(persona_node,\n\t\t\t\t\t\t\t\t   \"DisplayName\"));\n\t\t\tcompany     = sipe_xml_data(sipe_xml_child(persona_node,\n\t\t\t\t\t\t\t\t   \"CompanyName\"));\n\t\t\temail       = sipe_xml_data(sipe_xml_child(persona_node,\n\t\t\t\t\t\t\t\t   \"EmailAddress/EmailAddress\"));\n\n\t\t\tsipe_backend_search_results_add(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\tresults,\n\t\t\t\t\t\t\tsipe_get_no_sip_uri(uri),\n\t\t\t\t\t\t\tdisplayname,\n\t\t\t\t\t\t\tcompany,\n\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\temail);\n\n\t\t\tg_free(email);\n\t\t\tg_free(company);\n\t\t\tg_free(displayname);\n\t\t\tg_free(uri);\n\t\t}\n\t}\n\n\tif (match_count > 0)\n\t\tsipe_buddy_search_contacts_finalize(sipe_private,\n\t\t\t\t\t\t    results,\n\t\t\t\t\t\t    match_count,\n\t\t\t\t\t\t    FALSE);\n\telse\n\t\tsipe_backend_search_failed(SIPE_CORE_PUBLIC,\n\t\t\t\t\t   callback_data,\n\t\t\t\t\t   _(\"No contacts found\"));\n}\n\nvoid sipe_ucs_search(struct sipe_core_private *sipe_private,\n\t\t     struct sipe_backend_search_token *token,\n\t\t     const gchar *given_name,\n\t\t     const gchar *surname,\n\t\t     const gchar *email,\n\t\t     const gchar *sipid,\n\t\t     const gchar *company,\n\t\t     const gchar *country)\n{\n\tguint count    = 0;\n\tGString *query = g_string_new(NULL);\n\n\t/*\n\t * Search GAL for matching entries\n\t *\n\t * QueryString should support field properties and quoting (\"\")\n\t * according to the specification. But in my trials I couldn't get\n\t * them to work. Concatenate all query words to a single string.\n\t * Only items that match ALL words will be returned by this query.\n\t */\n#define ADD_QUERY_VALUE(val)\t\t\t       \\\n\tif (val) {\t\t\t\t       \\\n\t\tif (count++)\t\t\t       \\\n\t\t\tg_string_append_c(query, ' '); \\\n\t\tg_string_append(query, val);\t       \\\n\t}\n\n\tADD_QUERY_VALUE(given_name);\n\tADD_QUERY_VALUE(surname);\n\tADD_QUERY_VALUE(email);\n\tADD_QUERY_VALUE(sipid);\n\tADD_QUERY_VALUE(company);\n\tADD_QUERY_VALUE(country);\n\n\tif (count > 0) {\n\t\tgchar *body = g_markup_printf_escaped(\"<m:FindPeople>\"\n\t\t\t\t\t\t      \" <m:PersonaShape>\"\n\t\t\t\t\t\t      \"  <t:BaseShape>IdOnly</t:BaseShape>\"\n\t\t\t\t\t\t      \"  <t:AdditionalProperties>\"\n\t\t\t\t\t\t      \"   <t:FieldURI FieldURI=\\\"persona:CompanyName\\\"/>\"\n\t\t\t\t\t\t      \"   <t:FieldURI FieldURI=\\\"persona:DisplayName\\\"/>\"\n\t\t\t\t\t\t      \"   <t:FieldURI FieldURI=\\\"persona:EmailAddress\\\"/>\"\n\t\t\t\t\t\t      \"   <t:FieldURI FieldURI=\\\"persona:ImAddress\\\"/>\"\n\t\t\t\t\t\t      /* Locations doesn't seem to work\n\t\t\t\t\t\t      \"   <t:FieldURI FieldURI=\\\"persona:Locations\\\"/>\"\n\t\t\t\t\t\t      */\n\t\t\t\t\t\t      \"  </t:AdditionalProperties>\"\n\t\t\t\t\t\t      \" </m:PersonaShape>\"\n\t\t\t\t\t\t      \" <m:IndexedPageItemView BasePoint=\\\"Beginning\\\" MaxEntriesReturned=\\\"100\\\" Offset=\\\"0\\\"/>\"\n\t\t\t\t\t\t      /*\n\t\t\t\t\t\t       * I have no idea why Exchnage doesn't accept this\n\t\t\t\t\t\t       * FieldURI for restrictions. Without it the search\n\t\t\t\t\t\t       * will return users that don't have an ImAddress\n\t\t\t\t\t\t       * and we need to filter them out ourselves :-(\n\t\t\t\t\t\t      \" <m:Restriction>\"\n\t\t\t\t\t\t      \"  <t:Exists>\"\n\t\t\t\t\t\t      \"   <t:FieldURI FieldURI=\\\"persona:ImAddress\\\"/>\"\n\t\t\t\t\t\t      \"  </t:Exists>\"\n\t\t\t\t\t\t      \" </m:Restriction>\"\n\t\t\t\t\t\t      */\n\t\t\t\t\t\t      \" <m:ParentFolderId>\"\n\t\t\t\t\t\t      \"  <t:DistinguishedFolderId Id=\\\"directory\\\"/>\"\n\t\t\t\t\t\t      \" </m:ParentFolderId>\"\n\t\t\t\t\t\t      \" <m:QueryString>%s</m:QueryString>\"\n\t\t\t\t\t\t      \"</m:FindPeople>\",\n\t\t\t\t\t\t      query->str);\n\n\t\tif (!sipe_ucs_http_request(sipe_private,\n\t\t\t\t\t   NULL,\n\t\t\t\t\t   body,\n\t\t\t\t\t   sipe_ucs_search_response,\n\t\t\t\t\t   token))\n\t\t\tsipe_backend_search_failed(SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t   token,\n\t\t\t\t\t\t   _(\"Contact search failed\"));\n\t} else\n\t\tsipe_backend_search_failed(SIPE_CORE_PUBLIC,\n\t\t\t\t\t   token,\n\t\t\t\t\t   _(\"Invalid contact search query\"));\n\n\tg_string_free(query, TRUE);\n}\n\nstatic void sipe_ucs_ignore_response(struct sipe_core_private *sipe_private,\n\t\t\t\t     SIPE_UNUSED_PARAMETER struct sipe_ucs_transaction *trans,\n\t\t\t\t     SIPE_UNUSED_PARAMETER const sipe_xml *body,\n\t\t\t\t     SIPE_UNUSED_PARAMETER gpointer callback_data)\n{\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_ucs_ignore_response: done\");\n\tsipe_private->ucs->last_response = time(NULL);\n}\n\nstatic void ucs_extract_keys(const sipe_xml *persona_node,\n\t\t\t     const gchar **key,\n\t\t\t     const gchar **change)\n{\n\tconst sipe_xml *attr_node;\n\n\t/*\n\t * extract Exchange key - play the guessing game :-(\n\t *\n\t * We can't use the \"DisplayName\" node, because the text is localized.\n\t *\n\t * Assume that IsQuickContact == \"true\" and IsHidden == \"false\" means\n\t * this Attribution node contains the information for the Lync contact.\n\t */\n\tfor (attr_node = sipe_xml_child(persona_node,\n\t\t\t\t\t\"Attributions/Attribution\");\n\t     attr_node;\n\t     attr_node = sipe_xml_twin(attr_node)) {\n\t\tconst sipe_xml *id_node = sipe_xml_child(attr_node,\n\t\t\t\t\t\t\t \"SourceId\");\n\t\tgchar *hidden = sipe_xml_data(sipe_xml_child(attr_node,\n\t\t\t\t\t\t\t     \"IsHidden\"));\n\t\tgchar *quick = sipe_xml_data(sipe_xml_child(attr_node,\n\t\t\t\t\t\t\t    \"IsQuickContact\"));\n\t\tif (id_node &&\n\t\t    sipe_strcase_equal(hidden, \"false\") &&\n\t\t    sipe_strcase_equal(quick,  \"true\")) {\n\t\t\t*key = sipe_xml_attribute(id_node, \"Id\");\n\t\t\t*change = sipe_xml_attribute(id_node, \"ChangeKey\");\n\t\t\tg_free(quick);\n\t\t\tg_free(hidden);\n\t\t\tbreak;\n\t\t}\n\t\tg_free(quick);\n\t\tg_free(hidden);\n\t}\n}\n\nstatic void sipe_ucs_add_new_im_contact_to_group_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\t\t  SIPE_UNUSED_PARAMETER struct sipe_ucs_transaction *trans,\n\t\t\t\t\t\t\t  const sipe_xml *body,\n\t\t\t\t\t\t\t  gpointer callback_data)\n{\n\tgchar *who = callback_data;\n\tstruct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private, who);\n\tconst sipe_xml *persona_node = sipe_xml_child(body,\n\t\t\t\t\t\t      \"AddNewImContactToGroupResponse/Persona\");\n\n\tsipe_private->ucs->last_response = time(NULL);\n\n\tif (persona_node                  &&\n\t    buddy                         &&\n\t    is_empty(buddy->exchange_key) &&\n\t    is_empty(buddy->change_key)) {\n\t\tconst gchar *key = NULL;\n\t\tconst gchar *change = NULL;\n\n\t\tucs_extract_keys(persona_node, &key, &change);\n\n\t\tif (!is_empty(key) && !is_empty(change)) {\n\n\t\t\tsipe_buddy_add_keys(sipe_private,\n\t\t\t\t\t    buddy,\n\t\t\t\t\t    key,\n\t\t\t\t\t    change);\n\n\t\t\tSIPE_DEBUG_INFO(\"sipe_ucs_add_new_im_contact_to_group_response: persona URI '%s' key '%s' change '%s'\",\n\t\t\t\t\tbuddy->name, key, change);\n\t\t}\n\t}\n\n\tg_free(who);\n}\n\nvoid sipe_ucs_group_add_buddy(struct sipe_core_private *sipe_private,\n\t\t\t      struct sipe_ucs_transaction *trans,\n\t\t\t      struct sipe_group *group,\n\t\t\t      struct sipe_buddy *buddy,\n\t\t\t      const gchar *who)\n{\n\t/* existing or new buddy? */\n\tif (buddy && buddy->exchange_key) {\n\t\tgchar *body = g_strdup_printf(\"<m:AddImContactToGroup>\"\n\t\t\t\t\t      \" <m:ContactId Id=\\\"%s\\\" ChangeKey=\\\"%s\\\"/>\"\n\t\t\t\t\t      \" <m:GroupId Id=\\\"%s\\\" ChangeKey=\\\"%s\\\"/>\"\n\t\t\t\t\t      \"</m:AddImContactToGroup>\",\n\t\t\t\t\t      buddy->exchange_key,\n\t\t\t\t\t      buddy->change_key,\n\t\t\t\t\t      group->exchange_key,\n\t\t\t\t\t      group->change_key);\n\n\t\tsipe_ucs_http_request(sipe_private,\n\t\t\t\t      trans,\n\t\t\t\t      body,\n\t\t\t\t      sipe_ucs_ignore_response,\n\t\t\t\t      NULL);\n\t} else {\n\t\tgchar *payload = g_strdup(who);\n\t\tgchar *body = g_strdup_printf(\"<m:AddNewImContactToGroup>\"\n\t\t\t\t\t      \" <m:ImAddress>%s</m:ImAddress>\"\n\t\t\t\t\t      \" <m:GroupId Id=\\\"%s\\\" ChangeKey=\\\"%s\\\"/>\"\n\t\t\t\t\t      \"</m:AddNewImContactToGroup>\",\n\t\t\t\t\t      sipe_get_no_sip_uri(who),\n\t\t\t\t\t      group->exchange_key,\n\t\t\t\t\t      group->change_key);\n\n\t\tif (!sipe_ucs_http_request(sipe_private,\n\t\t\t\t\t   trans,\n\t\t\t\t\t   body,\n\t\t\t\t\t   sipe_ucs_add_new_im_contact_to_group_response,\n\t\t\t\t\t   payload))\n\t\t\tg_free(payload);\n\t}\n}\n\nvoid sipe_ucs_group_remove_buddy(struct sipe_core_private *sipe_private,\n\t\t\t\t struct sipe_ucs_transaction *trans,\n\t\t\t\t struct sipe_group *group,\n\t\t\t\t struct sipe_buddy *buddy)\n{\n\tif (group) {\n\t\t/*\n\t\t * If a contact is removed from last group, it will also be\n\t\t * removed from contact list completely. The documentation has\n\t\t * a RemoveContactFromImList operation, but that doesn't seem\n\t\t * to work at all, i.e. it is always rejected by the server.\n\t\t */\n\t\tgchar *body = g_strdup_printf(\"<m:RemoveImContactFromGroup>\"\n\t\t\t\t\t      \" <m:ContactId Id=\\\"%s\\\" ChangeKey=\\\"%s\\\"/>\"\n\t\t\t\t\t      \" <m:GroupId Id=\\\"%s\\\" ChangeKey=\\\"%s\\\"/>\"\n\t\t\t\t\t      \"</m:RemoveImContactFromGroup>\",\n\t\t\t\t\t      buddy->exchange_key,\n\t\t\t\t\t      buddy->change_key,\n\t\t\t\t\t      group->exchange_key,\n\t\t\t\t\t      group->change_key);\n\n\t\tsipe_ucs_http_request(sipe_private,\n\t\t\t\t      trans,\n\t\t\t\t      body,\n\t\t\t\t      sipe_ucs_ignore_response,\n\t\t\t\t      NULL);\n\t}\n}\n\nstatic struct sipe_group *ucs_create_group(struct sipe_core_private *sipe_private,\n\t\t\t\t\t   const sipe_xml *group_node)\n{\n\tconst sipe_xml *id_node = sipe_xml_child(group_node,\n\t\t\t\t\t\t \"ExchangeStoreId\");\n\tconst gchar *key = sipe_xml_attribute(id_node, \"Id\");\n\tconst gchar *change = sipe_xml_attribute(id_node, \"ChangeKey\");\n\tstruct sipe_group *group = NULL;\n\n\tif (!(is_empty(key) || is_empty(change))) {\n\t\tgchar *name = sipe_xml_data(sipe_xml_child(group_node,\n\t\t\t\t\t\t\t   \"DisplayName\"));\n\t\tgroup = sipe_group_add(sipe_private,\n\t\t\t\t       name,\n\t\t\t\t       key,\n\t\t\t\t       change,\n\t\t\t\t       /* sipe_group must have unique ID */\n\t\t\t\t       ++sipe_private->ucs->group_id);\n\t\tg_free(name);\n\t}\n\n\treturn(group);\n}\n\nstatic void sipe_ucs_add_im_group_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\t   struct sipe_ucs_transaction *trans,\n\t\t\t\t\t   const sipe_xml *body,\n\t\t\t\t\t   gpointer callback_data)\n{\n\tgchar *who = callback_data;\n\tconst sipe_xml *group_node = sipe_xml_child(body,\n\t\t\t\t\t\t    \"AddImGroupResponse/ImGroup\");\n\tstruct sipe_group *group = ucs_create_group(sipe_private, group_node);\n\n\tsipe_private->ucs->last_response = time(NULL);\n\n\tif (group) {\n\t\tstruct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private,\n\t\t\t\t\t\t\t\t  who);\n\n\t\tif (buddy)\n\t\t\tsipe_buddy_insert_group(buddy, group);\n\n\t\tsipe_ucs_group_add_buddy(sipe_private,\n\t\t\t\t\t trans,\n\t\t\t\t\t group,\n\t\t\t\t\t buddy,\n\t\t\t\t\t who);\n\t}\n\n\tg_free(who);\n}\n\nvoid sipe_ucs_group_create(struct sipe_core_private *sipe_private,\n\t\t\t   struct sipe_ucs_transaction *trans,\n\t\t\t   const gchar *name,\n\t\t\t   const gchar *who)\n{\n\tgchar *payload = g_strdup(who);\n\t/* new_name can contain restricted characters */\n\tgchar *body = g_markup_printf_escaped(\"<m:AddImGroup>\"\n\t\t\t\t\t      \" <m:DisplayName>%s</m:DisplayName>\"\n\t\t\t\t\t      \"</m:AddImGroup>\",\n\t\t\t\t\t      name);\n\n\tif (!sipe_ucs_http_request(sipe_private,\n\t\t\t\t   trans,\n\t\t\t\t   body,\n\t\t\t\t   sipe_ucs_add_im_group_response,\n\t\t\t\t   payload))\n\t\tg_free(payload);\n}\n\nvoid sipe_ucs_group_rename(struct sipe_core_private *sipe_private,\n\t\t\t   struct sipe_group *group,\n\t\t\t   const gchar *new_name)\n{\n\t/* new_name can contain restricted characters */\n\tgchar *body = g_markup_printf_escaped(\"<m:SetImGroup>\"\n\t\t\t\t\t      \" <m:GroupId Id=\\\"%s\\\" ChangeKey=\\\"%s\\\"/>\"\n\t\t\t\t\t      \" <m:NewDisplayName>%s</m:NewDisplayName>\"\n\t\t\t\t\t      \"</m:SetImGroup>\",\n\t\t\t\t\t      group->exchange_key,\n\t\t\t\t\t      group->change_key,\n\t\t\t\t\t      new_name);\n\n\tsipe_ucs_http_request(sipe_private,\n\t\t\t      NULL,\n\t\t\t      body,\n\t\t\t      sipe_ucs_ignore_response,\n\t\t\t      NULL);\n}\n\nvoid sipe_ucs_group_remove(struct sipe_core_private *sipe_private,\n\t\t\t   struct sipe_group *group)\n{\n\tgchar *body = g_strdup_printf(\"<m:RemoveImGroup>\"\n\t\t\t\t      \" <m:GroupId Id=\\\"%s\\\" ChangeKey=\\\"%s\\\"/>\"\n\t\t\t\t      \"</m:RemoveImGroup>\",\n\t\t\t\t      group->exchange_key,\n\t\t\t\t      group->change_key);\n\n\tsipe_ucs_http_request(sipe_private,\n\t\t\t      NULL,\n\t\t\t      body,\n\t\t\t      sipe_ucs_ignore_response,\n\t\t\t      NULL);\n}\n\nstatic void ucs_init_failure(struct sipe_core_private *sipe_private)\n{\n\t/* Did the user specify any email settings? */\n\tgboolean default_settings =\n\t\tis_empty(sipe_backend_setting(SIPE_CORE_PUBLIC,\n\t\t\t\t\t      SIPE_SETTING_EMAIL_URL))   &&\n\t\tis_empty(sipe_backend_setting(SIPE_CORE_PUBLIC,\n\t\t\t\t\t      SIPE_SETTING_EMAIL_LOGIN)) &&\n\t\tis_empty(sipe_backend_setting(SIPE_CORE_PUBLIC,\n\t\t\t\t\t      SIPE_SETTING_EMAIL_PASSWORD));\n\n\tsipe_backend_notify_error(SIPE_CORE_PUBLIC,\n\t\t\t\t  _(\"UCS initialization failed!\"),\n\t\t\t\t  default_settings ?\n\t\t\t\t  _(\"Couldn't find an Exchange server with the default Email settings. Therefore the contacts list will not work.\\n\\nYou'll need to provide Email settings in the account setup.\") :\n\t\t\t\t  _(\"Couldn't find an Exchange server with the Email settings provided in the account setup. Therefore the contacts list will not work.\\n\\nPlease correct your Email settings.\"));\n}\n\nstatic void sipe_ucs_get_im_item_list_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\t       SIPE_UNUSED_PARAMETER struct sipe_ucs_transaction *trans,\n\t\t\t\t\t       const sipe_xml *body,\n\t\t\t\t\t       SIPE_UNUSED_PARAMETER gpointer callback_data)\n{\n\tconst sipe_xml *node = sipe_xml_child(body,\n\t\t\t\t\t      \"GetImItemListResponse/ImItemList\");\n\n\tif (node) {\n\t\tconst sipe_xml *persona_node;\n\t\tconst sipe_xml *group_node;\n\t\tGHashTable *uri_to_alias = g_hash_table_new_full(g_str_hash,\n\t\t\t\t\t\t\t\t g_str_equal,\n\t\t\t\t\t\t\t\t NULL,\n\t\t\t\t\t\t\t\t g_free);\n\n\t\t/* Start processing contact list */\n\t\tif (SIPE_CORE_PRIVATE_FLAG_IS(SUBSCRIBED_BUDDIES)) {\n\t\t\tsipe_group_update_start(sipe_private);\n\t\t\tsipe_buddy_update_start(sipe_private);\n\t\t} else\n\t\t\tsipe_backend_buddy_list_processing_start(SIPE_CORE_PUBLIC);\n\n\t\tfor (persona_node = sipe_xml_child(node, \"Personas/Persona\");\n\t\t     persona_node;\n\t\t     persona_node = sipe_xml_twin(persona_node)) {\n\t\t\tgchar *address = sipe_xml_data(sipe_xml_child(persona_node,\n\t\t\t\t\t\t\t\t      \"ImAddress\"));\n\t\t\tconst gchar *key = NULL;\n\t\t\tconst gchar *change = NULL;\n\n\t\t\tucs_extract_keys(persona_node, &key, &change);\n\n\t\t\tif (!(is_empty(address) || is_empty(key) || is_empty(change))) {\n\t\t\t\tgchar *alias = sipe_xml_data(sipe_xml_child(persona_node,\n\t\t\t\t\t\t\t\t\t    \"DisplayName\"));\n\t\t\t\t/*\n\t\t\t\t * it seems to be undefined if ImAddress node\n\t\t\t\t * contains \"sip:\" prefix or not...\n\t\t\t\t */\n\t\t\t\tgchar *uri = sip_uri(address);\n\t\t\t\tstruct sipe_buddy *buddy = sipe_buddy_add(sipe_private,\n\t\t\t\t\t\t\t\t\t  uri,\n\t\t\t\t\t\t\t\t\t  key,\n\t\t\t\t\t\t\t\t\t  change);\n\t\t\t\tg_free(uri);\n\n\t\t\t\t/* hash table takes ownership of alias */\n\t\t\t\tg_hash_table_insert(uri_to_alias,\n\t\t\t\t\t\t    buddy->name,\n\t\t\t\t\t\t    alias);\n\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_ucs_get_im_item_list_response: persona URI '%s' key '%s' change '%s'\",\n\t\t\t\t\t\tbuddy->name, key, change);\n\t\t\t}\n\t\t\tg_free(address);\n\t\t}\n\n\t\tfor (group_node = sipe_xml_child(node, \"Groups/ImGroup\");\n\t\t     group_node;\n\t\t     group_node = sipe_xml_twin(group_node)) {\n\t\t\tstruct sipe_group *group = ucs_create_group(sipe_private,\n\t\t\t\t\t\t\t\t    group_node);\n\n\t\t\tif (group) {\n\t\t\t\tconst sipe_xml *member_node;\n\n\t\t\t\tfor (member_node = sipe_xml_child(group_node,\n\t\t\t\t\t\t\t\t  \"MemberCorrelationKey/ItemId\");\n\t\t\t\t     member_node;\n\t\t\t\t     member_node = sipe_xml_twin(member_node)) {\n\t\t\t\t\tstruct sipe_buddy *buddy = sipe_buddy_find_by_exchange_key(sipe_private,\n\t\t\t\t\t\t\t\t\t\t\t\t   sipe_xml_attribute(member_node,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t      \"Id\"));\n\t\t\t\t\tif (buddy)\n\t\t\t\t\t\tsipe_buddy_add_to_group(sipe_private,\n\t\t\t\t\t\t\t\t\tbuddy,\n\t\t\t\t\t\t\t\t\tgroup,\n\t\t\t\t\t\t\t\t\tg_hash_table_lookup(uri_to_alias,\n\t\t\t\t\t\t\t\t\t\t\t    buddy->name));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tg_hash_table_destroy(uri_to_alias);\n\n\t\t/* Finished processing contact list */\n\t\tif (SIPE_CORE_PRIVATE_FLAG_IS(SUBSCRIBED_BUDDIES)) {\n\t\t\tsipe_buddy_update_finish(sipe_private);\n\t\t\tsipe_group_update_finish(sipe_private);\n\t\t} else {\n\t\t\tsipe_buddy_cleanup_local_list(sipe_private);\n\t\t\tsipe_backend_buddy_list_processing_finish(SIPE_CORE_PUBLIC);\n\t\t\tsipe_subscribe_presence_initial(sipe_private);\n\t\t}\n\t} else if (sipe_private->ucs) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_ucs_get_im_item_list_response: query failed, contact list operations will not work!\");\n\t\tucs_init_failure(sipe_private);\n\t}\n}\n\nstatic void ucs_get_im_item_list(struct sipe_core_private *sipe_private)\n{\n\tif (sipe_private->ucs->migrated)\n\t\tsipe_ucs_http_request(sipe_private,\n\t\t\t\t      /* prioritize over pending default requests */\n\t\t\t\t      sipe_ucs_transaction(sipe_private),\n\t\t\t\t      g_strdup(\"<m:GetImItemList/>\"),\n\t\t\t\t      sipe_ucs_get_im_item_list_response,\n\t\t\t\t      NULL);\n}\n\nstatic void ucs_set_ews_url(struct sipe_core_private *sipe_private,\n\t\t      const gchar *ews_url)\n{\n\tstruct sipe_ucs *ucs = sipe_private->ucs;\n\n\tSIPE_DEBUG_INFO(\"ucs_set_ews_url: '%s'\", ews_url);\n\tucs->ews_url = g_strdup(ews_url);\n\n\t/* this will trigger sending of the first deferred request */\n\tucs_get_im_item_list(sipe_private);\n}\n\nstatic void ucs_ews_autodiscover_cb(struct sipe_core_private *sipe_private,\n\t\t\t\t    const struct sipe_ews_autodiscover_data *ews_data,\n\t\t\t\t    SIPE_UNUSED_PARAMETER gpointer callback_data)\n{\n\tstruct sipe_ucs *ucs = sipe_private->ucs;\n\tconst gchar *ews_url = NULL;\n\n\tif (!ucs)\n\t\treturn;\n\n\tif (ews_data)\n\t\tews_url = ews_data->ews_url;\n\n\tif (is_empty(ews_url)) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"ucs_ews_autodiscover_cb: can't detect EWS URL, contact list operations will not work!\");\n\t\tucs_init_failure(sipe_private);\n\t} else {\n\t\tucs_set_ews_url(sipe_private, ews_url);\n\t}\n}\n\ngboolean sipe_ucs_is_migrated(struct sipe_core_private *sipe_private)\n{\n\treturn(sipe_private->ucs ? sipe_private->ucs->migrated : FALSE);\n}\n\nconst gchar *sipe_ucs_ews_url(struct sipe_core_private *sipe_private)\n{\n\treturn(sipe_private->ucs ? sipe_private->ucs->ews_url : NULL);\n}\n\nvoid sipe_ucs_init(struct sipe_core_private *sipe_private,\n\t\t   gboolean migrated)\n{\n\tstruct sipe_ucs *ucs;\n\n\tif (sipe_private->ucs) {\n\t\tstruct sipe_ucs *ucs = sipe_private->ucs;\n\n\t\t/*\n\t\t * contact list update trigger -> request list again\n\t\t *\n\t\t * If the trigger arrives less than 10 seconds after our\n\t\t * last UCS response, then ignore it, because it is caused\n\t\t * by our own changes to the contact list.\n\t\t */\n\t\tif (SIPE_CORE_PRIVATE_FLAG_IS(SUBSCRIBED_BUDDIES)) {\n\t\t\tif ((time(NULL) - ucs->last_response) >= 10)\n\t\t\t\tucs_get_im_item_list(sipe_private);\n\t\t\telse\n\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_ucs_init: ignoring this contact list update - triggered by our last change\");\n\t\t}\n\n\t\tucs->last_response = 0;\n\t\treturn;\n\t}\n\n\tsipe_private->ucs = ucs = g_new0(struct sipe_ucs, 1);\n\tucs->migrated           = migrated;\n\n\t/* create default transaction */\n\tsipe_ucs_transaction(sipe_private);\n\tucs->default_transaction = ucs->transactions;\n\n\tif (migrated) {\n\t\t/* user specified a service URL? */\n\t\tconst gchar *ews_url = sipe_backend_setting(SIPE_CORE_PUBLIC, SIPE_SETTING_EMAIL_URL);\n\n\t\tif (is_empty(ews_url))\n\t\t\tsipe_ews_autodiscover_start(sipe_private,\n\t\t\t\t\t\t    ucs_ews_autodiscover_cb,\n\t\t\t\t\t\t    NULL);\n\t\telse\n\t\t\tucs_set_ews_url(sipe_private, ews_url);\n\t}\n}\n\nvoid sipe_ucs_free(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_ucs *ucs = sipe_private->ucs;\n\tGSList *entry;\n\n\tif (!ucs)\n\t\treturn;\n\n\t/* UCS stack is shutting down: reject all new requests */\n\tucs->shutting_down = TRUE;\n\n\tentry = ucs->transactions;\n\twhile (entry) {\n\t\tstruct sipe_ucs_transaction *trans = entry->data;\n\t\tGSList *entry2 = trans->pending_requests;\n\n\t\t/* transactions get deleted by sipe_ucs_request_free() */\n\t\tentry = entry->next;\n\n\t\twhile (entry2) {\n\t\t\tstruct ucs_request *request = entry2->data;\n\n\t\t\t/* transactions get deleted by sipe_ucs_request_free() */\n\t\t\tentry2 = entry2->next;\n\n\t\t\tsipe_ucs_request_free(sipe_private, request);\n\t\t}\n\n\t}\n\t/* only default transaction is left... */\n\tsipe_utils_slist_free_full(ucs->transactions, g_free);\n\n\tg_free(ucs->ews_url);\n\tg_free(ucs);\n\tsipe_private->ucs = NULL;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-ucs.h",
    "content": "/**\n * @file sipe-ucs.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013-2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sipe_backend_search_token;\nstruct sipe_buddy;\nstruct sipe_core_private;\nstruct sipe_group;\nstruct sipe_ucs_transaction;\n\n/**\n * Search EWS contact list\n *\n * This is not directly related to UCS, but we can reuse the code.\n *\n * @param sipe_private SIPE core private data\n * @param token        opaque search token provided by backend\n * @param given_name   search parameters provided by the user...\n * @param surname\n * @param email\n * @param sipid\n * @param company\n * @param country\n */\nvoid sipe_ucs_search(struct sipe_core_private *sipe_private,\n\t\t     struct sipe_backend_search_token *token,\n\t\t     const gchar *given_name,\n\t\t     const gchar *surname,\n\t\t     const gchar *email,\n\t\t     const gchar *sipid,\n\t\t     const gchar *company,\n\t\t     const gchar *country);\n\n/**\n * Has contact list been migrated to UCS?\n *\n * @param sipe_private SIPE core private data\n *\n * @return @c TRUE if contact list has been migrated\n */\ngboolean sipe_ucs_is_migrated(struct sipe_core_private *sipe_private);\n\n/**\n * Returns UCS EWS URL\n *\n * @param sipe_private SIPE core private data\n *\n * @return EWS URL string\n */\nconst gchar *sipe_ucs_ews_url(struct sipe_core_private *sipe_private);\n\n/**\n * Create new UCS transactions\n *\n * @param sipe_private SIPE core private data\n *\n * @return UCS transaction\n */\nstruct sipe_ucs_transaction *sipe_ucs_transaction(struct sipe_core_private *sipe_private);\n\n/**\n * Add existing/new buddy to group\n *\n * @param sipe_private SIPE core private data\n * @param trans        UCS transaction (may be @c NULL)\n * @param group        sipe_group structure\n * @param buddy        sipe_buddy structure (may be @c NULL)\n * @param who          SIP URI of the new buddy\n */\nvoid sipe_ucs_group_add_buddy(struct sipe_core_private *sipe_private,\n\t\t\t      struct sipe_ucs_transaction *trans,\n\t\t\t      struct sipe_group *group,\n\t\t\t      struct sipe_buddy *buddy,\n\t\t\t      const gchar *who);\n\n/**\n * Remove buddy from group\n *\n * @param sipe_private SIPE core private data\n * @param trans        UCS transaction (may be @c NULL)\n * @param group        sipe_group structure (may be @c NULL)\n * @param buddy        sipe_buddy structure\n */\nvoid sipe_ucs_group_remove_buddy(struct sipe_core_private *sipe_private,\n\t\t\t\t struct sipe_ucs_transaction *trans,\n\t\t\t\t struct sipe_group *group,\n\t\t\t\t struct sipe_buddy *buddy);\n\n/**\n * Create group\n *\n * @param sipe_private SIPE core private data\n * @param trans        UCS transaction (may be @c NULL)\n * @param name         name for group\n * @param who          SIP URI of the buddy to add to the new group\n */\nvoid sipe_ucs_group_create(struct sipe_core_private *sipe_private,\n\t\t\t   struct sipe_ucs_transaction *trans,\n\t\t\t   const gchar *name,\n\t\t\t   const gchar *who);\n\n/**\n * Rename group\n *\n * @param sipe_private SIPE core private data\n * @param group        sipe_group structure\n * @param new_name     new name for group\n */\nvoid sipe_ucs_group_rename(struct sipe_core_private *sipe_private,\n\t\t\t   struct sipe_group *group,\n\t\t\t   const gchar *new_name);\n\n/**\n * Remove group\n *\n * @param sipe_private SIPE core private data\n * @param group        sipe_group structure\n */\nvoid sipe_ucs_group_remove(struct sipe_core_private *sipe_private,\n\t\t\t   struct sipe_group *group);\n\n/**\n * Initialize UCS\n *\n * @param sipe_private SIPE core private data\n * @param migrated     @c TRUE if contact list has been migrated\n */\nvoid sipe_ucs_init(struct sipe_core_private *sipe_private,\n\t\t   gboolean migrated);\n\n/**\n * Free UCS data\n *\n * @param sipe_private SIPE core private data\n */\nvoid sipe_ucs_free(struct sipe_core_private *sipe_private);\n"
  },
  {
    "path": "src/core/sipe-user.c",
    "content": "/**\n * @file sipe-user.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipmsg.h\"\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-chat.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-dialog.h\"\n#include \"sipe-im.h\"\n#include \"sipe-nls.h\"\n#include \"sipe-session.h\"\n#include \"sipe-user.h\"\n#include \"sipe-utils.h\"\n\nvoid sipe_user_present_info(struct sipe_core_private *sipe_private,\n\t\t\t    struct sip_session *session,\n\t\t\t    const gchar *message)\n{\n\tsipe_backend_notify_message_info(SIPE_CORE_PUBLIC,\n\t\t\t\t\t session->chat_session ? session->chat_session->backend : NULL,\n\t\t\t\t\t session->with,\n\t\t\t\t\t message);\n}\n\nvoid sipe_user_present_error(struct sipe_core_private *sipe_private,\n\t\t\t     struct sip_session *session,\n\t\t\t     const gchar *message)\n{\n\tsipe_backend_notify_message_error(SIPE_CORE_PUBLIC,\n\t\t\t\t\t  session->chat_session ? session->chat_session->backend : NULL,\n\t\t\t\t\t  session->with,\n\t\t\t\t\t  message);\n}\n\nvoid sipe_user_present_message_undelivered(struct sipe_core_private *sipe_private,\n\t\t\t\t\t   struct sip_session *session,\n\t\t\t\t\t   int sip_error,\n\t\t\t\t\t   int sip_warning,\n\t\t\t\t\t   const gchar *who,\n\t\t\t\t\t   const gchar *message)\n{\n\tchar *msg, *msg_tmp, *msg_tmp2;\n\tconst char *label;\n\n\tmsg_tmp = message ? sipe_backend_markup_strip_html(message) : NULL;\n\tmsg = msg_tmp ? g_strdup_printf(\"<font color=\\\"#888888\\\"></b>%s<b></font>\", msg_tmp) : NULL;\n\tg_free(msg_tmp);\n\t/* Service unavailable; Server Internal Error; Server Time-out */\n\tif (sip_error == 606 && sip_warning == 309) { /* Not acceptable all. */ /* Message contents not allowed by policy */\n\t\tlabel = _(\"Your message or invitation was not delivered, possibly because it contains a hyperlink or other content that the system administrator has blocked.\");\n\t\tg_free(msg);\n\t\tmsg = NULL;\n\t} else if (sip_error == 500 || sip_error == 503 || sip_error == 504 || sip_error == 603) {\n\t\tlabel = _(\"This message was not delivered to %s because the service is not available\");\n\t} else if (sip_error == 486) { /* Busy Here */\n\t\tlabel = _(\"This message was not delivered to %s because one or more recipients do not want to be disturbed\");\n\t} else if (sip_error == 415) { /* Unsupported media type */\n\t\tlabel = _(\"This message was not delivered to %s because one or more recipients don't support this type of message\");\n\t} else {\n\t\tlabel = _(\"This message was not delivered to %s because one or more recipients are offline\");\n\t}\n\n\tmsg_tmp = g_strdup_printf( \"%s%s\\n%s\" ,\n\t\t\tmsg_tmp2 = g_strdup_printf(label, who ? who : \"\"),\n\t\t\tmsg ? \":\" : \"\",\n\t\t\tmsg ? msg : \"\");\n\tsipe_user_present_error(sipe_private, session, msg_tmp);\n\tg_free(msg_tmp2);\n\tg_free(msg_tmp);\n\tg_free(msg);\n}\n\nstatic gboolean process_info_typing_response(struct sipe_core_private *sipe_private,\n\t\t\t\t\t     struct sipmsg *msg,\n\t\t\t\t\t     SIPE_UNUSED_PARAMETER struct transaction *trans)\n{\n\t/* Indicates dangling IM session which needs to be dropped */\n\tif (msg->response == 408 || /* Request timeout */\n\t    msg->response == 480 || /* Temporarily Unavailable */\n\t    msg->response == 481) { /* Call/Transaction Does Not Exist */\n\t\tgchar *with = sipmsg_parse_to_address(msg);\n\t\tstruct sip_session *session = sipe_session_find_im(sipe_private, with);\n\t\tstruct sip_dialog *dialog = sipe_dialog_find(session, with);\n\t\tif (dialog)\n\t\t\tsipe_im_cancel_dangling(sipe_private, session, dialog, with,\n\t\t\t\t\t\tsipe_im_cancel_unconfirmed);\n\t\tg_free(with);\n\t}\t\n\treturn(TRUE);\n}\n\nvoid sipe_core_user_feedback_typing(struct sipe_core_public *sipe_public,\n\t\t\t\t    const gchar *to,\n\t\t\t\t    gboolean typing)\n{\n\tstruct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;\n\tstruct sip_session *session = sipe_session_find_im(sipe_private, to);\n\tstruct sip_dialog *dialog = sipe_dialog_find(session, to);\n\n\t/* only enable this debug output while testing\n\tSIPE_DEBUG_INFO(\"sipe_core_user_feedback_typing session %p (%s) dialog %p (%s) established %s\",\n\t\t\tsession, session ? session->callid : \"N/A\",\n\t\t\tdialog, dialog ? dialog->callid : \"N/A\",\n\t\t\t(dialog && dialog->is_established) ? \"YES\" : \"NO\"); */\n\n\tif (session && dialog && dialog->is_established) {\n\t\tgchar *body = g_strdup_printf(\"<?xml version=\\\"1.0\\\"?>\"\n\t\t\t\t\t      \"<KeyboardActivity>\"\n\t\t\t\t\t      \" <status status=\\\"%s\\\" />\"\n\t\t\t\t\t      \"</KeyboardActivity>\",\n\t\t\t\t\t      typing ? \"type\" : \"idle\");\n\t\tsip_transport_info(sipe_private,\n\t\t\t\t   \"Content-Type: application/xml\\r\\n\",\n\t\t\t\t   body,\n\t\t\t\t   dialog,\n\t\t\t\t   process_info_typing_response);\n\t\tg_free(body);\n\t}\n}\n\nstruct sipe_user_ask_ctx {\n\tstruct sipe_core_private *sipe_private;\n\tgpointer accept_cb;\n\tgpointer decline_cb;\n\tgpointer data;\n};\n\nstruct sipe_user_ask_ctx * sipe_user_ask(struct sipe_core_private *sipe_private,\n\t\t\t\t\t const gchar *message,\n\t\t\t\t\t const gchar *accept_label,\n\t\t\t\t\t SipeUserAskCb accept_cb,\n\t\t\t\t\t const gchar *decline_label,\n\t\t\t\t\t SipeUserAskCb decline_cb,\n\t\t\t\t\t gpointer data)\n{\n\tstruct sipe_user_ask_ctx *ctx = g_new0(struct sipe_user_ask_ctx, 1);\n\tctx->sipe_private = sipe_private;\n\tctx->accept_cb = accept_cb;\n\tctx->decline_cb = decline_cb;\n\tctx->data = data;\n\n\tsipe_backend_user_ask(SIPE_CORE_PUBLIC, message,\n\t\t\t      accept_label, decline_label,\n\t\t\t      ctx);\n\n\treturn ctx;\n}\n\nvoid sipe_core_user_ask_cb(gpointer context, gboolean accepted)\n{\n\tstruct sipe_user_ask_ctx *ctx = context;\n\n\tif (accepted && ctx->accept_cb)\n\t\t((SipeUserAskCb)ctx->accept_cb)(ctx->sipe_private, ctx->data);\n\telse if (ctx->decline_cb)\n\t\t((SipeUserAskCb)ctx->decline_cb)(ctx->sipe_private, ctx->data);\n\n\tg_free(ctx);\n}\n\nstruct sipe_user_ask_ctx * sipe_user_ask_choice(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\tconst gchar *message,\n\t\t\t\t\t\tGSList *choices,\n\t\t\t\t\t\tSipeUserAskChoiceCb callback,\n\t\t\t\t\t\tgpointer data)\n{\n\tstruct sipe_user_ask_ctx *ctx = g_new0(struct sipe_user_ask_ctx, 1);\n\tctx->sipe_private = sipe_private;\n\tctx->accept_cb = callback;\n\tctx->decline_cb = NULL;\n\tctx->data = data;\n\n\tsipe_backend_user_ask_choice(SIPE_CORE_PUBLIC, message, choices, ctx);\n\n\treturn ctx;\n}\n\nvoid sipe_core_user_ask_choice_cb(gpointer context, guint choice_id)\n{\n\tstruct sipe_user_ask_ctx *ctx = context;\n\n\tif (ctx->accept_cb) {\n\t\t((SipeUserAskChoiceCb)ctx->accept_cb)(ctx->sipe_private,\n\t\t\t\t\t\t      ctx->data, choice_id);\n\t}\n\n\tg_free(ctx);\n}\n\nvoid sipe_user_close_ask(struct sipe_user_ask_ctx *context)\n{\n\tsipe_backend_user_close_ask(context);\n\tg_free(context);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-user.h",
    "content": "/**\n * @file sipe-user.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct sip_session;\nstruct sipe_core_private;\n\n/* Opaque ask context structure */\nstruct sipe_user_ask_ctx;\n\n/**\n * Present error message in users session\n *\n * @param sipe_private SIPE core private data\n * @param session      session for the conversation\n * @param message      message text\n */\nvoid sipe_user_present_error(struct sipe_core_private *sipe_private,\n\t\t\t     struct sip_session *session,\n\t\t\t     const gchar *message);\n\n/**\n * Present info message in users session\n *\n * @param sipe_private SIPE core private data\n * @param session      session for the conversation\n * @param message      message text\n */\nvoid sipe_user_present_info(struct sipe_core_private *sipe_private,\n\t\t\t    struct sip_session *session,\n\t\t\t    const gchar *message);\n\n/**\n * Present error that his message wasn't delivered in users session\n *\n * @param sipe_private SIPE core private data\n * @param session      session for the conversation\n * @param sip_error    SIP error code or -1\n * @param sip_warning  SIP warning code or -1\n * @param who          URI of recipient\n * @param message      message text\n */\nvoid sipe_user_present_message_undelivered(struct sipe_core_private *sipe_private,\n\t\t\t\t\t   struct sip_session *session,\n\t\t\t\t\t   int sip_error,\n\t\t\t\t\t   int sip_warning,\n\t\t\t\t\t   const gchar *who,\n\t\t\t\t\t   const gchar *message);\n\ntypedef void (* SipeUserAskCb)(struct sipe_core_private *, gpointer data);\n\n/**\n * Present a query that is to be accepted or declined by the user\n *\n * @param sipe_private  SIPE core private data\n * @param message       Text of the query to be shown to user\n * @param accept_label  Label to be displayed on UI control that accepts query\n * @param accept_cb     callback function to be invoked when query is accepted\n * @param decline_label Label to be displayed on UI control that declines query\n * @param decline_cb    callback function to be invoked when query is declined\n * @param data          custom user data\n *\n * @return opaque sipe_user_ask_ctx pointer that can be used to close the query\n * before user answered it.\n */\nstruct sipe_user_ask_ctx * sipe_user_ask(struct sipe_core_private *sipe_private,\n\t\t\t\t\t const gchar *message,\n\t\t\t\t\t const gchar *accept_label,\n\t\t\t\t\t SipeUserAskCb accept_cb,\n\t\t\t\t\t const gchar *decline_label,\n\t\t\t\t\t SipeUserAskCb decline_cb,\n\t\t\t\t\t gpointer data);\n\ntypedef void (* SipeUserAskChoiceCb)(struct sipe_core_private *, gpointer data,\n\t\t\t\t     guint choice_id);\n\n/**\n * Present a set of options to the user to choose from.\n *\n * @param sipe_core_private SIPE core private data\n * @param message           text message to be shown to the user\n * @param choices           list of choice options\n * @param callback          callback function to be invoked after user makes\n *                          a choice\n * @param data              custom user data to pass to callback\n */\nstruct sipe_user_ask_ctx * sipe_user_ask_choice(struct sipe_core_private *sipe_private,\n\t\t\t\t\t\tconst gchar *message,\n\t\t\t\t\t\tGSList *choices,\n\t\t\t\t\t\tSipeUserAskChoiceCb callback,\n\t\t\t\t\t\tgpointer data);\n\n/**\n * Closes the pending user query\n *\n * @param context sipe_user_ask_ctx pointer returned by sipe_user_ask()\n */\nvoid sipe_user_close_ask(struct sipe_user_ask_ctx *context);\n"
  },
  {
    "path": "src/core/sipe-utils.c",
    "content": "/**\n * @file sipe-utils.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2009-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <ctype.h>\n#include <time.h>\n\n#include <glib.h>\n\n#include \"sip-transport.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"    /* to ensure same API for backends */\n#include \"sipe-core-private.h\"\n#include \"sipe-utils.h\"\n#include \"uuid.h\"\n\n/* Generate 16 random bits */\n#define RANDOM16BITS (rand() & 0xFFFF)\n\ngchar *gencallid(void)\n{\n\treturn g_strdup_printf(\"%04Xg%04Xa%04Xi%04Xm%04Xt%04Xb%04Xx%04Xx\",\n\t\t\t       RANDOM16BITS, RANDOM16BITS, RANDOM16BITS,\n\t\t\t       RANDOM16BITS, RANDOM16BITS, RANDOM16BITS,\n\t\t\t       RANDOM16BITS, RANDOM16BITS);\n}\n\ngchar *gentag(void)\n{\n\treturn g_strdup_printf(\"%04d%04d\", RANDOM16BITS, RANDOM16BITS);\n}\n\ngchar *genconfid(void)\n{\n\treturn g_strdup_printf(\"%04X%04X%04X%04X%04X%04X%04X%04X\",\n\t\t\t       RANDOM16BITS, RANDOM16BITS, RANDOM16BITS,\n\t\t\t       RANDOM16BITS, RANDOM16BITS, RANDOM16BITS,\n\t\t\t       RANDOM16BITS, RANDOM16BITS);\n}\n\ngchar *get_contact(const struct sipe_core_private *sipe_private)\n{\n\treturn g_strdup(sipe_private->contact);\n}\n\ngchar *parse_from(const gchar *hdr)\n{\n\tgchar *from;\n\tconst gchar *tmp, *tmp2 = hdr;\n\n\tif (!hdr) return NULL;\n\tSIPE_DEBUG_INFO(\"parsing address out of %s\", hdr);\n\ttmp = strchr(hdr, '<');\n\n\t/* i hate the different SIP UA behaviours... */\n\tif (tmp) { /* sip address in <...> */\n\t\ttmp2 = tmp + 1;\n\t\ttmp = strchr(tmp2, '>');\n\t\tif (tmp) {\n\t\t\tfrom = g_strndup(tmp2, tmp - tmp2);\n\t\t} else {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"found < without > in From\");\n\t\t\treturn NULL;\n\t\t}\n\t} else {\n\t\ttmp = strchr(tmp2, ';');\n\t\tif (tmp) {\n\t\t\tfrom = g_strndup(tmp2, tmp - tmp2);\n\t\t} else {\n\t\t\tfrom = g_strdup(tmp2);\n\t\t}\n\t}\n\tSIPE_DEBUG_INFO(\"got %s\", from);\n\treturn from;\n}\n\ngchar *sip_uri_from_name(const gchar *name)\n{\n\treturn(g_strdup_printf(\"sip:%s\", name));\n}\n\ngchar *sip_uri(const gchar *string)\n{\n\treturn(strstr(string, \"sip:\") ? g_strdup(string) : sip_uri_from_name(string));\n}\n\nstatic gchar *escape_uri_part(const gchar *in, guint len)\n{\n\tgchar *escaped = NULL;\n\n\tif (len) {\n\t\tgchar *s;\n\n\t\t/* reserve space for worst case, i.e. every character needs escaping */\n\t\tescaped = s = g_malloc(3 * len + 1);\n\t\twhile (len--) {\n\t\t\tgchar c = *in++;\n\n\t\t\t/* only allow ASCII characters */\n\t\t\tif (!isascii(c)) {\n\t\t\t\tg_free(escaped);\n\t\t\t\treturn(NULL);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * RFC 3986 Appendix A\n\t\t\t *\n\t\t\t * authority     = [ userinfo \"@\" ] host [ \":\" port ]\n\t\t\t * userinfo      = *( unreserved / pct-encoded / sub-delims / \":\" )\n\t\t\t * host          = IP-literal / IPv4address / reg-name\n\t\t\t * reg-name      = *( unreserved / pct-encoded / sub-delims )\n\t\t\t * pct-encoded   = \"%\" HEXDIG HEXDIG\n\t\t\t * unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n\t\t\t *\n\t\t\t * Escape everything that isn't in \"unreserved\"\n\t\t\t */\n\t\t\tif (isalnum(c) ||\n\t\t\t    (c == '.') ||\n\t\t\t    (c == '-') ||\n\t\t\t    (c == '_') ||\n\t\t\t    (c == '~')) {\n\t\t\t\t*s++ = c;\n\t\t\t} else {\n\t\t\t\tsprintf(s, \"%%%1X%1X\", c / 16, c % 16);\n\t\t\t\ts += 3;\n\t\t\t}\n\t\t}\n\t\t*s = '\\0';\n\t}\n\n\treturn(escaped);\n}\n\ngchar *sip_uri_if_valid(const gchar *string)\n{\n\t/* strip possible sip: prefix */\n\tconst gchar *uri = sipe_get_no_sip_uri(string);\n\tconst gchar *at;\n\tgchar *result    = NULL;\n\n\t/* only XXX@YYY is valid */\n\tif (uri && ((at = strchr(uri, '@')) != NULL)) {\n\t\tgchar *userinfo = escape_uri_part(uri, at - uri);\n\n\t\tif (userinfo) {\n\t\t\tgchar *host = escape_uri_part(at + 1, strlen(at + 1));\n\n\t\t\tif (host) {\n\t\t\t\t/* name is valid for URI, convert it */\n\t\t\t\tresult = g_strdup_printf(\"sip:%s@%s\",\n\t\t\t\t\t\t\t userinfo,\n\t\t\t\t\t\t\t host);\n\t\t\t\tg_free(host);\n\t\t\t}\n\t\t\tg_free(userinfo);\n\t\t}\n\t}\n\n\treturn(result);\n}\n\nconst gchar *sipe_get_no_sip_uri(const gchar *sip_uri)\n{\n#define SIP_PREFIX \"sip:\"\n\n\tif (!sip_uri) return NULL;\n\n\tif (g_str_has_prefix(sip_uri, SIP_PREFIX)) {\n\t\treturn(sip_uri + strlen(SIP_PREFIX));\n\t} else {\n\t\treturn sip_uri;\n\t}\n}\n\ngchar *get_uuid(struct sipe_core_private *sipe_private)\n{\n\treturn(generateUUIDfromEPID(sip_transport_epid(sipe_private)));\n}\n\n\nguint\nsipe_get_pub_instance(struct sipe_core_private *sipe_private,\n\t\t      int publication_key)\n{\n\tunsigned res = 0;\n\n\tsscanf(sip_transport_epid(sipe_private), \"%08x\", &res);\n\n\tif (publication_key == SIPE_PUB_DEVICE) {\n\t\t/* as is */\n\t} else if (publication_key == SIPE_PUB_STATE_MACHINE) {\t\t/* First hexadecimal digit is 0x3 */\n\t\tres = (res >> 4) | 0x30000000;\n\t} else if (publication_key == SIPE_PUB_STATE_USER) {\n\t\tres = 0x20000000; /* fixed */\n\t} else if (publication_key == SIPE_PUB_STATE_CALENDAR) {\t/* First hexadecimal digit is 0x4 */\n\t\tres = (res >> 4) | 0x40000000;\n\t} else if (publication_key == SIPE_PUB_STATE_CALENDAR_OOF) {\t/* First hexadecimal digit is 0x5 */\n\t\tres = (res >> 4) | 0x50000000;\n\t} else if (publication_key == SIPE_PUB_CALENDAR_DATA ||\n\t\t   publication_key == SIPE_PUB_NOTE_OOF)\n\t{ /* First hexadecimal digit is 0x4 */\n\t\tunsigned calendar_id = 0;\n\t\tchar *mail_hash = sipe_get_epid(sipe_private->email, \"\", \"\");\n\n\t\tsscanf(mail_hash, \"%08x\", &calendar_id);\n\t\tg_free(mail_hash);\n\t\tres = (calendar_id >> 4) | 0x40000000;\n\t} else if (publication_key == SIPE_PUB_STATE_PHONE_VOIP) {\t/* First hexadecimal digit is 0x8 */\n\t\tres = (res >> 4) | 0x80000000;\n\t}\n\n\treturn res;\n}\n\ngboolean\nsipe_is_bad_alias(const char *uri,\n\t\t  const char *alias)\n{\n\tchar *uri_alias;\n\tgboolean result = FALSE;\n\n\tif (!uri) return FALSE;\n\tif (!alias) return TRUE;\n\n\tif (g_str_has_prefix(alias, \"sip:\") || g_str_has_prefix(alias, \"sips:\")) return TRUE;\n\n\t/* check if alias is just SIP URI but without 'sip:' prefix */\n\turi_alias = sip_uri_from_name(alias);\n\tif (sipe_strcase_equal(uri, uri_alias)) {\n\t\tresult = TRUE;\n\t}\n\tg_free(uri_alias);\n\n\treturn result;\n}\n\ngboolean\nis_empty(const char *st)\n{\n\tif (!st || strlen(st) == 0)\n\t{\n\t\treturn TRUE;\n\t}\n\t/* suspicious leading or trailing spaces */\n\telse if (isspace((unsigned char) *st) ||\n\t\t isspace((unsigned char) *(st + strlen(st) - 1)))\n\t{\n\t\t/* to not modify original string */\n\t\tchar *dup = g_strdup(st);\n\t\tif (strlen(g_strstrip(dup)) == 0) {\n\t\t\tg_free(dup);\n\t\t\treturn TRUE;\n\t\t}\n\t\tg_free(dup);\n\t}\n\treturn FALSE;\n}\n\nvoid sipe_utils_message_debug(struct sipe_transport_connection *conn,\n\t\t\t      const gchar *type,\n\t\t\t      const gchar *header,\n\t\t\t      const gchar *body,\n\t\t\t      gboolean sending)\n{\n\tGString *str       = g_string_new(\"\");\n\tconst char *marker = sending ?\n\t\t\">>>>>>>>>>\" :\n\t\t\"<<<<<<<<<<\";\n\n\tif (sipe_backend_debug_enabled()) {\n\t\t/* unsafe debugging enabled - include message contents */\n\t\tgchar *time_str;\n\t\tgchar *tmp = NULL;\n\n#if GLIB_CHECK_VERSION(2,56,0)\n\t\t// resolution is microseconds\n\t\tGDateTime *datetime = g_date_time_new_now_utc();\n\t\tgint       msecs    = 0;\n\t\tif (datetime) {\n\t\t\ttmp   = g_date_time_format(datetime, \"%FT%T\");\n\t\t\tmsecs = g_date_time_get_microsecond(datetime);\n\t\t\tg_date_time_unref(datetime);\n\t\t}\n\t\ttime_str = g_strdup_printf(\"%s.%06dZ\", tmp ? tmp : \"\", msecs);\n\t\tg_free(tmp);\n#else\n\t\tGTimeVal currtime;\n\t\tg_get_current_time(&currtime);\n\t\ttime_str = g_time_val_to_iso8601(&currtime);\n#endif\n\n\t\tg_string_append_printf(str, \"\\nMESSAGE START %s %s(%p) - %s\\n\", marker, type, conn, time_str);\n\t\tg_string_append(str, tmp = sipe_utils_str_replace(header, \"\\r\\n\", \"\\n\"));\n\t\tg_free(tmp);\n\t\tg_string_append(str, \"\\n\");\n\t\tif (body) {\n\t\t\tg_string_append(str, tmp = sipe_utils_str_replace(body, \"\\r\\n\", \"\\n\"));\n\t\t\tg_free(tmp);\n\t\t\tg_string_append(str, \"\\n\");\n\t\t}\n\t\tg_string_append_printf(str, \"MESSAGE END %s %s(%p) - %s\", marker, type, conn, time_str);\n\t\tg_free(time_str);\n\t} else {\n\t\t/* normal debugging - just show the important stuff */\n\t\tg_string_append_printf(str, \"MESSAGE %s %s(%p)\", marker, type, conn);\n\t}\n\n\tSIPE_DEBUG_INFO_NOFORMAT(str->str);\n\tg_string_free(str, TRUE);\n}\n\ngboolean\nsipe_strequal(const gchar *left, const gchar *right)\n{\n\treturn (g_strcmp0(left, right) == 0);\n}\n\ngboolean\nsipe_strcase_equal(const gchar *left, const gchar *right)\n{\n\treturn ((left == NULL && right == NULL) ||\n\t        (left != NULL && right != NULL && g_ascii_strcasecmp(left, right) == 0));\n}\n\ntime_t\nsipe_utils_str_to_time(const gchar *timestamp)\n{\n#if GLIB_CHECK_VERSION(2,56,0)\n\tGDateTime *datetime = NULL;\n#else\n\tGTimeVal time;\n\tgboolean success = FALSE;\n#endif\n\n\t/* g_time_val_from_iso8601() warns about NULL pointer */\n\tif (timestamp) {\n\t\tguint len;\n\n\t\t/* We have to make sure that the ISO8601 contains a time zone offset,\n\t\t   otherwise the time is interpreted as local time, not UTC!\n\t\t   @TODO: is there a better way to check this? */\n\t\tif (((len = strlen(timestamp)) > 0) &&\n\t\t    isdigit(timestamp[len-1])) {\n\t\t\tgchar *tmp = g_strdup_printf(\"%sZ\", timestamp);\n#if GLIB_CHECK_VERSION(2,56,0)\n\t\t\tdatetime = g_date_time_new_from_iso8601(tmp, NULL);\n#else\n\t\t\tsuccess  = g_time_val_from_iso8601(tmp, &time);\n#endif\n\t\t\tg_free(tmp);\n\t\t} else {\n#if GLIB_CHECK_VERSION(2,56,0)\n\t\t\tdatetime = g_date_time_new_from_iso8601(timestamp, NULL);\n#else\n\t\t\tsuccess  = g_time_val_from_iso8601(timestamp, &time);\n#endif\n\t\t}\n\t}\n\n#if GLIB_CHECK_VERSION(2,56,0)\n\tif (datetime) {\n\t\ttime_t result = g_date_time_to_unix(datetime);\n\t\tg_date_time_unref(datetime);\n\t\treturn(result);\n\t}\n#else\n\tif (success)\n\t\treturn(time.tv_sec);\n#endif\n\n\tSIPE_DEBUG_ERROR(\"sipe_utils_str_to_time: failed to parse ISO8601 string '%s'\",\n\t\t\t timestamp ? timestamp : \"\");\n\treturn(0);\n}\n\ngchar *\nsipe_utils_time_to_str(time_t timestamp)\n{\n\tgchar *result = NULL;\n\n#if GLIB_CHECK_VERSION(2,56,0)\n\tGDateTime *datetime = g_date_time_new_from_unix_utc(timestamp);\n\tif (datetime) {\n                // resolution is seconds\n\t\tresult = g_date_time_format(datetime, \"%FT%TZ\");\n\t\tg_date_time_unref(datetime);\n\t}\n#else\n\tGTimeVal time = { timestamp, 0 };\n\tresult = g_time_val_to_iso8601(&time);\n#endif\n\n\tif (result)\n\t\treturn(result);\n\n\tSIPE_DEBUG_ERROR(\"sipe_utils_time_to_str: failed to convert %lu to ISO8601 string\",\n\t\t\t timestamp);\n\treturn(g_strdup(\"\"));\n}\n\nconst gchar *sipe_utils_time_to_debug_str(const struct tm *tm)\n{\n\tgchar *buffer = asctime(tm);\n\tsize_t length;\n\n\tif (!buffer)\n\t\treturn(\"\");\n\n\t/* asctime() appends \"\\n\" to the resulting string -> strip it */\n\tlength = strlen(buffer);\n\tif (length)\n\t\tbuffer[length - 1] = '\\0';\n\n\treturn(buffer);\n}\n\nsize_t\nhex_str_to_buff(const char *hex_str, guint8 **buff)\n{\n\tchar two_digits[3];\n\tsize_t length;\n\tsize_t i;\n\n\tif (!buff) return 0;\n\tif (!hex_str) return 0;\n\n\tlength = strlen(hex_str)/2;\n\t*buff = (unsigned char *)g_malloc(length);\n\tfor (i = 0; i < length; i++) {\n\t\ttwo_digits[0] = hex_str[i * 2];\n\t\ttwo_digits[1] = hex_str[i * 2 + 1];\n\t\ttwo_digits[2] = '\\0';\n\t\t(*buff)[i] = (unsigned char)strtoul(two_digits, NULL, 16);\n\t}\n\n\treturn length;\n}\n\nchar *\nbuff_to_hex_str(const guint8 *buff, const size_t buff_len)\n{\n\tchar *res;\n\tsize_t i, j;\n\n\tif (!buff) return NULL;\n\n\tres = g_malloc(buff_len * 2 + 1);\n\tfor (i = 0, j = 0; i < buff_len; i++, j+=2) {\n\t\tsprintf(&res[j], \"%02X\", buff[i]);\n\t}\n\tres[j] = '\\0';\n\treturn res;\n}\n\ngboolean\nsipe_utils_parse_lines(GSList **list, gchar **lines, const gchar *delimiter)\n{\n\tint i;\n\tgchar **parts;\n\tgchar *dummy;\n\tgchar *dummy2;\n\tgchar *tmp;\n\n\tfor(i = 0; lines[i] && strlen(lines[i]) > 2; i++) {\n\t\tparts = g_strsplit(lines[i], delimiter, 2);\n\t\tif(!parts[0] || !parts[1]) {\n\t\t\tg_strfreev(parts);\n\t\t\treturn FALSE;\n\t\t}\n\t\tdummy = parts[1];\n\t\tdummy2 = 0;\n\t\twhile(*dummy==' ' || *dummy=='\\t') dummy++;\n\t\tdummy2 = g_strdup(dummy);\n\t\twhile(lines[i+1] && (lines[i+1][0]==' ' || lines[i+1][0]=='\\t')) {\n\t\t\ti++;\n\t\t\tdummy = lines[i];\n\t\t\twhile(*dummy==' ' || *dummy=='\\t') dummy++;\n\t\t\ttmp = g_strdup_printf(\"%s %s\",dummy2, dummy);\n\t\t\tg_free(dummy2);\n\t\t\tdummy2 = tmp;\n\t\t}\n\t\t*list = sipe_utils_nameval_add(*list, parts[0], dummy2);\n\t\tg_free(dummy2);\n\t\tg_strfreev(parts);\n\t}\n\n\treturn TRUE;\n}\n\nGSList*\nsipe_utils_nameval_add(GSList* list, const gchar *name, const gchar *value)\n{\n\tstruct sipnameval *element = g_new0(struct sipnameval,1);\n\n\t/* SANITY CHECK: the calling code must be fixed if this happens! */\n\tif (!value) {\n\t\tSIPE_DEBUG_ERROR(\"sipe_utils_nameval_add: NULL value for %s\",\n\t\t\t\t name);\n\t\tvalue = \"\";\n\t}\n\n\telement->name = g_strdup(name);\n\telement->value = g_strdup(value);\n\treturn g_slist_append(list, element);\n}\n\nvoid\nsipe_utils_nameval_free(GSList *list) {\n\tstruct sipnameval *elem;\n\twhile(list) {\n\t\telem = list->data;\n\t\tlist = g_slist_remove(list,elem);\n\t\tg_free(elem->name);\n\t\tg_free(elem->value);\n\t\tg_free(elem);\n\t}\n}\n\nconst gchar *\nsipe_utils_nameval_find(const GSList *list, const gchar *name)\n{\n\treturn sipe_utils_nameval_find_instance (list, name, 0);\n}\n\nconst gchar *\nsipe_utils_nameval_find_instance(const GSList *list, const gchar *name, int which)\n{\n\tconst GSList *tmp;\n\tstruct sipnameval *elem;\n\tint i = 0;\n\ttmp = list;\n\twhile(tmp) {\n\t\telem = tmp->data;\n\t\t// OCS2005 can send the same header in either all caps or mixed case\n\t\tif (sipe_strcase_equal(elem->name, name)) {\n\t\t\tif (i == which) {\n\t\t\t\treturn elem->value;\n\t\t\t}\n\t\t\ti++;\n\t\t}\n\t\ttmp = g_slist_next(tmp);\n\t}\n\treturn NULL;\n}\n\ngchar *sipe_utils_str_replace(const gchar *string,\n\t\t\t      const gchar *delimiter,\n\t\t\t      const gchar *replacement)\n{\n\tgchar **split;\n\tgchar *result;\n\n\tif (!string || !delimiter || !replacement) return NULL;\n\n\tsplit = g_strsplit(string, delimiter, 0);\n\tresult = g_strjoinv(replacement, split);\n\tg_strfreev(split);\n\n\treturn result;\n}\n\nvoid sipe_utils_shrink_buffer(struct sipe_transport_connection *conn,\n\t\t\t      const gchar *unread)\n{\n\tconn->buffer_used -= unread - conn->buffer;\n\t/* string terminator is not included in buffer_used */\n\tmemmove(conn->buffer, unread, conn->buffer_used + 1);\n}\n\ngboolean sipe_utils_ip_is_private(const char *ip)\n{\n\treturn /* IPv4 */\n\t       g_str_has_prefix(ip, \"10.\")      ||\n\t       g_str_has_prefix(ip, \"172.16.\")  ||\n\t       g_str_has_prefix(ip, \"192.168.\") ||\n\t       /* IPV6 */\n\t       g_str_has_prefix(ip, \"fd\");\n}\n\nconst gchar *sipe_utils_ip_sdp_address_marker(const gchar *ip)\n{\n\treturn(ip && strchr(ip, ':') ? \"IP6\" : \"IP4\");\n}\n\ngchar *sipe_utils_presence_key(const gchar *uri)\n{\n\treturn g_strdup_printf(\"<presence><%s>\", uri);\n}\n\ngchar *\nsipe_utils_uri_unescape(const gchar *string)\n{\n\tgchar *unescaped;\n\tgchar *tmp;\n\n\tif (!string)\n\t\treturn NULL;\n\n\tunescaped = g_uri_unescape_string(string, NULL);\n\tif (unescaped && !g_utf8_validate(unescaped, -1, (const gchar **)&tmp))\n\t\t*tmp = '\\0';\n\n\treturn unescaped;\n}\n\nGSList *sipe_utils_slist_insert_unique_sorted(GSList *list,\n\t\t\t\t\t      gpointer data,\n\t\t\t\t\t      GCompareFunc func,\n\t\t\t\t\t      GDestroyNotify destroy)\n{\n\tif (g_slist_find_custom(list, data, func)) {\n\t\t/* duplicate */\n\t\tif (destroy)\n\t\t\t(*destroy)(data);\n\t\treturn(list);\n\t} else {\n\t\t/* unique: list takes ownership of \"data\" */\n\t\treturn(g_slist_insert_sorted(list, data, func));\n\t}\n}\n\nvoid sipe_utils_slist_free_full(GSList *list,\n\t\t\t\tGDestroyNotify free)\n{\n#if GLIB_CHECK_VERSION(2,28,0)\n\tg_slist_free_full(list, free);\n#else\n\tGSList *entry = list;\n\twhile (entry) {\n\t\t(*free)(entry->data);\n\t\tentry = entry->next;\n\t}\n\tg_slist_free(list);\n#endif\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-utils.h",
    "content": "/**\n * @file sipe-utils.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2009-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/*\n * Interface dependencies:\n *\n * <time.h>\n * <glib.h>\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\nstruct sipe_transport_connection;\n\n/* Our publication type keys. OCS 2007+\n * Format: SIPE_PUB_{Category}[_{SubSategory}]\n */\n/**\n * device\n * -\n *\n * -\n * Unique to the device.\n */\n#define SIPE_PUB_DEVICE\t\t0\n/**\n * state\n * Machine state\n *\n * Availability, activity, end-point location, time zone, and device type.\n * First hexadecimal digit is 0x3; remaining seven hexadecimal digits are unique per device.\n */\n#define SIPE_PUB_STATE_MACHINE\t3\n/**\n * state\n * User state\n *\n * Availability and activity.\n * 0x20000000\n */\n#define SIPE_PUB_STATE_USER\t2\n/**\n * state\n * Calendar state\n *\n * Availability, activity, meeting subject, and meeting location.\n * First hexadecimal digit is 0x4; remaining seven hexadecimal digits are unique per device.\n */\n#define SIPE_PUB_STATE_CALENDAR\t4\n/**\n * state\n * Calendar state for an Out of Office meeting\n *\n * (??)Activity for when a user sets or removes an Out of Office message in Exchange.\n * (+)user sets in Outlook for an Out of Office meeting\n * First hexadecimal digit is 0x5; remaining seven hexadecimal digits are unique per device.\n */\n#define SIPE_PUB_STATE_CALENDAR_OOF\t5\n/**\n * state\n * RCC Phone State\n *\n * Availability and activity for RCC call connect/disconnect or participant count changes from 0 to 2, 2 to N, N to 2, 2 to 0.\n * First hexadecimal digit is 0x7; remaining seven hexadecimal digits are unique per device.\n */\n#define SIPE_PUB_STATE_PHONE_RCC\t7\n/**\n * state\n * VOIP Phone State\n *\n * Availability and activity for VOIP call connect/disconnect or participant count changes from 0 to 2, 2 to N, N to 2, 2 to 0.\n * First hexadecimal digit is 0x8; remaining seven hexadecimal digits uniquely define the SIP URI and device.\n */\n#define SIPE_PUB_STATE_PHONE_VOIP\t8\n/**\n * calendarData\n * Free/busy data\n *\n * Start time, granularity, and free/busy data.\n * First hexadecimal digit is 0x4; last seven hexadecimal digits uniquely define the calendar.\n */\n#define SIPE_PUB_CALENDAR_DATA\t400\n/**\n * note\n * Out of Office note\n *\n * Out of Office note that a user sets in Outlook using the Out of Office assistant.\n * First hexadecimal digit is 0x4; last seven hexadecimal digits uniquely define the calendar.\n */\n#define SIPE_PUB_NOTE_OOF\t400\n\n/**\n * Returns UUID value.\n *\n * @param sipe_private (in) SIPE core private data\n *\n * @return uuid. Must be g_free()'d.\n */\ngchar *\nget_uuid(struct sipe_core_private *sipe_private);\n\n/**\n * Generate Call ID\n *\n * @return Call ID. Must be g_free()'d.\n */\ngchar *gencallid(void);\n\n/**\n * Generate Tag\n *\n * @return Tag. Must be g_free()'d.\n */\ngchar *gentag(void);\n\n/**\n * Generate conference-id\n * 32 characters long. Value space is restricted to printable ASCII characters\n *\n * Ex.: 8386E6AEAAA41E4AA6627BA76D43B6D1\n *\n * @return conference-id. Must be g_free()'d.\n */\ngchar *genconfid(void);\n\n/**\n * Returns instance value for particular publication type.\n * It should be consistent for the same endpoint\n * but different between distinct endpoints.\n *\n * See defined constants for keys patterned SIPE_PUB_*\n */\nguint\nsipe_get_pub_instance(struct sipe_core_private *sipe_private,\n\t\t      int publication_key);\n\n/**\n * Get contact information from SIPE account\n *\n * @param sipe_private (in) SIPE core private data\n *\n * @return Contact. Must be g_free()'d.\n */\ngchar *get_contact(const struct sipe_core_private *sipe_private);\n\n/**\n * Parses URI from SIP header\n *\n * @param hdr (in) To/From header\n *\n * @return URI with sip: prefix. Must be g_free()'d.\n */\ngchar *parse_from(const gchar *hdr);\n\n/**\n * Create sip: URI from name\n *\n * @param name (in)\n *\n * @return URI with sip: prefix. Must be g_free()'d.\n */\ngchar *sip_uri_from_name(const gchar *name);\n\n/**\n * Create sip: URI from SIP account user name\n *\n * @param sipe_private (in) SIPE core private data\n *\n * @return URI with sip: prefix. Must be g_free()'d.\n */\n#define sip_uri_self(sipe_private) (sip_uri_from_name(sipe_private->username))\n\n/**\n * Create sip: URI from name or sip: URI\n *\n * @param string (in) name or sip: URI\n *\n * @return URI with sip: prefix. Must be g_free()'d.\n */\ngchar *sip_uri(const gchar *string);\n\n/**\n * Create sip: URI from name or sip: URI. Checks for invalid characters\n *\n * @param string (in) name or sip: URI\n *\n * @return URI with sip: prefix. Returns NULL if @c string contains invalid\n *         characters. Must be g_free()'d.\n */\ngchar *sip_uri_if_valid(const gchar *string);\n\n/**\n * Returns pointer to URI without sip: prefix if any (doesn't allocate memory)\n *\n * @param sip_uri SIP URI possibly with sip: prefix. Example: sip:first.last@hq.company.com\n *\n * @return pointer to URL without sip: prefix. Coresponding example: first.last@hq.company.com\n */\nconst gchar *sipe_get_no_sip_uri(const gchar *sip_uri);\n\n/**\n * Tries to figure out if contact alias which stored locally\n * is just SIP URI, not a proper display name or local alias.\n *\n * @param uri SIP URI with 'sip:' prefix.\n * @param alias as returned by purple.\n */\ngboolean\nsipe_is_bad_alias(const char *uri,\n\t\t  const char *alias);\n\n/**\n * Checks if provided string is empty - NULL, zero size or just series of white spaces.\n * Doesn't modify input string.\n */\ngboolean\nis_empty(const char *st);\n\n/**\n * Message debugging\n *\n * @param transport the transport connection\n * @param type      message type description (SIP or HTTP).\n * @param header    message header\n * @param body      message body or NULL\n * @param sending   TRUE if outgoing message\n */\nvoid sipe_utils_message_debug(struct sipe_transport_connection *conn,\n\t\t\t      const gchar *type,\n\t\t\t      const gchar *header,\n\t\t\t      const gchar *body,\n\t\t\t      gboolean sending);\n\n/**\n * Tests two strings for equality.\n *\n * Unlike strcmp(), this function will not crash if one or both of the\n * strings are @c NULL.\n *\n * Same as purple_strequal (defined only for 2.6) to maintain\n * our backward compatibility.\n *\n * @param left\tA string\n * @param right A string to compare with left\n *\n * @return @c TRUE if the strings are the same, else @c FALSE.\n *\n */\ngboolean sipe_strequal(const gchar *left, const gchar *right);\n\n/**\n * Tests two strings for equality, ignoring the case\n *\n * Same as glib @c g_ascii_strcasecmp() but works correctly for @c NULL\n * pointers too. Plus it doesn't complain loudly about them...\n *\n * @param left\tA string\n * @param right A string to compare with left\n *\n * @return @c TRUE if the strings are the same, else @c FALSE.\n *\n */\ngboolean sipe_strcase_equal(const gchar *left, const gchar *right);\n\n/**\n * Parses a timestamp in ISO8601 format and returns a time_t.\n * Assumes UTC if no timezone specified\n *\n * @param timestamp The timestamp (may be @c NULL)\n *\n * @return time_t or 0 if timestamp parsing failed\n */\ntime_t\nsipe_utils_str_to_time(const gchar *timestamp);\n\n/**\n * Converts time_t to ISO8601 string.\n * Timezone is UTC.\n *\n * Must be g_free()'d after use.\n *\n * Example: 2010-02-03T23:59:59Z\n */\ngchar *\nsipe_utils_time_to_str(time_t timestamp);\n\n/**\n * Converts struct tm to human readable string\n *\n * Example: Sat Feb 28 11:07:35 2015\n *\n * @return pointer to static buffer. Will never return @c NULL.\n */\nconst gchar *sipe_utils_time_to_debug_str(const struct tm *tm);\n\nstruct sipnameval {\n\tgchar *name;\n\tgchar *value;\n};\n\n/**\n * Parses string of hex digits to buffer.\n * Allocates memory.\n *\n * @param hex_str (in)\tstring of hex digits to convert.\n * @param buff (out)\tnewly allocated buffer. Must be g_free()'d after use.\n *\n * @return\t\tsize of newly allocated buffer\n */\nsize_t\nhex_str_to_buff(const char *hex_str, guint8 **buff);\n\n/**\n * Composes hex string out of provided buffer.\n * Allocates memory.\n *\n * @param buff\t\tinput buffer\n * @param buff_len\tlength of buffer\n *\n * @result\t\tnewly allocated hex string representing buffer. Must be g_free()'d after use.\n */\nchar *\nbuff_to_hex_str(const guint8 *buff, const size_t buff_len);\n\n/**\n * Creates name-value pairs from given lines and appends them to @c list\n *\n * Lines must be in format 'name [delimiter] value'\n *\n * @param list      a list of @c sipnameval structures\n * @param lines     array of strings in format 'name: value'\n * @param delimiter sequence of characters between name and value\n *\n * @return @c FALSE if any of @c lines has incorrect format, @c TRUE otherwise\n */\ngboolean\nsipe_utils_parse_lines(GSList **list, gchar **lines, const gchar *delimiter);\n\n/**\n * Adds a name-value pair to @c list\n *\n * @param list  a list of @c sipnameval structures\n * @param name  attribute's name\n * @param value value of attribute @c name\n *\n * @return the new start of the GSList\n */\nGSList *\nsipe_utils_nameval_add(GSList *list, const gchar *name, const gchar *value);\n\n/**\n * Finds a value of attribute @c name in @c list\n *\n * @param list a list of @c sipnameval structures\n * @param name attribute to find\n *\n * @return value of @c name or NULL if @c name is not found\n */\nconst gchar *\nsipe_utils_nameval_find(const GSList *list, const gchar *name);\n\n/**\n * Returns @c which occurrence of attribute @c name in @c list\n *\n * @c which is zero based, so 0 means first occurrence of @c name in @c list.\n *\n * @param list  a list of @c sipnameval structures\n * @param name  attribute to find\n * @param which specifies occurrence of @name in @c list\n *\n * @return value of @c name or NULL if @c name is not found\n */\nconst gchar *\nsipe_utils_nameval_find_instance(const GSList *list, const gchar *name, int which);\n\n/**\n * Frees memory allocated by @c list\n *\n * @param list a list of @c sipnameval structures\n */\nvoid\nsipe_utils_nameval_free(GSList *list);\n\n/**\n * Given a string, this replaces one substring with another\n * and returns a newly allocated string.\n *\n * @param string      the string from which to replace stuff.\n * @param delimiter   the substring you want replaced.\n * @param replacement the substring you want as replacement.\n *\n * @return string with the substitution or NULL. Must be g_free()'d after use.\n */\ngchar *sipe_utils_str_replace(const gchar *string,\n\t\t\t      const gchar *delimiter,\n\t\t\t      const gchar *replacement);\n\n/**\n * Remove read characters from transport buffer\n *\n * @param conn   the transport connection\n * @param unread pointer to the first character in the buffer\n */\nvoid sipe_utils_shrink_buffer(struct sipe_transport_connection *conn,\n\t\t\t      const gchar *unread);\n/**\n * Checks whether given IP address belongs to private block as defined in RFC1918\n *\n * @param ip IPv4 address in \"X.X.X.X\" format\n * @return @c TRUE if address is private\n */\ngboolean sipe_utils_ip_is_private(const char *ip);\n\n/**\n * Get SDP address marker for IP address\n *\n * @param ip address\n *\n * @return address marker string for IP address\n */\nconst gchar *sipe_utils_ip_sdp_address_marker(const gchar *ip);\n\n/**\n * Generate presence key\n *\n * @param uri presence URI\n *\n * @return key string. Must be g_free()'d after use.\n */\ngchar *sipe_utils_presence_key(const gchar *uri);\n\n/**\n * Decodes a URI into a plain string.\n *\n * @param string the string to translate.\n *\n * @return the resulting string. Must be g_free()'d after use.\n */\ngchar *sipe_utils_uri_unescape(const gchar *string);\n\n/**\n * Inserts in item in the list only if the value isn't already in that list\n *\n * @param list    a singly linked list\n * @param data    the item to insert. Will not be copied.\n * @param func    function to use to compare the values\n * @param destroy if @c NULL call to destroy @c data if is already on list\n *\n * @return the new list head\n */\nGSList *sipe_utils_slist_insert_unique_sorted(GSList *list,\n\t\t\t\t\t      gpointer data,\n\t\t\t\t\t      GCompareFunc func,\n\t\t\t\t\t      GDestroyNotify destroy);\n\n/**\n * Same as @c g_slist_free_full() which is only defined for >= 2.28\n *\n * @param list a singly linked list\n * @param free function to free list data\n */\nvoid sipe_utils_slist_free_full(GSList *list,\n\t\t\t\tGDestroyNotify free);\n"
  },
  {
    "path": "src/core/sipe-webticket.c",
    "content": "/**\n * @file sipe-webticket.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *\n * Specification references:\n *\n *   - [MS-OCAUTHWS]: http://msdn.microsoft.com/en-us/library/ff595592.aspx\n *   - MS Tech-Ed Europe 2010 \"UNC310: Microsoft Lync 2010 Technology Explained\"\n *     http://ecn.channel9.msdn.com/o9/te/Europe/2010/pptx/unc310.pptx\n */\n\n#include <string.h>\n#include <time.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-core-private.h\"\n#include \"sipe-digest.h\"\n#include \"sipe-svc.h\"\n#include \"sipe-tls.h\"\n#include \"sipe-webticket.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n\nstruct webticket_queued_data {\n\tsipe_webticket_callback *callback;\n\tgpointer callback_data;\n};\n\nstruct webticket_callback_data {\n\tgchar *service_uri;\n\tconst gchar *service_port;\n\tgchar *service_auth_uri;\n\n\tgchar *webticket_negotiate_uri;\n\tgchar *webticket_fedbearer_uri;\n\n\tgboolean tried_fedbearer;\n\tgboolean requires_signing;\n\tenum {\n\t\tTOKEN_STATE_NONE       = 0,\n\t\tTOKEN_STATE_SERVICE,\n\t\tTOKEN_STATE_FEDERATION,\n\t\tTOKEN_STATE_FED_BEARER,\n\t} token_state;\n\n\tstruct sipe_tls_random entropy;\n\n\tsipe_webticket_callback *callback;\n\tgpointer callback_data;\n\n\tstruct sipe_svc_session *session;\n\n\tGSList *queued;\n};\n\nstruct webticket_token {\n\tgchar *auth_uri;\n\tgchar *token;\n\ttime_t expires;\n};\n\nstruct sipe_webticket {\n\tGHashTable *cache;\n\tGHashTable *pending;\n\n\tgchar *webticket_adfs_uri;\n\tgchar *adfs_token;\n\ttime_t adfs_token_expires;\n\n\tgboolean retrieved_realminfo;\n\tgboolean shutting_down;\n};\n\nvoid sipe_webticket_free(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_webticket *webticket = sipe_private->webticket;\n\tif (!webticket)\n\t\treturn;\n\n\t/* Web Ticket stack is shutting down: reject all new requests */\n\twebticket->shutting_down = TRUE;\n\n\tg_free(webticket->webticket_adfs_uri);\n\tg_free(webticket->adfs_token);\n\tif (webticket->pending)\n\t\tg_hash_table_destroy(webticket->pending);\n\tif (webticket->cache)\n\t\tg_hash_table_destroy(webticket->cache);\n\tg_free(webticket);\n\tsipe_private->webticket = NULL;\n}\n\nstatic void free_token(gpointer data)\n{\n\tstruct webticket_token *wt = data;\n\tg_free(wt->auth_uri);\n\tg_free(wt->token);\n\tg_free(wt);\n}\n\nstatic void sipe_webticket_init(struct sipe_core_private *sipe_private)\n{\n\tstruct sipe_webticket *webticket;\n\n\tif (sipe_private->webticket)\n\t\treturn;\n\n\tsipe_private->webticket = webticket = g_new0(struct sipe_webticket, 1);\n\n\twebticket->cache   = g_hash_table_new_full(g_str_hash,\n\t\t\t\t\t\t   g_str_equal,\n\t\t\t\t\t\t   g_free,\n\t\t\t\t\t\t   free_token);\n\twebticket->pending = g_hash_table_new(g_str_hash,\n\t\t\t\t\t      g_str_equal);\n}\n\n/* takes ownership of \"token\" */\nstatic void cache_token(struct sipe_core_private *sipe_private,\n\t\t\tconst gchar *service_uri,\n\t\t\tconst gchar *auth_uri,\n\t\t\tgchar *token,\n\t\t\ttime_t expires)\n{\n\tstruct webticket_token *wt = g_new0(struct webticket_token, 1);\n\twt->auth_uri = g_strdup(auth_uri);\n\twt->token    = token;\n\twt->expires  = expires;\n\tg_hash_table_insert(sipe_private->webticket->cache,\n\t\t\t    g_strdup(service_uri),\n\t\t\t    wt);\n}\n\nstatic const struct webticket_token *cache_hit(struct sipe_core_private *sipe_private,\n\t\t\t\t\t       const gchar *service_uri)\n{\n\tconst struct webticket_token *wt;\n\n\t/* make sure a cached Web Ticket is still valid for 60 seconds */\n\twt = g_hash_table_lookup(sipe_private->webticket->cache,\n\t\t\t\t service_uri);\n\tif (wt && (wt->expires < time(NULL) + 60)) {\n\t\tSIPE_DEBUG_INFO(\"cache_hit: cached token for URI %s has expired\",\n\t\t\t\tservice_uri);\n\t\twt = NULL;\n\t}\n\n\treturn(wt);\n}\n\n/* frees just the main request data, when this is called \"queued\" is cleared */\nstatic void callback_data_free(struct webticket_callback_data *wcd)\n{\n\tif (wcd) {\n\t\tsipe_tls_free_random(&wcd->entropy);\n\t\tg_free(wcd->webticket_negotiate_uri);\n\t\tg_free(wcd->webticket_fedbearer_uri);\n\t\tg_free(wcd->service_auth_uri);\n\t\tg_free(wcd->service_uri);\n\t\tg_free(wcd);\n\t}\n}\n\nstatic void queue_request(struct webticket_callback_data *wcd,\n\t\t\t  sipe_webticket_callback *callback,\n\t\t\t  gpointer callback_data)\n{\n\tstruct webticket_queued_data *wqd = g_new0(struct webticket_queued_data, 1);\n\n\twqd->callback      = callback;\n\twqd->callback_data = callback_data;\n\n\twcd->queued = g_slist_prepend(wcd->queued, wqd);\n}\n\nstatic void callback_execute(struct sipe_core_private *sipe_private,\n\t\t\t     struct webticket_callback_data *wcd,\n\t\t\t     const gchar *auth_uri,\n\t\t\t     const gchar *wsse_security,\n\t\t\t     const gchar *failure_msg)\n{\n\tGSList *entry = wcd->queued;\n\n\t/* complete main request */\n\twcd->callback(sipe_private,\n\t\t      wcd->service_uri,\n\t\t      auth_uri,\n\t\t      wsse_security,\n\t\t      failure_msg,\n\t\t      wcd->callback_data);\n\n\t/* complete queued requests */\n\twhile (entry) {\n\t\tstruct webticket_queued_data *wqd = entry->data;\n\n\t\tSIPE_DEBUG_INFO(\"callback_execute: completing queue request URI %s (Auth URI %s)\",\n\t\t\t\twcd->service_uri, auth_uri);\n\t\twqd->callback(sipe_private,\n\t\t\t      wcd->service_uri,\n\t\t\t      auth_uri,\n\t\t\t      wsse_security,\n\t\t\t      failure_msg,\n\t\t\t      wqd->callback_data);\n\n\t\tg_free(wqd);\n\t\tentry = entry->next;\n\t}\n\tg_slist_free(wcd->queued);\n\n\t/* drop request from pending hash */\n\tg_hash_table_remove(sipe_private->webticket->pending,\n\t\t\t    wcd->service_uri);\n}\n\nstatic gchar *extract_raw_xml_attribute(const gchar *xml,\n\t\t\t\t\tconst gchar *name)\n{\n\tgchar *attr_start = g_strdup_printf(\"%s=\\\"\", name);\n\tgchar *data       = NULL;\n\tconst gchar *start = strstr(xml, attr_start);\n\n\tif (start) {\n\t\tconst gchar *value = start + strlen(attr_start);\n\t\tconst gchar *end = strchr(value, '\"');\n\t\tif (end) {\n\t\t\tdata = g_strndup(value, end - value);\n\t\t}\n\t}\n\n\tg_free(attr_start);\n\treturn(data);\n}\n\nstatic gchar *generate_timestamp(const gchar *raw)\n{\n\tgchar *lifetime = sipe_xml_extract_raw(raw, \"Lifetime\", FALSE);\n\tgchar *timestamp = NULL;\n\tif (lifetime)\n\t\ttimestamp = g_strdup_printf(\"<wsu:Timestamp xmlns:wsu=\\\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\\\" wsu:Id=\\\"timestamp\\\">%s</wsu:Timestamp>\",\n\t\t\t\t\t    lifetime);\n\tg_free(lifetime);\n\treturn(timestamp);\n}\n\nstatic gchar *generate_keydata(const gchar *raw)\n{\n\treturn(sipe_xml_extract_raw(raw, \"Assertion\", TRUE));\n}\n\nstatic gchar *generate_expires(const gchar *timestamp)\n{\n\treturn(sipe_xml_extract_raw(timestamp, \"Expires\", FALSE));\n}\n\nstatic gchar *generate_fedbearer_wsse(const gchar *raw)\n{\n\tgchar *timestamp = generate_timestamp(raw);\n\tgchar *keydata   = sipe_xml_extract_raw(raw, \"EncryptedData\", TRUE);\n\tgchar *wsse_security = NULL;\n\n\tif (timestamp && keydata) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"generate_fedbearer_wsse: found timestamp & keydata\");\n\t\twsse_security = g_strconcat(timestamp, keydata, NULL);\n\t}\n\n\tg_free(keydata);\n\tg_free(timestamp);\n\treturn(wsse_security);\n}\n\nstatic void generate_federation_wsse(struct sipe_webticket *webticket,\n\t\t\t\t     const gchar *raw)\n{\n\tgchar *timestamp = generate_timestamp(raw);\n\tgchar *keydata   = generate_keydata(raw);\n\n\t/* clear old ADFS token */\n\tg_free(webticket->adfs_token);\n\twebticket->adfs_token = NULL;\n\n\tif (timestamp && keydata) {\n\t\tgchar *expires_string = generate_expires(timestamp);\n\n\t\tif (expires_string) {\n\n\t\t\tSIPE_DEBUG_INFO(\"generate_federation_wsse: found timestamp & keydata, expires %s\",\n\t\t\t\t\texpires_string);\n\n\t\t\t/* cache ADFS token */\n\t\t\twebticket->adfs_token         = g_strconcat(timestamp,\n\t\t\t\t\t\t\t\t    keydata,\n\t\t\t\t\t\t\t\t    NULL);\n\t\t\twebticket->adfs_token_expires = sipe_utils_str_to_time(expires_string);\n\t\t\tg_free(expires_string);\n\t\t}\n\t}\n\n\tg_free(keydata);\n\tg_free(timestamp);\n}\n\nstatic gchar *generate_sha1_proof_wsse(const gchar *raw,\n\t\t\t\t       struct sipe_tls_random *entropy,\n\t\t\t\t       time_t *expires)\n{\n\tgchar *timestamp = generate_timestamp(raw);\n\tgchar *keydata   = generate_keydata(raw);\n\tgchar *wsse_security = NULL;\n\n\tif (timestamp && keydata) {\n\t\tgchar *expires_string = generate_expires(timestamp);\n\n\t\tif (entropy) {\n\t\t\tgchar *assertionID = extract_raw_xml_attribute(keydata,\n\t\t\t\t\t\t\t\t       \"AssertionID\");\n\n\t\t\t/*\n\t\t\t * WS-Trust 1.3\n\t\t\t *\n\t\t\t * http://docs.oasis-open.org/ws-sx/ws-trust/200512/CK/PSHA1:\n\t\t\t *\n\t\t\t * \"The key is computed using P_SHA1() from the TLS sepcification to generate\n\t\t\t *  a bit stream using entropy from both sides. The exact form is:\n\t\t\t *\n\t\t\t *       key = P_SHA1(Entropy_REQ, Entropy_RES)\"\n\t\t\t */\n\t\t\tgchar *entropy_res_base64 = sipe_xml_extract_raw(raw, \"BinarySecret\", FALSE);\n\t\t\tgsize entropy_res_length;\n\t\t\tguchar *entropy_response = g_base64_decode(entropy_res_base64,\n\t\t\t\t\t\t\t\t   &entropy_res_length);\n\t\t\tguchar *key = sipe_tls_p_sha1(entropy->buffer,\n\t\t\t\t\t\t      entropy->length,\n\t\t\t\t\t\t      entropy_response,\n\t\t\t\t\t\t      entropy_res_length,\n\t\t\t\t\t\t      entropy->length);\n\t\t\tg_free(entropy_response);\n\t\t\tg_free(entropy_res_base64);\n\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"generate_sha1_proof_wsse: found timestamp & keydata\");\n\n\t\t\tif (assertionID && key) {\n\t\t\t\t/* same as SIPE_DIGEST_HMAC_SHA1_LENGTH */\n\t\t\t\tguchar digest[SIPE_DIGEST_SHA1_LENGTH];\n\t\t\t\tgchar *base64;\n\t\t\t\tgchar *signed_info;\n\t\t\t\tgchar *canon;\n\n\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"generate_sha1_proof_wsse: found assertionID and successfully computed the key\");\n\n\t\t\t\t/* Digest over reference element (#timestamp -> wsu:Timestamp) */\n\t\t\t\tsipe_digest_sha1((guchar *) timestamp,\n\t\t\t\t\t\t strlen(timestamp),\n\t\t\t\t\t\t digest);\n\t\t\t\tbase64 = g_base64_encode(digest,\n\t\t\t\t\t\t\t SIPE_DIGEST_SHA1_LENGTH);\n\n\t\t\t\t/* XML-Sig: SignedInfo for reference element */\n\t\t\t\tsigned_info = g_strdup_printf(\"<SignedInfo xmlns=\\\"http://www.w3.org/2000/09/xmldsig#\\\">\"\n\t\t\t\t\t\t\t      \"<CanonicalizationMethod Algorithm=\\\"http://www.w3.org/2001/10/xml-exc-c14n#\\\"/>\"\n\t\t\t\t\t\t\t      \"<SignatureMethod Algorithm=\\\"http://www.w3.org/2000/09/xmldsig#hmac-sha1\\\"/>\"\n\t\t\t\t\t\t\t      \"<Reference URI=\\\"#timestamp\\\">\"\n\t\t\t\t\t\t\t      \"<Transforms>\"\n\t\t\t\t\t\t\t      \"<Transform Algorithm=\\\"http://www.w3.org/2001/10/xml-exc-c14n#\\\"/>\"\n\t\t\t\t\t\t\t      \"</Transforms>\"\n\t\t\t\t\t\t\t      \"<DigestMethod Algorithm=\\\"http://www.w3.org/2000/09/xmldsig#sha1\\\"/>\"\n\t\t\t\t\t\t\t      \"<DigestValue>%s</DigestValue>\"\n\t\t\t\t\t\t\t      \"</Reference>\"\n\t\t\t\t\t\t\t      \"</SignedInfo>\",\n\t\t\t\t\t\t\t      base64);\n\t\t\t\tg_free(base64);\n\n\t\t\t\t/* XML-Sig: SignedInfo in canonical form */\n\t\t\t\tcanon = sipe_xml_exc_c14n(signed_info);\n\t\t\t\tg_free(signed_info);\n\n\t\t\t\tif (canon) {\n\t\t\t\t\tgchar *signature;\n\n\t\t\t\t\t/* calculate signature */\n\t\t\t\t\tsipe_digest_hmac_sha1(key, entropy->length,\n\t\t\t\t\t\t\t      (guchar *)canon,\n\t\t\t\t\t\t\t      strlen(canon),\n\t\t\t\t\t\t\t      digest);\n\t\t\t\t\tbase64 = g_base64_encode(digest,\n\t\t\t\t\t\t\t\t SIPE_DIGEST_HMAC_SHA1_LENGTH);\n\n\t\t\t\t\t/* XML-Sig: Signature from SignedInfo + Key */\n\t\t\t\t\tsignature = g_strdup_printf(\"<Signature xmlns=\\\"http://www.w3.org/2000/09/xmldsig#\\\">\"\n\t\t\t\t\t\t\t\t    \" %s\"\n\t\t\t\t\t\t\t\t    \" <SignatureValue>%s</SignatureValue>\"\n\t\t\t\t\t\t\t\t    \" <KeyInfo>\"\n\t\t\t\t\t\t\t\t    \"  <wsse:SecurityTokenReference wsse:TokenType=\\\"http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1\\\">\"\n\t\t\t\t\t\t\t\t    \"   <wsse:KeyIdentifier ValueType=\\\"http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID\\\">%s</wsse:KeyIdentifier>\"\n\t\t\t\t\t\t\t\t    \"  </wsse:SecurityTokenReference>\"\n\t\t\t\t\t\t\t\t    \" </KeyInfo>\"\n\t\t\t\t\t\t\t\t    \"</Signature>\",\n\t\t\t\t\t\t\t\t    canon,\n\t\t\t\t\t\t\t\t    base64,\n\t\t\t\t\t\t\t\t    assertionID);\n\t\t\t\t\tg_free(base64);\n\t\t\t\t\tg_free(canon);\n\n\t\t\t\t\twsse_security = g_strconcat(timestamp,\n\t\t\t\t\t\t\t\t    keydata,\n\t\t\t\t\t\t\t\t    signature,\n\t\t\t\t\t\t\t\t    NULL);\n\t\t\t\t\tg_free(signature);\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tg_free(key);\n\t\t\tg_free(assertionID);\n\t\t} else {\n\t\t\t/* token doesn't require signature */\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"generate_sha1_proof_wsse: found timestamp & keydata, no signing required\");\n\t\t\twsse_security = g_strconcat(timestamp,\n\t\t\t\t\t\t    keydata,\n\t\t\t\t\t\t    NULL);\n\t\t}\n\n\t\t*expires = 0;\n\t\tif (expires_string) {\n\t\t\t*expires = sipe_utils_str_to_time(expires_string);\n\t\t\tg_free(expires_string);\n\t\t}\n\t}\n\n\tg_free(keydata);\n\tg_free(timestamp);\n\treturn(wsse_security);\n}\n\nstatic gboolean federated_authentication(struct sipe_core_private *sipe_private,\n\t\t\t\t\t struct webticket_callback_data *wcd);\nstatic gboolean initiate_fedbearer(struct sipe_core_private *sipe_private,\n\t\t\t\t   struct webticket_callback_data *wcd);\nstatic void webticket_token(struct sipe_core_private *sipe_private,\n\t\t\t    const gchar *uri,\n\t\t\t    const gchar *raw,\n\t\t\t    sipe_xml *soap_body,\n\t\t\t    gpointer callback_data)\n{\n\tstruct webticket_callback_data *wcd = callback_data;\n\tgboolean failed = TRUE;\n\n\tif (soap_body) {\n\t\tswitch (wcd->token_state) {\n\t\tcase TOKEN_STATE_NONE:\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"webticket_token: ILLEGAL STATE - should not happen...\");\n\t\t\tbreak;\n\n\t\tcase TOKEN_STATE_SERVICE: {\n\t\t\t/* WebTicket for Web Service */\n\t\t\ttime_t expires;\n\t\t\tgchar *wsse_security = generate_sha1_proof_wsse(raw,\n\t\t\t\t\t\t\t\t\twcd->requires_signing ? &wcd->entropy : NULL,\n\t\t\t\t\t\t\t\t\t&expires);\n\n\t\t\tif (wsse_security) {\n\t\t\t\t/* cache takes ownership of wsse_security */\n\t\t\t\tcache_token(sipe_private,\n\t\t\t\t\t    wcd->service_uri,\n\t\t\t\t\t    wcd->service_auth_uri,\n\t\t\t\t\t    wsse_security,\n\t\t\t\t\t    expires);\n\t\t\t\tcallback_execute(sipe_private,\n\t\t\t\t\t\t wcd,\n\t\t\t\t\t\t wcd->service_auth_uri,\n\t\t\t\t\t\t wsse_security,\n\t\t\t\t\t\t NULL);\n\t\t\t\tfailed = FALSE;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase TOKEN_STATE_FEDERATION:\n\t\t\t/* WebTicket from ADFS for federated authentication */\n\t\t\tgenerate_federation_wsse(sipe_private->webticket,\n\t\t\t\t\t\t raw);\n\n\t\t\tif (sipe_private->webticket->adfs_token) {\n\n\t\t\t\tSIPE_DEBUG_INFO(\"webticket_token: received valid SOAP message from ADFS %s\",\n\t\t\t\t\t\turi);\n\n\t\t\t\tif (federated_authentication(sipe_private,\n\t\t\t\t\t\t\t     wcd)) {\n\t\t\t\t\t/* callback data passed down the line */\n\t\t\t\t\twcd = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase TOKEN_STATE_FED_BEARER: {\n\t\t\t/* WebTicket for federated authentication */\n\t\t\tgchar *wsse_security = generate_fedbearer_wsse(raw);\n\n\t\t\tif (wsse_security) {\n\n\t\t\t\tSIPE_DEBUG_INFO(\"webticket_token: received valid SOAP message from service %s\",\n\t\t\t\t\t\turi);\n\n\t\t\t\tif (sipe_svc_webticket(sipe_private,\n\t\t\t\t\t\t       wcd->session,\n\t\t\t\t\t\t       wcd->webticket_fedbearer_uri,\n\t\t\t\t\t\t       wsse_security,\n\t\t\t\t\t\t       wcd->service_auth_uri,\n\t\t\t\t\t\t       &wcd->entropy,\n\t\t\t\t\t\t       webticket_token,\n\t\t\t\t\t\t       wcd)) {\n\t\t\t\t\twcd->token_state = TOKEN_STATE_SERVICE;\n\n\t\t\t\t\t/* callback data passed down the line */\n\t\t\t\t\twcd = NULL;\n\t\t\t\t}\n\t\t\t\tg_free(wsse_security);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\t/* end of: switch (wcd->token_state) { */\n\t\t}\n\n\t} else if (uri) {\n\t\t/* Retry with federated authentication? */\n\t\tif (wcd->webticket_fedbearer_uri) {\n\n\t\t\t/* Authentication against ADFS failed? */\n\t\t\tif (wcd->token_state == TOKEN_STATE_FEDERATION) {\n\t\t\t\tstruct sipe_webticket *webticket = sipe_private->webticket;\n\n\t\t\t\tSIPE_LOG_WARNING_NOFORMAT(\"webticket_token: ADFS authentication failed - assuming Multi-Factor Authentication (MFA)\");\n\n\t\t\t\t/* forget ADFS URI */\n\t\t\t\tg_free(webticket->webticket_adfs_uri);\n\t\t\t\twebticket->webticket_adfs_uri = NULL;\n\t\t\t}\n\n\t\t\tif (!wcd->tried_fedbearer) {\n\t\t\t\tSIPE_DEBUG_INFO(\"webticket_token: anonymous authentication to service %s failed, retrying with federated authentication\",\n\t\t\t\t\t\turi);\n\n\t\t\t\tif (initiate_fedbearer(sipe_private, wcd)) {\n\t\t\t\t\t/* callback data passed down the line */\n\t\t\t\t\twcd = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (wcd) {\n\t\tif (failed) {\n\t\t\tgchar *failure_msg = NULL;\n\n\t\t\tif (soap_body) {\n\t\t\t\tfailure_msg = sipe_xml_data(sipe_xml_child(soap_body,\n\t\t\t\t\t\t\t\t\t   \"Body/Fault/Detail/error/internalerror/text\"));\n\t\t\t\t/* XML data can end in &#x000D;&#x000A; */\n\t\t\t\tg_strstrip(failure_msg);\n\t\t\t}\n\n\t\t\tcallback_execute(sipe_private,\n\t\t\t\t\t wcd,\n\t\t\t\t\t uri,\n\t\t\t\t\t NULL,\n\t\t\t\t\t failure_msg);\n\t\t\tg_free(failure_msg);\n\t\t}\n\t\tcallback_data_free(wcd);\n\t}\n}\n\nstatic gboolean federated_authentication(struct sipe_core_private *sipe_private,\n\t\t\t\t\t struct webticket_callback_data *wcd)\n{\n\tgboolean success;\n\n\tif ((success = sipe_svc_webticket_lmc_federated(sipe_private,\n\t\t\t\t\t\t\twcd->session,\n\t\t\t\t\t\t\tsipe_private->webticket->adfs_token,\n\t\t\t\t\t\t\twcd->webticket_fedbearer_uri,\n\t\t\t\t\t\t\twebticket_token,\n\t\t\t\t\t\t\twcd)))\n\t\twcd->token_state = TOKEN_STATE_FED_BEARER;\n\n\t/* If TRUE then callback data has been passed down the line */\n\treturn(success);\n}\n\nstatic gboolean fedbearer_authentication(struct sipe_core_private *sipe_private,\n\t\t\t\t\t struct webticket_callback_data *wcd)\n{\n\tstruct sipe_webticket *webticket = sipe_private->webticket;\n\tgboolean success;\n\n\t/* make sure a cached ADFS token is still valid for 60 seconds */\n\tif (webticket->adfs_token &&\n\t    (webticket->adfs_token_expires >= time(NULL) + 60)) {\n\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"fedbearer_authentication: reusing cached ADFS token\");\n\t\tsuccess = federated_authentication(sipe_private, wcd);\n\n\t} else if (webticket->webticket_adfs_uri) {\n\t\tif ((success = sipe_svc_webticket_adfs(sipe_private,\n\t\t\t\t\t\t       wcd->session,\n\t\t\t\t\t\t       webticket->webticket_adfs_uri,\n\t\t\t\t\t\t       webticket_token,\n\t\t\t\t\t\t       wcd)))\n\t\t\twcd->token_state = TOKEN_STATE_FEDERATION;\n\t} else {\n\t\tif ((success = sipe_svc_webticket_lmc(sipe_private,\n\t\t\t\t\t\t      wcd->session,\n\t\t\t\t\t\t      wcd->webticket_fedbearer_uri,\n\t\t\t\t\t\t      webticket_token,\n\t\t\t\t\t\t      wcd)))\n\t\t\twcd->token_state = TOKEN_STATE_FED_BEARER;\n\t}\n\n\t/* If TRUE then callback data has been passed down the line */\n\treturn(success);\n}\n\nstatic void realminfo(struct sipe_core_private *sipe_private,\n\t\t      const gchar *uri,\n\t\t      SIPE_UNUSED_PARAMETER const gchar *raw,\n\t\t      sipe_xml *realminfo,\n\t\t      gpointer callback_data)\n{\n\tstruct sipe_webticket *webticket = sipe_private->webticket;\n\tstruct webticket_callback_data *wcd = callback_data;\n\n\t/* Only try retrieving of RealmInfo once */\n\twebticket->retrieved_realminfo = TRUE;\n\n\t/*\n\t * We must specifically check for abort, because\n\t * realminfo == NULL is a valid response\n\t */\n\tif (uri) {\n\t\tif (realminfo) {\n\t\t\t/* detect ADFS setup. See also:\n\t\t\t *\n\t\t\t *   http://en.wikipedia.org/wiki/Active_Directory_Federation_Services\n\t\t\t *\n\t\t\t * NOTE: this is based on observed behaviour.\n\t\t\t *       It is unkown if this is documented somewhere...\n\t\t\t */\n\t\t\tSIPE_DEBUG_INFO(\"realminfo: data for user %s retrieved successfully\",\n\t\t\t\t\tsipe_private->username);\n\n\t\t\twebticket->webticket_adfs_uri = sipe_xml_data(sipe_xml_child(realminfo,\n\t\t\t\t\t\t\t\t\t\t     \"STSAuthURL\"));\n\t\t}\n\n\t\tif (webticket->webticket_adfs_uri) {\n\t\t\tSIPE_LOG_INFO_NOFORMAT(\"realminfo: ADFS setup detected\");\n\t\t\tSIPE_DEBUG_INFO(\"realminfo: ADFS URI: %s\",\n\t\t\t\t\twebticket->webticket_adfs_uri);\n\t\t} else\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"realminfo: no RealmInfo found or no ADFS setup detected - try direct login\");\n\n\t\tif (fedbearer_authentication(sipe_private, wcd)) {\n\t\t\t/* callback data passed down the line */\n\t\t\twcd = NULL;\n\t\t}\n\t}\n\n\tif (wcd) {\n\t\tcallback_execute(sipe_private,\n\t\t\t\t wcd,\n\t\t\t\t uri,\n\t\t\t\t NULL,\n\t\t\t\t NULL);\n\t\tcallback_data_free(wcd);\n\t}\n}\n\nstatic gboolean initiate_fedbearer(struct sipe_core_private *sipe_private,\n\t\t\t\t   struct webticket_callback_data *wcd)\n{\n\tgboolean success;\n\n\tif (sipe_private->webticket->retrieved_realminfo) {\n\t\t/* skip retrieval and go to authentication */\n\t\twcd->tried_fedbearer = TRUE;\n\t\tsuccess = fedbearer_authentication(sipe_private, wcd);\n\t} else {\n\t\tsuccess = sipe_svc_realminfo(sipe_private,\n\t\t\t\t\t     wcd->session,\n\t\t\t\t\t     realminfo,\n\t\t\t\t\t     wcd);\n\t}\n\n\treturn(success);\n}\n\nstatic void webticket_metadata(struct sipe_core_private *sipe_private,\n\t\t\t       const gchar *uri,\n\t\t\t       SIPE_UNUSED_PARAMETER const gchar *raw,\n\t\t\t       sipe_xml *metadata,\n\t\t\t       gpointer callback_data)\n{\n\tstruct webticket_callback_data *wcd = callback_data;\n\n\tif (metadata) {\n\t\tconst sipe_xml *node;\n\n\t\tSIPE_DEBUG_INFO(\"webticket_metadata: metadata for service %s retrieved successfully\",\n\t\t\t\turi);\n\n\t\t/* Authentication ports accepted by WebTicket Service */\n\t\tfor (node = sipe_xml_child(metadata, \"service/port\");\n\t\t     node;\n\t\t     node = sipe_xml_twin(node)) {\n\t\t\tconst gchar *auth_uri = sipe_xml_attribute(sipe_xml_child(node,\n\t\t\t\t\t\t\t\t\t\t  \"address\"),\n\t\t\t\t\t\t\t\t   \"location\");\n\n\t\t\tif (auth_uri) {\n\t\t\t\tif (sipe_strcase_equal(sipe_xml_attribute(node, \"name\"),\n\t\t\t\t\t\t       \"WebTicketServiceWinNegotiate\")) {\n\t\t\t\t\tSIPE_DEBUG_INFO(\"webticket_metadata: WebTicket Windows Negotiate Auth URI %s\", auth_uri);\n\t\t\t\t\tg_free(wcd->webticket_negotiate_uri);\n\t\t\t\t\twcd->webticket_negotiate_uri = g_strdup(auth_uri);\n\t\t\t\t} else if (sipe_strcase_equal(sipe_xml_attribute(node, \"name\"),\n\t\t\t\t\t\t\t      \"WsFedBearer\")) {\n\t\t\t\t\tSIPE_DEBUG_INFO(\"webticket_metadata: WebTicket FedBearer Auth URI %s\", auth_uri);\n\t\t\t\t\tg_free(wcd->webticket_fedbearer_uri);\n\t\t\t\t\twcd->webticket_fedbearer_uri = g_strdup(auth_uri);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (wcd->webticket_negotiate_uri || wcd->webticket_fedbearer_uri) {\n\t\t\tgboolean success;\n\n\t\t\t/* Entropy: 256 random bits */\n\t\t\tif (!wcd->entropy.buffer)\n\t\t\t\tsipe_tls_fill_random(&wcd->entropy, 256);\n\n\t\t\tif (wcd->webticket_negotiate_uri) {\n\t\t\t\t/* Try Negotiate authentication first */\n\n\t\t\t\tsuccess = sipe_svc_webticket(sipe_private,\n\t\t\t\t\t\t\t     wcd->session,\n\t\t\t\t\t\t\t     wcd->webticket_negotiate_uri,\n\t\t\t\t\t\t\t     NULL,\n\t\t\t\t\t\t\t     wcd->service_auth_uri,\n\t\t\t\t\t\t\t     &wcd->entropy,\n\t\t\t\t\t\t\t     webticket_token,\n\t\t\t\t\t\t\t     wcd);\n\t\t\t\twcd->token_state = TOKEN_STATE_SERVICE;\n\t\t\t} else {\n\t\t\t\tsuccess = initiate_fedbearer(sipe_private,\n\t\t\t\t\t\t\t     wcd);\n\t\t\t}\n\n\t\t\tif (success) {\n\t\t\t\t/* callback data passed down the line */\n\t\t\t\twcd = NULL;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (wcd) {\n\t\tcallback_execute(sipe_private,\n\t\t\t\t wcd,\n\t\t\t\t uri,\n\t\t\t\t NULL,\n\t\t\t\t NULL);\n\t\tcallback_data_free(wcd);\n\t}\n}\n\nstatic void service_metadata(struct sipe_core_private *sipe_private,\n\t\t\t     const gchar *uri,\n\t\t\t     SIPE_UNUSED_PARAMETER const gchar *raw,\n\t\t\t     sipe_xml *metadata,\n\t\t\t     gpointer callback_data)\n{\n\tstruct webticket_callback_data *wcd = callback_data;\n\n\tif (metadata) {\n\t\tconst sipe_xml *node;\n\t\tgchar *policy = g_strdup_printf(\"%s_policy\", wcd->service_port);\n\t\tgchar *ticket_uri = NULL;\n\n\t\tSIPE_DEBUG_INFO(\"service_metadata: metadata for service %s retrieved successfully\",\n\t\t\t\turi);\n\n\t\t/* WebTicket policies accepted by Web Service */\n\t\tfor (node = sipe_xml_child(metadata, \"Policy\");\n\t\t     node;\n\t\t     node = sipe_xml_twin(node)) {\n\t\t\tif (sipe_strcase_equal(sipe_xml_attribute(node, \"Id\"),\n\t\t\t\t\t       policy)) {\n\n\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"service_metadata: WebTicket policy found\");\n\n\t\t\t\tticket_uri = sipe_xml_data(sipe_xml_child(node,\n\t\t\t\t\t\t\t\t\t  \"ExactlyOne/All/EndorsingSupportingTokens/Policy/IssuedToken/Issuer/Address\"));\n\t\t\t\tif (ticket_uri) {\n\t\t\t\t\t/* this token type requires signing */\n\t\t\t\t\twcd->requires_signing = TRUE;\n\t\t\t\t} else {\n\t\t\t\t\t/* try alternative token type */\n\t\t\t\t\tticket_uri = sipe_xml_data(sipe_xml_child(node,\n\t\t\t\t\t\t\t\t\t\t  \"ExactlyOne/All/SignedSupportingTokens/Policy/IssuedToken/Issuer/Address\"));\n\t\t\t\t}\n\t\t\t\tif (ticket_uri) {\n\t\t\t\t\tSIPE_DEBUG_INFO(\"service_metadata: WebTicket URI %s\", ticket_uri);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tg_free(policy);\n\n\t\tif (ticket_uri) {\n\n\t\t\t/* Authentication ports accepted by Web Service */\n\t\t\tfor (node = sipe_xml_child(metadata, \"service/port\");\n\t\t\t     node;\n\t\t\t     node = sipe_xml_twin(node)) {\n\t\t\t\tif (sipe_strcase_equal(sipe_xml_attribute(node, \"name\"),\n\t\t\t\t\t\t       wcd->service_port)) {\n\t\t\t\t\tconst gchar *auth_uri;\n\n\t\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"service_metadata: authentication port found\");\n\n\t\t\t\t\tauth_uri = sipe_xml_attribute(sipe_xml_child(node,\n\t\t\t\t\t\t\t\t\t\t     \"address\"),\n\t\t\t\t\t\t\t\t      \"location\");\n\t\t\t\t\tif (auth_uri) {\n\t\t\t\t\t\tSIPE_DEBUG_INFO(\"service_metadata: Auth URI %s\", auth_uri);\n\n\t\t\t\t\t\tif (sipe_svc_metadata(sipe_private,\n\t\t\t\t\t\t\t\t      wcd->session,\n\t\t\t\t\t\t\t\t      ticket_uri,\n\t\t\t\t\t\t\t\t      webticket_metadata,\n\t\t\t\t\t\t\t\t      wcd)) {\n\t\t\t\t\t\t\t/* Remember for later */\n\t\t\t\t\t\t\twcd->service_auth_uri = g_strdup(auth_uri);\n\n\t\t\t\t\t\t\t/* callback data passed down the line */\n\t\t\t\t\t\t\twcd = NULL;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tg_free(ticket_uri);\n\t\t}\n\t}\n\n\tif (wcd) {\n\t\tcallback_execute(sipe_private,\n\t\t\t\t wcd,\n\t\t\t\t uri,\n\t\t\t\t NULL,\n\t\t\t\t NULL);\n\t\tcallback_data_free(wcd);\n\t}\n}\n\nstatic gboolean webticket_request(struct sipe_core_private *sipe_private,\n\t\t\t\t  struct sipe_svc_session *session,\n\t\t\t\t  const gchar *base_uri,\n\t\t\t\t  const gchar *auth_uri,\n\t\t\t\t  const gchar *port_name,\n\t\t\t\t  sipe_webticket_callback *callback,\n\t\t\t\t  gpointer callback_data)\n{\n\tstruct sipe_webticket *webticket;\n\tgboolean ret = FALSE;\n\n\tsipe_webticket_init(sipe_private);\n\twebticket = sipe_private->webticket;\n\n\tif (webticket->shutting_down) {\n\t\tSIPE_DEBUG_ERROR(\"webticket_request: new Web Ticket request during shutdown: THIS SHOULD NOT HAPPEN! Debugging information:\\n\"\n\t\t\t\t \"Base URI:  %s\\n\"\n\t\t\t\t \"Port Name: %s\\n\",\n\t\t\t\t base_uri,\n\t\t\t\t port_name);\n\n\t} else {\n\t\tconst struct webticket_token *wt = cache_hit(sipe_private, base_uri);\n\n\t\t/* cache hit for this URI? */\n\t\tif (wt) {\n\t\t\tSIPE_DEBUG_INFO(\"webticket_request: using cached token for URI %s (Auth URI %s)\",\n\t\t\t\t\tbase_uri, wt->auth_uri);\n\t\t\tcallback(sipe_private,\n\t\t\t\t base_uri,\n\t\t\t\t wt->auth_uri,\n\t\t\t\t wt->token,\n\t\t\t\t NULL,\n\t\t\t\t callback_data);\n\t\t\tret = TRUE;\n\t\t} else {\n\t\t\tGHashTable *pending = webticket->pending;\n\t\t\tstruct webticket_callback_data *wcd = g_hash_table_lookup(pending,\n\t\t\t\t\t\t\t\t\t\t  base_uri);\n\n\t\t\t/* is there already a pending request for this URI? */\n\t\t\tif (wcd) {\n\t\t\t\tSIPE_DEBUG_INFO(\"webticket_request: pending request found for URI %s - queueing\",\n\t\t\t\t\t\tbase_uri);\n\t\t\t\tqueue_request(wcd, callback, callback_data);\n\t\t\t\tret = TRUE;\n\t\t\t} else {\n\t\t\t\twcd = g_new0(struct webticket_callback_data, 1);\n\n\t\t\t\tret = sipe_svc_metadata(sipe_private,\n\t\t\t\t\t\t\tsession,\n\t\t\t\t\t\t\tbase_uri,\n\t\t\t\t\t\t\tport_name ? service_metadata : webticket_metadata,\n\t\t\t\t\t\t\twcd);\n\n\t\t\t\tif (ret) {\n\t\t\t\t\twcd->service_uri      = g_strdup(base_uri);\n\t\t\t\t\twcd->service_port     = port_name;\n\t\t\t\t\twcd->service_auth_uri = g_strdup(auth_uri);\n\t\t\t\t\twcd->callback         = callback;\n\t\t\t\t\twcd->callback_data    = callback_data;\n\t\t\t\t\twcd->session          = session;\n\t\t\t\t\twcd->token_state      = TOKEN_STATE_NONE;\n\t\t\t\t\tg_hash_table_insert(pending,\n\t\t\t\t\t\t\t    wcd->service_uri, /* borrowed */\n\t\t\t\t\t\t\t    wcd);             /* borrowed */\n\t\t\t\t} else {\n\t\t\t\t\tg_free(wcd);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(ret);\n}\n\ngboolean sipe_webticket_request_with_port(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  struct sipe_svc_session *session,\n\t\t\t\t\t  const gchar *base_uri,\n\t\t\t\t\t  const gchar *port_name,\n\t\t\t\t\t  sipe_webticket_callback *callback,\n\t\t\t\t\t  gpointer callback_data)\n{\n\treturn(webticket_request(sipe_private,\n\t\t\t\t session,\n\t\t\t\t base_uri,\n\t\t\t\t NULL, /* Auth URI is determined via port_name */\n\t\t\t\t port_name,\n\t\t\t\t callback,\n\t\t\t\t callback_data));\n}\n\ngboolean sipe_webticket_request_with_auth(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  struct sipe_svc_session *session,\n\t\t\t\t\t  const gchar *base_uri,\n\t\t\t\t\t  const gchar *auth_uri,\n\t\t\t\t\t  sipe_webticket_callback *callback,\n\t\t\t\t\t  gpointer callback_data)\n{\n\treturn(webticket_request(sipe_private,\n\t\t\t\t session,\n\t\t\t\t base_uri,\n\t\t\t\t auth_uri,\n\t\t\t\t NULL,\n\t\t\t\t callback,\n\t\t\t\t callback_data));\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-webticket.h",
    "content": "/**\n * @file sipe-webticket.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/*\n * Interface dependencies:\n *\n * <glib.h>\n */\n\n/* Forward declarations */\nstruct sipe_core_private;\nstruct sipe_svc_session;\n\n/**\n * Web Ticket callback\n *\n * @param sipe_private  SIPE core private data\n * @param base_uri      Web Service base URI\n * @param auth_uri      Web Service auth. URI    (@c NULL when request aborted)\n * @param wsse_security Web Ticket XML fragment  (@c NULL when request failed)\n * @param failure_msg   Web Ticket error message (may be @c NULL)\n * @param callback_data callback data\n */\ntypedef void (sipe_webticket_callback)(struct sipe_core_private *sipe_private,\n\t\t\t\t       const gchar *base_uri,\n\t\t\t\t       const gchar *auth_uri,\n\t\t\t\t       const gchar *wsse_security,\n\t\t\t\t       const gchar *failure_msg,\n\t\t\t\t       gpointer callback_data);\n\n/**\n * Request a Web Ticket for Web Service URI with port name\n *\n * NOTE: the callback can be called immediately if the Web Ticket is cached.\n *       The callback data must therefore be properly initialized already.\n *\n * @param sipe_private  SIPE core private data\n * @param base_uri      Web Service base URI\n * @param port_name     Web Service authentication port name\n * @param callback      callback function\n * @param callback_data callback data\n * @return              @c TRUE if web ticket fetch was triggered\n */\ngboolean sipe_webticket_request_with_port(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  struct sipe_svc_session *session,\n\t\t\t\t\t  const gchar *base_uri,\n\t\t\t\t\t  const gchar *port_name,\n\t\t\t\t\t  sipe_webticket_callback *callback,\n\t\t\t\t\t  gpointer callback_data);\n\n/**\n * Request a Web Ticket for Web Service URI with Authentication URI\n *\n * NOTE: the callback can be called immediately if the Web Ticket is cached.\n *       The callback data must therefore be properly initialized already.\n *\n * @param sipe_private  SIPE core private data\n * @param base_uri      URI\n * @param auth_uri      Authentication URI\n * @param callback      callback function\n * @param callback_data callback data\n * @return              @c TRUE if web ticket fetch was triggered\n */\ngboolean sipe_webticket_request_with_auth(struct sipe_core_private *sipe_private,\n\t\t\t\t\t  struct sipe_svc_session *session,\n\t\t\t\t\t  const gchar *base_uri,\n\t\t\t\t\t  const gchar *auth_uri,\n\t\t\t\t\t  sipe_webticket_callback *callback,\n\t\t\t\t\t  gpointer callback_data);\n\n/**\n * Free webticket data\n *\n * @param sipe_private SIPE core private data\n */\nvoid sipe_webticket_free(struct sipe_core_private *sipe_private);\n"
  },
  {
    "path": "src/core/sipe-win32dep.c",
    "content": "/**\n * @file sipe-win32dep.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010 pier11 <pier11@operamail.com> (fix for REG_EXPAND_SZ)\n * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* This file is an attempt to fix purple's wpurple_read_reg_string()\n * which doesn't read REG_EXPAND_SZ types from registry, only REG_SZ.\n * The code is identical (v2.6.6) apart from one line.\n *\n * The nead is desperate to read Lotus Notes' notes.ini file location\n * stored in REG_EXPAND_SZ type.\n */\n\n#include \"glib.h\"\n\n#include \"sipe-win32dep.h\"\n#include \"sipe-backend.h\"\n\nstatic HKEY _reg_open_key(HKEY rootkey, const char *subkey, REGSAM access) {\n\tHKEY reg_key = NULL;\n\tLONG rv;\n\n\tif(G_WIN32_HAVE_WIDECHAR_API()) {\n\t\twchar_t *wc_subkey = g_utf8_to_utf16(subkey, -1, NULL,\n\t\t\tNULL, NULL);\n\t\trv = RegOpenKeyExW(rootkey, wc_subkey, 0, access, &reg_key);\n\t\tg_free(wc_subkey);\n\t} else {\n\t\tchar *cp_subkey = g_locale_from_utf8(subkey, -1, NULL,\n\t\t\tNULL, NULL);\n\t\trv = RegOpenKeyExA(rootkey, cp_subkey, 0, access, &reg_key);\n\t\tg_free(cp_subkey);\n\t}\n\n\tif (rv != ERROR_SUCCESS) {\n\t\tchar *errmsg = g_win32_error_message(rv);\n\t\tSIPE_DEBUG_ERROR(\"Could not open reg key '%s' subkey '%s'.\\nMessage: (%ld) %s\\n\",\n\t\t\t\t\t((rootkey == HKEY_LOCAL_MACHINE) ? \"HKLM\" :\n\t\t\t\t\t (rootkey == HKEY_CURRENT_USER) ? \"HKCU\" :\n\t\t\t\t\t  (rootkey == HKEY_CLASSES_ROOT) ? \"HKCR\" : \"???\"),\n\t\t\t\t\tsubkey, rv, errmsg);\n\t\tg_free(errmsg);\n\t}\n\n\treturn reg_key;\n}\n\nstatic gboolean _reg_read(HKEY reg_key, const char *valname, LPDWORD type, LPBYTE data, LPDWORD data_len) {\n\tLONG rv;\n\n\tif(G_WIN32_HAVE_WIDECHAR_API()) {\n\t\twchar_t *wc_valname = NULL;\n\t\tif (valname)\n\t\t\twc_valname = g_utf8_to_utf16(valname, -1, NULL, NULL, NULL);\n\t\trv = RegQueryValueExW(reg_key, wc_valname, 0, type, data, data_len);\n\t\tg_free(wc_valname);\n\t} else {\n\t\tchar *cp_valname = NULL;\n\t\tif(valname)\n\t\t\tcp_valname = g_locale_from_utf8(valname, -1, NULL, NULL, NULL);\n\t\trv = RegQueryValueExA(reg_key, cp_valname, 0, type, data, data_len);\n\t\tg_free(cp_valname);\n\t}\n\n\tif (rv != ERROR_SUCCESS) {\n\t\tchar *errmsg = g_win32_error_message(rv);\n\t\tSIPE_DEBUG_ERROR(\"Could not read from reg key value '%s'.\\nMessage: (%ld) %s\\n\",\n\t\t\t\t\tvalname, rv, errmsg);\n\t\tg_free(errmsg);\n\t}\n\n\treturn (rv == ERROR_SUCCESS);\n}\n\nchar *wpurple_read_reg_expand_string(HKEY rootkey, const char *subkey, const char *valname) {\n\n\tDWORD type;\n\tDWORD nbytes;\n\tHKEY reg_key = _reg_open_key(rootkey, subkey, KEY_QUERY_VALUE);\n\tchar *result = NULL;\n\n\tif(reg_key) {\n\t\tif(_reg_read(reg_key, valname, &type, NULL, &nbytes) && (type == REG_SZ || type == REG_EXPAND_SZ)) {\n\t\t\tLPBYTE data;\n\t\t\tif(G_WIN32_HAVE_WIDECHAR_API())\n\t\t\t\tdata = (LPBYTE) g_new(wchar_t, ((nbytes + 1) / sizeof(wchar_t)) + 1);\n\t\t\telse\n\t\t\t\tdata = (LPBYTE) g_malloc(nbytes + 1);\n\n\t\t\tif(_reg_read(reg_key, valname, &type, data, &nbytes)) {\n\t\t\t\tif(G_WIN32_HAVE_WIDECHAR_API()) {\n\t\t\t\t\twchar_t *wc_temp = (wchar_t*) data;\n\t\t\t\t\twc_temp[nbytes / sizeof(wchar_t)] = '\\0';\n\t\t\t\t\tresult = g_utf16_to_utf8(wc_temp, -1,\n\t\t\t\t\t\tNULL, NULL, NULL);\n\t\t\t\t} else {\n\t\t\t\t\tchar *cp_temp = (char*) data;\n\t\t\t\t\tcp_temp[nbytes] = '\\0';\n\t\t\t\t\tresult = g_locale_to_utf8(cp_temp, -1,\n\t\t\t\t\t\tNULL, NULL, NULL);\n\t\t\t\t}\n\t\t\t}\n\t\t\tg_free(data);\n\t\t}\n\t\tRegCloseKey(reg_key);\n\t}\n\n\treturn result;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-win32dep.h",
    "content": "/**\n * @file sipe-win32dep.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010 pier11 <pier11@operamail.com>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <windows.h>\n\nchar *wpurple_read_reg_expand_string(HKEY rootkey, const char *subkey, const char *valname);\n"
  },
  {
    "path": "src/core/sipe-xml-tests.c",
    "content": "/**\n * @file sipe-xml-tests.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Tests for sipe-xml.c */\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <stdarg.h>\n#include <time.h>\n\n#include <glib.h>\n\n#include \"sip-transport.h\"\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-digest.h\"\n#include \"sipe-xml.h\"\n#include \"sipe-utils.h\"\n#include \"uuid.h\"\n\n/* stub functions for backend API */\nvoid sipe_backend_debug_literal(sipe_debug_level level,\n\t\t\t\tconst gchar *msg)\n{\n\tprintf(\"DEBUG %d: %s\", level, msg);\n}\nvoid sipe_backend_debug(sipe_debug_level level,\n\t\t\tconst gchar *format,\n\t\t\t...)\n{\n\tva_list args;\n\tgchar *msg;\n\tva_start(args, format);\n\tmsg = g_strdup_vprintf(format, args);\n\tva_end(args);\n\n\tsipe_backend_debug_literal(level, msg);\n\tg_free(msg);\n}\ngboolean sipe_backend_debug_enabled(void)\n{\n\treturn TRUE;\n}\n\nvoid sipe_digest_sha1(SIPE_UNUSED_PARAMETER const guchar *data,\n\t\t      SIPE_UNUSED_PARAMETER gsize length,\n\t\t      SIPE_UNUSED_PARAMETER guchar *digest) {}\nconst gchar *sip_transport_epid(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private) { return(NULL); }\nconst gchar *sip_transport_ip_address(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private) { return(NULL); }\nchar *generateUUIDfromEPID(SIPE_UNUSED_PARAMETER const gchar *epid) { return(NULL); }\nchar *sipe_get_epid(SIPE_UNUSED_PARAMETER const char *self_sip_uri,\n\t\t    SIPE_UNUSED_PARAMETER const char *hostname,\n\t\t    SIPE_UNUSED_PARAMETER const char *ip_address) { return(NULL); }\n\n/* test helpers */\nstatic guint succeeded = 0;\nstatic guint failed    = 0;\nstatic const gchar *teststring;\n\nstatic sipe_xml *assert_parse(const gchar *s, gboolean ok)\n{\n\tsipe_xml *xml = sipe_xml_parse(s, s ? strlen(s) : 0);\n\n\tteststring = s ? s : \"(nil)\";\n\n\tif ((ok && xml) || (!ok && !xml)) {\n\t\tsucceeded++;\n\t} else {\n\t\tprintf(\"[%s]\\nXML parse FAILED: %p\\n\",\n\t\t       teststring, xml);\n\t\tfailed++;\n\t}\n\treturn(xml);\n}\n\nstatic void assert_name(const sipe_xml *xml, const gchar *s)\n{\n\tconst gchar *name = sipe_xml_name(xml);\n\n\tif (sipe_strequal(name, s)) {\n\t\tsucceeded++;\n\t} else {\n\t\tprintf(\"[%s]\\nXML name FAILED: '%s' expected: '%s'\\n\",\n\t\t       teststring, name ? name : \"(nil)\", s ? s : \"(nil)\");\n\t\tfailed++;\n\t}\n\n}\n\nstatic const sipe_xml *assert_child(const sipe_xml *xml, const gchar *s, gboolean ok)\n{\n\tconst sipe_xml *child = sipe_xml_child(xml, s);\n\n\tif ((ok && child) || (!ok && !child)) {\n\t\tsucceeded++;\n\t} else {\n\t\tprintf(\"[%s]\\nXML child FAILED: %p '%s'\\n\",\n\t\t       teststring, xml, s ? s : \"(nil)\");\n\t\tfailed++;\n\t}\n\treturn(child);\n}\n\nstatic void assert_data(const sipe_xml *xml, const gchar *s)\n{\n\tgchar *data = sipe_xml_data(xml);\n\n\tif (sipe_strequal(s, data)) {\n\t\tsucceeded++;\n\t} else {\n\t\tprintf(\"[%s]\\nXML data FAILED: '%s' expected: '%s'\\n\",\n\t\t       teststring, data ? data : \"(nil)\", s ? s : \"(nil)\");\n\t\tfailed++;\n\t}\n\tg_free(data);\n}\n\nstatic void assert_attribute(const sipe_xml *xml,\n\t\t\t     const gchar *key, const gchar *value)\n{\n\tconst gchar *attr = sipe_xml_attribute(xml, key);\n\n\tif (sipe_strequal(value, attr)) {\n\t\tsucceeded++;\n\t} else {\n\t\tprintf(\"[%s]\\nXML attr FAILED: '%s': '%s' expected: '%s'\\n\",\n\t\t       teststring, key ? key : \"(nil)\",\n\t\t       attr ? attr : \"(nil)\", value ? value : \"(nil)\");\n\t\tfailed++;\n\t}\n}\n\nstatic void assert_int_attribute(const sipe_xml *xml,\n\t\t\t\t const gchar *key, gint value, gint fallback)\n{\n\tgint attr = sipe_xml_int_attribute(xml, key, fallback);\n\n\tif ((attr == value) || (attr == fallback)) {\n\t\tsucceeded++;\n\t} else {\n\t\tprintf(\"[%s]\\nXML int attr FAILED: '%s': %d expected: %d/%d\\n\",\n\t\t       teststring, key ? key : \"(nil)\",\n\t\t       attr, value, fallback);\n\t\tfailed++;\n\t}\n}\n\nstatic void assert_stringify(const sipe_xml *xml,\n\t\t\t     int expected, ...)\n{\n\tva_list args;\n\tgchar *string = sipe_xml_stringify(xml);\n\n\tva_start(args, expected);\n\twhile (expected-- > 0) {\n\t\tconst gchar *alternative = va_arg(args, const gchar *);\n\t\tif (sipe_strequal(string, alternative)) {\n\t\t\tsucceeded++;\n\t\t\tbreak;\n\t\t} else {\n\t\t\tprintf(\"XML stringify alternative FAILED: '%s' (trying next...)\\n\",\n\t\t\t       alternative ? alternative : \"(nil)\");\n\t\t}\n\t}\n\tva_end(args);\n\n\tif (expected < 0) {\n\t\tprintf(\"[%s]\\nXML stringify all alternatives FAILED: '%s'\\n\",\n\t\t       teststring, string ? string : \"(nil)\");\n\t\tfailed++;\n\t}\n\n\tg_free(string);\n}\n\nstatic void assert_raw(const gchar *raw,\n\t\t       const gchar *tag,\n\t\t       gboolean include_tag,\n\t\t       const char *expected)\n{\n\tgchar *string = sipe_xml_extract_raw(raw, tag, include_tag);\n\tif (expected) {\n\t\tif (string) {\n\t\t\tif (sipe_strequal(string, expected)) {\n\t\t\t\tsucceeded++;\n\t\t\t} else {\n\t\t\t\tprintf(\"[%s]\\nXML raw extract FAILED: '%s' expected: '%s'\\n\",\n\t\t\t\t       raw, string, expected);\n\t\t\t\tfailed++;\n\t\t\t}\n\t\t} else {\n\t\t\tprintf(\"[%s]\\nXML raw extract not found FAILED: '%s' expected: '%s'\\n\",\n\t\t\t       raw, tag, expected);\n\t\t\tfailed++;\n\t\t}\n\t} else {\n\t\tif (string) {\n\t\t\tprintf(\"[%s]\\nXML raw extract no match FAILED: '%s' matched: '%s'\\n\",\n\t\t\t       raw, tag, string);\n\t\t\tfailed++;\n\t\t} else {\n\t\t\tsucceeded++;\n\t\t}\n\t}\n\n\tg_free(string);\n}\n\n\n/* memory leak check */\nstatic gsize allocated = 0;\n\nstatic gpointer test_malloc(gsize n_bytes)\n{\n\tgsize *m = malloc(sizeof(gsize) + n_bytes);\n\tif (!m) return(NULL);\n\tallocated += n_bytes;\n\tm[0] = n_bytes;\n\treturn(m + 1);\n}\n\nstatic void test_free(gpointer mem)\n{\n\tgsize *m = mem;\n\tif (!m) return;\n\tm--;\n\tallocated -= m[0];\n\tfree(m);\n}\n\nstatic gpointer test_realloc(gpointer mem, gsize n_bytes)\n{\n\tguint8 *n = NULL;\n\tif (n_bytes) {\n\t\tn = test_malloc(n_bytes);\n\t\tif (mem && n) {\n\t\t\tmemcpy(n, mem, n_bytes);\n\t\t}\n\t}\n\ttest_free(mem);\n\treturn(n);\n}\n\nstatic GMemVTable memory_leak_check = {\n\t&test_malloc,\n\t&test_realloc,\n\t&test_free,\n\tNULL,\n\tNULL,\n\tNULL,\n};\n\nint main(SIPE_UNUSED_PARAMETER int argc, SIPE_UNUSED_PARAMETER char **argv)\n{\n\tsipe_xml *xml;\n\tconst sipe_xml *child1, *child2;\n\n#if 0\n\t/*\n\t * No idea why the memory leak checks work on some platforms\n\t * but fail on others :-( Disable for now...\n\t */\n\tg_mem_set_vtable(&memory_leak_check);\n#else\n\t(void) memory_leak_check;\n#endif\n\n\t/* empty XML */\n\txml = assert_parse(NULL, FALSE);\n\tassert_stringify(xml, 1, NULL);\n\tsipe_xml_free(xml);\n\txml = assert_parse(\"\",   FALSE);\n\tsipe_xml_free(xml);\n\txml = assert_parse(\"<?xml version=\\\"1.0\\\" ?>\", FALSE);\n\tsipe_xml_free(xml);\n\n\t/* one node */\n\txml = assert_parse(\"<test></test>\", TRUE);\n\tassert_name(xml, \"test\");\n\tassert_data(xml, NULL);\n\tassert_stringify(xml, 1, \"<test/>\");\n\tsipe_xml_free(xml);\n\txml = assert_parse(\"<test/>\", TRUE);\n\tassert_name(xml, \"test\");\n\tassert_data(xml, NULL);\n\tassert_stringify(xml, 1, teststring);\n\tsipe_xml_free(xml);\n\txml = assert_parse(\"<test>a</test>\", TRUE);\n\tassert_name(xml, \"test\");\n\tassert_data(xml, \"a\");\n\tassert_stringify(xml, 1, teststring);\n\tsipe_xml_free(xml);\n\txml = assert_parse(\"<test>a\\nb</test>\", TRUE);\n\tassert_name(xml, \"test\");\n\tassert_data(xml, \"a\\nb\");\n\tassert_stringify(xml, 1, teststring);\n\tsipe_xml_free(xml);\n\n\t/* child node */\n\txml = assert_parse(\"<test>a<child>b</child></test>\", TRUE);\n\tassert_name(xml, \"test\");\n\tassert_data(xml, \"a\");\n\tchild1 = assert_child(xml, NULL, FALSE);\n\tchild1 = assert_child(xml, \"child\", TRUE);\n\tassert_name(child1, \"child\");\n\tassert_data(child1, \"b\");\n\tchild1 = assert_child(xml, \"shouldnotmatch\", FALSE);\n\tassert_data(child1, NULL);\n\tassert_stringify(xml, 1, teststring);\n\tsipe_xml_free(xml);\n\n\txml = assert_parse(\"<test>a<child/></test>\", TRUE);\n\tassert_name(xml, \"test\");\n\tassert_data(xml, \"a\");\n\tchild1 = assert_child(xml, \"child\", TRUE);\n\tassert_name(child1, \"child\");\n\tassert_data(child1, NULL);\n\tchild1 = assert_child(xml, \"shouldnotmatch\", FALSE);\n\tassert_data(child1, NULL);\n\tassert_stringify(xml, 1, teststring);\n\tsipe_xml_free(xml);\n\n\txml = assert_parse(\"<test>a<child>b<inner>c</inner></child></test>\", TRUE);\n\tassert_name(xml, \"test\");\n\tassert_data(xml, \"a\");\n\tchild1 = assert_child(xml, \"child\", TRUE);\n\tassert_name(child1, \"child\");\n\tassert_data(child1, \"b\");\n\tchild1 = assert_child(child1, \"inner\", TRUE);\n\tassert_name(child1, \"inner\");\n\tassert_data(child1, \"c\");\n\tchild1 = assert_child(xml, \"child/inner\", TRUE);\n\tassert_name(child1, \"inner\");\n\tassert_data(child1, \"c\");\n\tassert_stringify(xml, 1, teststring);\n\tsipe_xml_free(xml);\n\n\txml = assert_parse(\"<test>a<child>b<inner>c<innerinner>d</innerinner></inner></child></test>\", TRUE);\n\tassert_name(xml, \"test\");\n\tassert_data(xml, \"a\");\n\tchild1 = assert_child(xml, \"child\", TRUE);\n\tassert_name(child1, \"child\");\n\tassert_data(child1, \"b\");\n\tchild2 = assert_child(child1, \"inner/innerinner\", TRUE);\n\tassert_name(child2, \"innerinner\");\n\tassert_data(child2, \"d\");\n\tchild1 = assert_child(child1, \"inner\", TRUE);\n\tassert_name(child1, \"inner\");\n\tassert_data(child1, \"c\");\n\tchild1 = assert_child(child1, \"innerinner\", TRUE);\n\tassert_name(child1, \"innerinner\");\n\tassert_data(child1, \"d\");\n\tchild1 = assert_child(xml, \"child/inner\", TRUE);\n\tassert_name(child1, \"inner\");\n\tassert_data(child1, \"c\");\n\tchild1 = assert_child(xml, \"child/inner/innerinner\", TRUE);\n\tassert_name(child1, \"innerinner\");\n\tassert_data(child1, \"d\");\n\tassert_stringify(xml, 1, teststring);\n\tsipe_xml_free(xml);\n\n\t/* attributes */\n\txml = assert_parse(\"<test a=\\\"\\\">a</test>\", TRUE);\n\tassert_name(xml, \"test\");\n\tassert_data(xml, \"a\");\n\tassert_attribute(xml, NULL, NULL);\n\tassert_attribute(xml, \"a\", \"\");\n\tassert_attribute(xml, \"b\", NULL);\n\tassert_stringify(xml, 1, teststring);\n\tsipe_xml_free(xml);\n\n\txml = assert_parse(\"<test a=\\\"1\\\" b=\\\"abc\\\">a</test>\", TRUE);\n\tassert_name(xml, \"test\");\n\tassert_data(xml, \"a\");\n\tassert_attribute(xml, \"a\", \"1\");\n\tassert_int_attribute(xml, \"a\", 1, 0);\n\tassert_attribute(xml, \"b\", \"abc\");\n\tassert_attribute(xml, \"c\", NULL);\n\tassert_int_attribute(xml, \"d\", 100, 200);\n\t/* the attribute order depends on glib hashing :-( */\n\tassert_stringify(xml, 2, teststring, \"<test b=\\\"abc\\\" a=\\\"1\\\">a</test>\");\n\tsipe_xml_free(xml);\n\n\t/* attributes with namespace */\n\txml = assert_parse(\"<m:row m:uri=\\\"sip:\\\" m:displayName=\\\"X\\\" m:title=\\\"Y\\\" m:office=\\\"Z\\\" m:phone=\\\"0\\\" m:company=\\\"A\\\" m:city=\\\"B\\\" m:state=\\\"C\\\" m:country=\\\"D\\\" m:email=\\\"E\\\" />\", TRUE);\n\tassert_name(xml, \"row\");\n\tassert_data(xml, NULL);\n\tassert_attribute(xml, \"uri\", \"sip:\");\n\tassert_attribute(xml, \"displayName\", \"X\");\n\tassert_attribute(xml, \"title\", \"Y\");\n\tassert_attribute(xml, \"office\", \"Z\");\n\tassert_attribute(xml, \"phone\", \"0\");\n\tassert_attribute(xml, \"company\", \"A\");\n\tassert_attribute(xml, \"city\", \"B\");\n\tassert_attribute(xml, \"state\", \"C\");\n\tassert_attribute(xml, \"country\", \"D\");\n\tassert_attribute(xml, \"email\", \"E\");\n\tsipe_xml_free(xml);\n\n\txml = assert_parse(\"<state xsi:type=\\\"aggregateState\\\" lastActive=\\\"date\\\" xmlns:xsi=\\\"http://one\\\" xmlns=\\\"http://two\\\"><availability>15500</availability></state>\", TRUE);\n\tassert_name(xml, \"state\");\n\tassert_data(xml, NULL);\n\tassert_attribute(xml, \"type\", \"aggregateState\");\n\tassert_attribute(xml, \"lastActive\", \"date\");\n\tassert_attribute(xml, \"xsi\", \"http://one\");\n\tassert_attribute(xml, \"xmlns\", \"http://two\");\n\tchild1 = assert_child(xml, \"availability\", TRUE);\n\tassert_name(child1, \"availability\");\n\tassert_data(child1, \"15500\");\n\tsipe_xml_free(xml);\n\n\t/* broken XML */\n\txml = assert_parse(\"t\", FALSE);\n\tsipe_xml_free(xml);\n\txml = assert_parse(\"<>\", FALSE);\n\tsipe_xml_free(xml);\n\txml = assert_parse(\"<></>\", FALSE);\n\tsipe_xml_free(xml);\n\txml = assert_parse(\"<test>\", FALSE);\n\tsipe_xml_free(xml);\n\txml = assert_parse(\"<a a=\\\"1\\\" a=\\\"2\\\"></a>\", FALSE);\n\tsipe_xml_free(xml);\n\n\t/* XML raw extract */\n\tassert_raw(\"<tag>data</tag>\",        \"tag\",     FALSE, \"data\");\n\tassert_raw(\"<tag>data</tag>\",        \"tag\",     TRUE,  \"<tag>data</tag>\");\n\tassert_raw(\"<tag>data</tag>\",        \"tag1\",    FALSE, NULL);\n\tassert_raw(\"<tag>data</tag>\",        \"tag1\",    TRUE,  NULL);\n\tassert_raw(\"<ns:tag>data</ns:tag>\",  \"tag\",     FALSE, \"data\");\n\tassert_raw(\"<ns:tag>data</ns:tag>\",  \"tag\",     TRUE,  \"<ns:tag>data</ns:tag>\");\n\tassert_raw(\"<ns:tag>data</ns:tag>\",  \"tag1\",    FALSE, NULL);\n\tassert_raw(\"<ns:tag>data</ns:tag>\",  \"tag1\",    TRUE,  NULL);\n\tassert_raw(\"<ns:tag>data</ns:tag>\",  \"ns:tag\",  FALSE, \"data\");\n\tassert_raw(\"<ns:tag>data</ns:tag>\",  \"ns:tag\",  TRUE,  \"<ns:tag>data</ns:tag>\");\n\tassert_raw(\"<ns:tag>data</ns:tag>\",  \"ns:tag1\", FALSE, NULL);\n\tassert_raw(\"<ns:tag>data</ns:tag>\",  \"ns:tag1\", TRUE,  NULL);\n\n\tassert_raw(\"<othertag>data</othertag><tag>data</tag>\",                          \"tag\",  FALSE, \"data\");\n\tassert_raw(\"<othertag>data</othertag><tag>data</tag>\",                          \"tag\",  TRUE,  \"<tag>data</tag>\");\n\tassert_raw(\"<othertag>data</othertag><tag>data</tag><othertag>data</othertag>\", \"tag\",  FALSE, \"data\");\n\tassert_raw(\"<othertag>data</othertag><tag>data</tag><othertag>data</othertag>\", \"tag\",  TRUE,  \"<tag>data</tag>\");\n\tassert_raw(\"<othertag>data</othertag><tag>data</tag>\",                          \"tag1\", FALSE, NULL);\n\tassert_raw(\"<othertag>data</othertag><tag>data</tag>\",                          \"tag1\", TRUE,  NULL);\n\tassert_raw(\"<othertag>data</othertag><tag>data</tag><othertag>data</othertag>\", \"tag1\", FALSE, NULL);\n\tassert_raw(\"<othertag>data</othertag><tag>data</tag><othertag>data</othertag>\", \"tag1\", TRUE,  NULL);\n\tassert_raw(\"<othertag>data</othertag><ns:tag>data</ns:tag>\",                          \"tag\",  FALSE, \"data\");\n\tassert_raw(\"<othertag>data</othertag><ns:tag>data</ns:tag>\",                          \"tag\",  TRUE,  \"<ns:tag>data</ns:tag>\");\n\tassert_raw(\"<othertag>data</othertag><ns:tag>data</ns:tag><othertag>data</othertag>\", \"tag\",  FALSE, \"data\");\n\tassert_raw(\"<othertag>data</othertag><ns:tag>data</ns:tag><othertag>data</othertag>\", \"tag\",  TRUE,  \"<ns:tag>data</ns:tag>\");\n\tassert_raw(\"<othertag>data</othertag><ns:tag>data</ns:tag>\",                          \"tag1\", FALSE, NULL);\n\tassert_raw(\"<othertag>data</othertag><ns:tag>data</ns:tag>\",                          \"tag1\", TRUE,  NULL);\n\tassert_raw(\"<othertag>data</othertag><ns:tag>data</ns:tag><othertag>data</othertag>\", \"tag1\", FALSE, NULL);\n\tassert_raw(\"<othertag>data</othertag><ns:tag>data</ns:tag><othertag>data</othertag>\", \"tag1\", TRUE,  NULL);\n\n\t/* broken XML raw extract */\n\tassert_raw(\"tag>data</tag>\",         \"tag\",     FALSE, NULL);\n\tassert_raw(\":tag>data</tag>\",        \"tag\",     FALSE, NULL);\n\tassert_raw(\"<tag>data</tag\",         \"tag\",     FALSE, NULL);\n\tassert_raw(\"<tag>data</tag1>\",       \"tag\",     FALSE, NULL);\n\tassert_raw(\"<ns:tag>data</tag1>\",    \"tag\",     FALSE, NULL);\n\tassert_raw(\"<ns:tag>data</ns:tag1>\", \"tag\",     FALSE, NULL);\n\n\tif (allocated) {\n\t\tprintf(\"MEMORY LEAK: %\" G_GSIZE_FORMAT \" still allocated\\n\", allocated);\n\t\tfailed++;\n\t} else {\n\t\tprintf(\"MEMORY LEAK CHECK OK\\n\");\n\t\tsucceeded++;\n\t}\n\n\tprintf(\"Result: %d PASSED %d FAILED\\n\", succeeded, failed);\n\treturn(failed);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-xml.c",
    "content": "/**\n * @file sipe-xml.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2015 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/*\n * This code is loosely based on libpurple xmlnode.c\n */\n\n#include <stdarg.h>\n#include <string.h>\n#include <time.h>\n\n#include \"libxml/parser.h\"\n#include \"libxml/c14n.h\"\n#include \"libxml/xmlversion.h\"\n\n#include \"glib.h\"\n\n#include \"sipe-backend.h\"\n#include \"sipe-utils.h\"\n#include \"sipe-xml.h\"\n\nstruct _sipe_xml {\n\tgchar *name;\n\tsipe_xml *parent;\n\tsipe_xml *sibling;\n\tsipe_xml *first;\n\tsipe_xml *last;\n\tGString *data;\n\tGHashTable *attributes;\n};\n\nstruct _parser_data {\n\tsipe_xml *root;\n\tsipe_xml *current;\n\tgboolean error;\n};\n\n/* our string equal function is case insensitive -> hash must be too! */\nstatic guint sipe_ascii_strdown_hash(gconstpointer key)\n{\n\tgchar *lc = g_ascii_strdown((const gchar *) key, -1);\n\tguint bucket = g_str_hash(lc);\n\tg_free(lc);\n\n\treturn(bucket);\n}\n\nstatic void callback_start_element(void *user_data, const xmlChar *name, const xmlChar **attrs)\n{\n\tstruct _parser_data *pd = user_data;\n\tconst char *tmp;\n\tsipe_xml *node;\n\n\tif (!name || pd->error) return;\n\n\tnode = g_new0(sipe_xml, 1);\n\n\tif ((tmp = strchr((char *)name, ':')) != NULL) {\n\t\tname = (xmlChar *)tmp + 1;\n\t}\n\tnode->name = g_strdup((gchar *)name);\n\n\tif (!pd->root) {\n\t\tpd->root = node;\n\t} else {\n\t\tsipe_xml *current = pd->current;\n\n\t\tnode->parent = current;\n\t\tif (current->last) {\n\t\t\tcurrent->last->sibling = node;\n\t\t} else {\n\t\t\tcurrent->first = node;\n\t\t}\n\t\tcurrent->last = node;\n\t}\n\n\tif (attrs) {\n\t\tconst xmlChar *key;\n\n\t\tnode->attributes = g_hash_table_new_full(sipe_ascii_strdown_hash,\n\t\t\t\t\t\t\t (GEqualFunc) sipe_strcase_equal,\n\t\t\t\t\t\t\t g_free, g_free);\n\t\twhile ((key = *attrs++) != NULL) {\n\t\t\tif ((tmp = strchr((char *)key, ':')) != NULL) {\n\t\t\t\tkey = (xmlChar *)tmp + 1;\n\t\t\t}\n\t\t\t/* libxml2 decodes all entities except &amp;.\n\t\t\t   &amp; is replaced by the equivalent &#38; */\n\t\t\tg_hash_table_insert(node->attributes,\n\t\t\t\t\t    g_strdup((gchar *) key),\n\t\t\t\t\t    sipe_utils_str_replace((gchar *) *attrs++, \"&#38;\", \"&\"));\n\t\t}\n\t}\n\n\tpd->current = node;\n}\n\nstatic void callback_end_element(void *user_data, const xmlChar *name)\n{\n\tstruct _parser_data *pd = user_data;\n\n\tif (!name || !pd->current || pd->error) return;\n\n\tif (pd->current->parent)\n\t\tpd->current = pd->current->parent;\n}\n\nstatic void callback_characters(void *user_data, const xmlChar *text, int text_len)\n{\n\tstruct _parser_data *pd = user_data;\n\tsipe_xml *node;\n\n\tif (!pd->current || pd->error || !text || !text_len) return;\n\n\tnode = pd->current;\n\tif (node->data)\n\t\tnode->data = g_string_append_len(node->data, (gchar *)text, text_len);\n\telse\n\t\tnode->data = g_string_new_len((gchar *)text, text_len);\n}\n\nstatic void callback_error(void *user_data, const char *msg, ...)\n{\n\tstruct _parser_data *pd = user_data;\n\tgchar *errmsg;\n\tva_list args;\n\n\tpd->error = TRUE;\n\n\tva_start(args, msg);\n\terrmsg = g_strdup_vprintf(msg, args);\n\tva_end(args);\n\n\tSIPE_DEBUG_ERROR(\"error parsing xml string: %s\", errmsg);\n\tg_free(errmsg);\n}\n\nstatic void callback_serror(void *user_data, xmlErrorPtr error)\n{\n\tstruct _parser_data *pd = user_data;\n\n\tif (error && (error->level == XML_ERR_ERROR ||\n\t              error->level == XML_ERR_FATAL)) {\n\t\tpd->error = TRUE;\n\t\tSIPE_DEBUG_ERROR(\"XML parser error: Domain %i, code %i, level %i: %s\",\n\t\t\t\t error->domain, error->code, error->level,\n\t\t\t\t error->message ? error->message : \"(null)\");\n\t} else if (error) {\n\t\tSIPE_DEBUG_WARNING(\"XML parser error: Domain %i, code %i, level %i: %s\",\n\t\t                   error->domain, error->code, error->level,\n\t\t\t\t   error->message ? error->message : \"(null)\");\n\t} else {\n\t\t/* *sigh* macro expects at least two parameters */\n\t\tSIPE_DEBUG_WARNING_NOFORMAT(\"XML parser error\");\n\t}\n}\n\n/* API doesn't accept const data structure */\nstatic xmlSAXHandler parser = {\n\tNULL,                   /* internalSubset */\n\tNULL,                   /* isStandalone */\n\tNULL,                   /* hasInternalSubset */\n\tNULL,                   /* hasExternalSubset */\n\tNULL,                   /* resolveEntity */\n\tNULL,                   /* getEntity */\n\tNULL,                   /* entityDecl */\n\tNULL,                   /* notationDecl */\n\tNULL,                   /* attributeDecl */\n\tNULL,                   /* elementDecl */\n\tNULL,                   /* unparsedEntityDecl */\n\tNULL,                   /* setDocumentLocator */\n\tNULL,                   /* startDocument */\n\tNULL,                   /* endDocument */\n\tcallback_start_element, /* startElement */\n\tcallback_end_element,   /* endElement   */\n\tNULL,                   /* reference */\n\tcallback_characters,    /* characters */\n\tNULL,                   /* ignorableWhitespace */\n\tNULL,                   /* processingInstruction */\n\tNULL,                   /* comment */\n\tNULL,                   /* warning */\n\tcallback_error,         /* error */\n\tNULL,                   /* fatalError */\n\tNULL,                   /* getParameterEntity */\n\tNULL,                   /* cdataBlock */\n\tNULL,                   /* externalSubset */\n\tXML_SAX2_MAGIC,         /* initialized */\n\tNULL,                   /* _private */\n\tNULL,                   /* startElementNs */\n\tNULL,                   /* endElementNs   */\n\tcallback_serror,        /* serror */\n};\n\nsipe_xml *sipe_xml_parse(const gchar *string, gsize length)\n{\n\tsipe_xml *result = NULL;\n\n\tif (string && length) {\n\t\tstruct _parser_data *pd = g_new0(struct _parser_data, 1);\n\n\t\tif (xmlSAXUserParseMemory(&parser, pd, string, length))\n\t\t\tpd->error = TRUE;\n\n\t\tif (pd->error) {\n\t\t\tsipe_xml_free(pd->root);\n\t\t} else {\n\t\t\tresult = pd->root;\n\t\t}\n\n\t\tg_free(pd);\n\t}\n\n\treturn result;\n}\n\nvoid sipe_xml_free(sipe_xml *node)\n{\n\tsipe_xml *child;\n\n\tif (!node) return;\n\n\t/* we don't support partial tree deletion */\n\tif (node->parent != NULL) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_xml_free: partial delete attempt! Expect crash or memory leaks...\");\n\t}\n\n\t/* free children */\n\tchild = node->first;\n\twhile (child) {\n\t\tsipe_xml *tmp = child->sibling;\n\t\tchild->parent = NULL; /* detach from tree, see above */\n\t\tsipe_xml_free(child);\n\t\tchild = tmp;\n\t}\n\n\t/* free node */\n\tg_free(node->name);\n\tif (node->data)       g_string_free(node->data, TRUE);\n\tif (node->attributes) g_hash_table_destroy(node->attributes);\n\tg_free(node);\n}\n\nstatic void sipe_xml_stringify_attribute(gpointer key, gpointer value,\n\t\t\t\t\t gpointer user_data)\n{\n\tg_string_append_printf(user_data, \" %s=\\\"%s\\\"\",\n\t\t\t       (const gchar *) key, (const gchar *) value);\n}\n\nstatic void sipe_xml_stringify_node(GString *s, const sipe_xml *node)\n{\n\tg_string_append_printf(s, \"<%s\", node->name);\n\n\tif (node->attributes) {\n\t\tg_hash_table_foreach(node->attributes,\n\t\t\t\t     (GHFunc) sipe_xml_stringify_attribute,\n\t\t\t\t     s);\n\t}\n\n\tif (node->data || node->first) {\n\t\tconst sipe_xml *child;\n\n\t\tg_string_append_printf(s, \">%s\",\n\t\t\t\t       node->data ? node->data->str : \"\");\n\n\t\tfor (child = node->first; child; child = child->sibling)\n\t\t\tsipe_xml_stringify_node(s, child);\n\n\t\tg_string_append_printf(s, \"</%s>\", node->name);\n\t} else {\n\t\tg_string_append(s, \"/>\");\n\t}\n}\n\ngchar *sipe_xml_stringify(const sipe_xml *node)\n{\n\tGString *s;\n\n\tif (!node) return NULL;\n\n\ts = g_string_new(\"\");\n\tsipe_xml_stringify_node(s, node);\n\treturn g_string_free(s, FALSE);\n}\n\nconst sipe_xml *sipe_xml_child(const sipe_xml *parent, const gchar *name)\n{\n\tgchar **names;\n\tconst sipe_xml *child = NULL;\n\n\tif (!parent || !name) return NULL;\n\n\t/* 0: child name */\n\t/* 1: trailing path (optional) */\n\tnames = g_strsplit(name, \"/\", 2);\n\n\tfor (child = parent->first; child; child = child->sibling) {\n\t\tif (sipe_strequal(names[0], child->name))\n\t\t\tbreak;\n\t}\n\n\t/* recurse into path */\n\tif (child && names[1])\n\t\tchild = sipe_xml_child(child, names[1]);\n\n\tg_strfreev(names);\n\treturn child;\n}\n\nconst sipe_xml *sipe_xml_twin(const sipe_xml *node)\n{\n\tsipe_xml *sibling;\n\n\tif (!node) return NULL;\n\n\tfor (sibling = node->sibling; sibling; sibling = sibling->sibling) {\n\t\tif (sipe_strequal(node->name, sibling->name))\n\t\t\treturn sibling;\n\t}\n\treturn NULL;\n}\n\nconst gchar *sipe_xml_name(const sipe_xml *node)\n{\n\treturn(node ? node->name : NULL);\n}\n\nconst gchar *sipe_xml_attribute(const sipe_xml *node, const gchar *attr)\n{\n\tif (!node || !attr || !node->attributes) return NULL;\n\treturn(g_hash_table_lookup(node->attributes, attr));\n}\n\nguint sipe_xml_int_attribute(const sipe_xml *node, const gchar *attr,\n\t\t\t     guint fallback)\n{\n\tconst gchar *value = sipe_xml_attribute(node, attr);\n\treturn(value ? g_ascii_strtoull(value, NULL, 10) : fallback);\n}\n\ngchar *sipe_xml_data(const sipe_xml *node)\n{\n\tif (!node || !node->data || !node->data->str) return NULL;\n\treturn g_strdup(node->data->str);\n}\n\n/**\n * Set to 1 to enable debugging code and then add this line to your code:\n *\n *      sipe_xml_dump(node, NULL);\n */\n#if 0\nvoid sipe_xml_dump(const sipe_xml *node, const gchar *path)\n{\n\tconst sipe_xml *child;\n\tgchar *new_path;\n\tif (!node) return;\n\tnew_path = g_strdup_printf(\"%s/%s\", path ? path : \"\", node->name);\n\tif (node->attributes) {\n\t\tGList *attrs = g_hash_table_get_keys(node->attributes);\n\t\tGString *buf = g_string_new(\"\");\n\t\tGList *entry = attrs;\n\t\twhile (entry) {\n\t\t\tg_string_append_printf(buf, \"%s \", (gchar *)entry->data);\n\t\t\tentry = entry->next;\n\t\t}\n\t\tSIPE_DEBUG_INFO(\"%s [%s]\", new_path, buf->str);\n\t\tg_string_free(buf, TRUE);\n\t\tg_list_free(attrs);\n\t} else {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(new_path);\n\t}\n\tfor (child = node->first; child; child = child->sibling)\n\t\tsipe_xml_dump(child, new_path);\n\tg_free(new_path);\n}\n#endif\n\n/*\n * Other XML convenience functions not based on libpurple xmlnode.c\n */\n\ngchar *sipe_xml_exc_c14n(const gchar *string)\n{\n\t/* Parse string to XML document */\n\txmlDocPtr doc = xmlReadMemory(string, strlen(string), \"\", NULL, 0);\n\tgchar *canon = NULL;\n\n\tif (doc) {\n\t\txmlChar *buffer;\n\t\tint size;\n\n\t\t/* Apply canonicalization */\n\t\tsize = xmlC14NDocDumpMemory(doc,\n\t\t\t\t\t    NULL,\n#if LIBXML_VERSION > 20703\n\t\t\t\t\t    /* new API: int mode (a xmlC14NMode) */\n\t\t\t\t\t    XML_C14N_EXCLUSIVE_1_0,\n#else\n\t\t\t\t\t    /* old API: int exclusive */\n\t\t\t\t\t    1,\n#endif\n\t\t\t\t\t    NULL,\n\t\t\t\t\t    0,\n\t\t\t\t\t    &buffer);\n\t\txmlFreeDoc(doc);\n\n\t\tif (size >= 0) {\n\t\t\tSIPE_DEBUG_INFO(\"sipe_xml_exc_c14n:\\noriginal:      %s\\ncanonicalized: %s\",\n\t\t\t\t\tstring, buffer);\n\t\t\tcanon = g_strndup((gchar *) buffer, size);\n\t\t\txmlFree(buffer);\n\t\t} else {\n\t\t\tSIPE_DEBUG_ERROR(\"sipe_xml_exc_c14n: failed to canonicalize xml string:\\n%s\",\n\t\t\t\t\t string);\n\t\t}\n\t} else {\n\t\tSIPE_DEBUG_ERROR(\"sipe_xml_exc_c14n: error parsing xml string:\\n%s\",\n\t\t\t\t string);\n\t}\n\n\treturn(canon);\n}\n\nstatic gchar *sipe_xml_extract_exact_raw(const gchar *xml, const gchar *tag,\n\t\t\t\t\t gboolean include_tag)\n{\n\tgchar *tag_start = g_strdup_printf(\"<%s\", tag);\n\tgchar *tag_end = g_strdup_printf(\"</%s>\", tag);\n\tgchar *data = NULL;\n\tconst gchar *start = strstr(xml, tag_start);\n\n\tif (start) {\n\t\tconst gchar *end = strstr(start + strlen(tag_start), tag_end);\n\t\tif (end) {\n\t\t\tif (include_tag) {\n\t\t\t\tdata = g_strndup(start, end + strlen(tag_end) - start);\n\t\t\t} else {\n\t\t\t\tconst gchar *tmp = strchr(start + strlen(tag_start), '>') + 1;\n\t\t\t\tdata = g_strndup(tmp, end - tmp);\n\t\t\t}\n\t\t}\n\t}\n\n\tg_free(tag_end);\n\tg_free(tag_start);\n\treturn data;\n}\n\nstatic gchar *sipe_xml_extract_any_raw(const gchar *xml, const gchar *tag,\n\t\t\t\t       gboolean include_tag)\n{\n\tgchar *tag_start   = g_strdup_printf(\":%s\", tag);\n\tgchar *data        = NULL;\n\tconst gchar *start = strstr(xml, tag_start);\n\n\tif (start) {\n\t\tconst gchar *p = start - 1;\n\n\t\t/* search for beginning of tag */\n\t\twhile ((*p != '<') && (p >= xml)) p--;\n\n\t\t/* namespace identifier found? */\n\t\tif ((p >= xml) && (p != (start - 1))) {\n\t\t\tgchar *ns      = g_strndup(p + 1, start - p);\n\t\t\tgchar *tag_end = g_strdup_printf(\"</%s%s>\",\n\t\t\t\t\t\t\t ns,\n\t\t\t\t\t\t\t tag);\n\t\t\tconst gchar *end = strstr(start + strlen(tag_start),\n\t\t\t\t\t\t  tag_end);\n\t\t\tg_free(ns);\n\n\t\t\tif (end) {\n\t\t\t\tif (include_tag) {\n\t\t\t\t\tdata = g_strndup(p, end + strlen(tag_end) - p);\n\t\t\t\t} else {\n\t\t\t\t\tconst gchar *tmp = strchr(start + strlen(tag_start), '>') + 1;\n\t\t\t\t\tdata = g_strndup(tmp, end - tmp);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tg_free(tag_end);\n\t\t}\n\t}\n\n\tg_free(tag_start);\n\treturn data;\n}\ngchar *sipe_xml_extract_raw(const gchar *xml, const gchar *tag,\n\t\t\t    gboolean include_tag)\n{\n\t/* first try exact match */\n\tgchar *data = sipe_xml_extract_exact_raw(xml, tag, include_tag);\n\n\t/* otherwise match tag in any name space */\n\tif (!data)\n\t\tdata = sipe_xml_extract_any_raw(xml, tag, include_tag);\n\n\treturn(data);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipe-xml.h",
    "content": "/**\n * @file sipe-xml.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-11 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\ntypedef struct _sipe_xml sipe_xml;\n\n/**\n * Parse XML from a string.\n *\n * @param string String with the XML to be parsed.\n * @param length Length of the string.\n *\n * @return Parsed XML information. Must be @c sipe_xml_free()'d.\n */\nsipe_xml *sipe_xml_parse(const gchar *string, gsize length);\n\n/**\n * Free XML information.\n *\n * @param string XML information to be freed.\n */\nvoid sipe_xml_free(sipe_xml *xml);\n\n/**\n * Convert XML information to string.\n *\n * @param xml XML information.\n *\n * @return XML converted to a string. Must be @c g_free()'d.\n */\ngchar *sipe_xml_stringify(const sipe_xml *xml);\n\n/**\n * Gets a child node named name.\n *\n * @param parent The parent node.\n * @param name   relative XPATH of the child (a, a/b, a/b/c, etc.).\n *\n * @return The child or @c NULL. Never try to @c sipe_xml_free() it!\n */\nconst sipe_xml *sipe_xml_child(const sipe_xml *parent, const gchar *name);\n\n/**\n * Gets the next node with the same name as node.\n *\n * @param node The node of a twin to find.\n *\n * @return The twin of node or @c NULL.\n */\nconst sipe_xml *sipe_xml_twin(const sipe_xml *node);\n\n/**\n * Gets the name from the current XML node.\n *\n * @param node The node to get the name from.\n *\n * @return The name of the node\n */\nconst gchar *sipe_xml_name(const sipe_xml *node);\n\n/**\n * Gets an attribute from the current XML node.\n *\n * @param node The node to get an attribute from.\n * @param attr The attribute to get.\n *\n * @return The value of the attribute or @c NULL.\n */\nconst gchar *sipe_xml_attribute(const sipe_xml *node, const gchar *attr);\n\n/**\n * Gets an attribute from the current XML node and convert it to an\n * unsigned integer.\n *\n * @param node     The node to get an attribute from.\n * @param attr     The attribute to get.\n * @param fallback Default value if the attribute doesn't exist.\n *\n * @return Attribute value converted to an integer or the fallback value.\n */\nguint sipe_xml_int_attribute(const sipe_xml *node, const gchar *attr,\n\t\t\t     guint fallback);\n\n/**\n * Gets escaped data from the current XML node.\n *\n * @param node The node to get data from.\n *\n * @return The data from the node or @c NULL. Must be @c g_free()'d.\n */\ngchar *sipe_xml_data(const sipe_xml *node);\n\n/**\n * For debugging while writing XML processing code.\n * NOTE: the code for this function is flagged out by default!\n *\n * @param node The node to start dumping from\n * @param path The path to this node (can be NULL)\n */\nvoid sipe_xml_dump(const sipe_xml *node, const gchar *path);\n\n/* Other XML convenience functions */\n\n/**\n * Apply \"Exclusive XML Canonicalization\" to a XML string\n * See also http://www.w3.org/TR/xml-exc-c14n/\n *\n * @param string String with the XML to be canonicalized.\n *\n * @return canonicalized XML string. Must be @c g_free()'d.\n */\ngchar *sipe_xml_exc_c14n(const gchar *string);\n\n/**\n * Extracts raw data between a pair of XML tags.\n *\n * @param xml XML document\n * @param tag XML tag enclosing the data\n * @param include_tag whether the enclosing tags should be included in the result\n *\n * @return a first substring from the XML document enclosed by @c tag.\n * Must be @c g_free()'d.\n */\ngchar *sipe_xml_extract_raw(const gchar *xml, const gchar *tag,\n\t\t\t    gboolean include_tag);\n"
  },
  {
    "path": "src/core/sipmsg.c",
    "content": "/**\n * @file sipmsg.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2008 Novell, Inc.\n * Copyright (C) 2005 Thomas Butter <butter@uni-mannheim.de>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <time.h>\n\n#include <glib.h>\n\n#include \"sipmsg.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-mime.h\"\n#include \"sipe-rtf.h\"\n#include \"sipe-utils.h\"\n\nstruct sipmsg *sipmsg_parse_msg(const gchar *msg) {\n\tconst char *tmp = strstr(msg, \"\\r\\n\\r\\n\");\n\tchar *line;\n\tstruct sipmsg *smsg;\n\n\tif(!tmp) return NULL;\n\n\tline = g_strndup(msg, tmp - msg);\n\n\tsmsg = sipmsg_parse_header(line);\n\tsmsg->body = g_strdup(tmp + 4);\n\n\tg_free(line);\n\treturn smsg;\n}\n\nstruct sipmsg *sipmsg_parse_header(const gchar *header) {\n\tstruct sipmsg *msg = g_new0(struct sipmsg,1);\n\tgchar **lines = g_strsplit(header,\"\\r\\n\",0);\n\tgchar **parts;\n\tconst gchar *contentlength;\n\tif(!lines[0]) {\n\t\tg_strfreev(lines);\n\t\tg_free(msg);\n\t\treturn NULL;\n\t}\n\tparts = g_strsplit(lines[0], \" \", 3);\n\tif(!parts[0] || !parts[1] || !parts[2]) {\n\t\tg_strfreev(parts);\n\t\tg_strfreev(lines);\n\t\tg_free(msg);\n\t\treturn NULL;\n\t}\n\tif(strstr(parts[0],\"SIP\") || strstr(parts[0],\"HTTP\")) { /* numeric response */\n\t\tmsg->responsestr = g_strdup(parts[2]);\n\t\tmsg->response = strtol(parts[1],NULL,10);\n\t} else { /* request */\n\t\tmsg->method = g_strdup(parts[0]);\n\t\tmsg->target = g_strdup(parts[1]);\n\t\tmsg->response = 0;\n\t}\n\tg_strfreev(parts);\n\tif (sipe_utils_parse_lines(&msg->headers, lines + 1, \":\") == FALSE) {\n\t\tg_strfreev(lines);\n\t\tsipmsg_free(msg);\n\t\treturn NULL;\n\t}\n\tg_strfreev(lines);\n\tcontentlength = sipmsg_find_header(msg, \"Content-Length\");\n\tif (contentlength) {\n\t\tmsg->bodylen = strtol(contentlength,NULL,10);\n\t} else {\n\t\tconst gchar *tmp = sipmsg_find_header(msg, \"Transfer-Encoding\");\n\t\tif (tmp && sipe_strcase_equal(tmp, \"chunked\")) {\n\t\t\tmsg->bodylen = SIPMSG_BODYLEN_CHUNKED;\n\t\t} else {\n\t\t\ttmp = sipmsg_find_content_type_header(msg);\n\t\t\tif (tmp) {\n\t\t\t\t/*\n\t\t\t\t * This is a fatal error situation: the message\n\t\t\t\t * is corrupted and we can't proceed. Set the\n\t\t\t\t * response code to a special value so that the\n\t\t\t\t * caller can abort correctly.\n\t\t\t\t */\n\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipmsg_parse_header: Content-Length header not found. Aborting!\");\n\t\t\t\tmsg->response = SIPMSG_RESPONSE_FATAL_ERROR;\n\t\t\t\treturn(msg);\n\t\t\t} else {\n\t\t\t\tmsg->bodylen = 0;\n\t\t\t}\n\t\t}\n\t}\n\tif(msg->response) {\n\t\tconst gchar *tmp;\n\t\ttmp = sipmsg_find_cseq_header(msg);\n\t\tif(!tmp) {\n\t\t\t/* SHOULD NOT HAPPEN */\n\t\t\tmsg->method = 0;\n\t\t} else {\n\t\t\tparts = g_strsplit(tmp, \" \", 2);\n\t\t\tmsg->method = g_strdup(parts[1]);\n\t\t\tg_strfreev(parts);\n\t\t}\n\t}\n\treturn msg;\n}\n\nstruct sipmsg *sipmsg_copy(const struct sipmsg *other) {\n\tstruct sipmsg *msg = g_new0(struct sipmsg, 1);\n\tGSList *list;\n\n\tmsg->response\t\t= other->response;\n\tmsg->responsestr\t= g_strdup(other->responsestr);\n\tmsg->method\t\t= g_strdup(other->method);\n\tmsg->target\t\t= g_strdup(other->target);\n\n\tlist = other->headers;\n\twhile(list) {\n\t\tstruct sipnameval *elem = list->data;\n\t\tsipmsg_add_header_now(msg, elem->name, elem->value);\n\t\tlist = list->next;\n\t}\n\n\tlist = other->new_headers;\n\twhile(list) {\n\t\tstruct sipnameval *elem = list->data;\n\t\tsipmsg_add_header(msg, elem->name, elem->value);\n\t\tlist = list->next;\n\t}\n\n\tmsg->bodylen\t= other->bodylen;\n\tmsg->body\t= g_strdup(other->body);\n\tmsg->signature\t= g_strdup(other->signature);\n\tmsg->rand\t= g_strdup(other->rand);\n\tmsg->num\t= g_strdup(other->num);\n\n\treturn msg;\n}\n\nchar *sipmsg_to_string(const struct sipmsg *msg) {\n\tGSList *cur;\n\tGString *outstr = g_string_new(\"\");\n\tstruct sipnameval *elem;\n\n\tif(msg->response)\n\t\tg_string_append_printf(outstr, \"SIP/2.0 %d Unknown\\r\\n\",\n\t\t\tmsg->response);\n\telse\n\t\tg_string_append_printf(outstr, \"%s %s SIP/2.0\\r\\n\",\n\t\t\tmsg->method, msg->target);\n\n\tcur = msg->headers;\n\twhile(cur) {\n\t\telem = cur->data;\n                /*Todo: remove the LFCR in a good way*/\n                /*if(sipe_strequal(elem->name,\"Proxy-Authorization\"))\n                  g_string_append_printf(outstr, \"%s: %s\", elem->name,\n\t\t\telem->value);\n                else     */\n\t\t   g_string_append_printf(outstr, \"%s: %s\\r\\n\", elem->name,\n\t\t\telem->value);\n\t\tcur = g_slist_next(cur);\n\t}\n\n\tg_string_append_printf(outstr, \"\\r\\n%s\", msg->bodylen ? msg->body : \"\");\n\n\treturn g_string_free(outstr, FALSE);\n}\n\n/**\n * Adds header to current message headers\n */\nvoid sipmsg_add_header_now(struct sipmsg *msg, const gchar *name, const gchar *value) {\n\tstruct sipnameval *element = g_new0(struct sipnameval,1);\n\n\t/* SANITY CHECK: the calling code must be fixed if this happens! */\n\tif (!value) {\n\t\tSIPE_DEBUG_ERROR(\"sipmsg_add_header_now: NULL value for %s\",\n\t\t\t\t name);\n\t\tvalue = \"\";\n\t}\n\n\telement->name = g_strdup(name);\n\telement->value = g_strdup(value);\n\tmsg->headers = g_slist_append(msg->headers, element);\n}\n\n/**\n * Adds header to separate storage for future merge\n */\nvoid sipmsg_add_header(struct sipmsg *msg, const gchar *name, const gchar *value) {\n\tstruct sipnameval *element = g_new0(struct sipnameval,1);\n\n\t/* SANITY CHECK: the calling code must be fixed if this happens! */\n\tif (!value) {\n\t\tSIPE_DEBUG_ERROR(\"sipmsg_add_header: NULL value for %s\", name);\n\t\tvalue = \"\";\n\t}\n\n\telement->name = g_strdup(name);\n\telement->value = g_strdup(value);\n\tmsg->new_headers = g_slist_append(msg->new_headers, element);\n}\n\n/**\n * Removes header if it's not in keepers array\n */\nvoid sipmsg_strip_headers(struct sipmsg *msg, const gchar *keepers[]) {\n\tGSList *entry;\n\tstruct sipnameval *elem;\n\n\tentry = msg->headers;\n\twhile(entry) {\n\t\tint i = 0;\n\t\tgboolean keeper = FALSE;\n\n\t\telem = entry->data;\n\t\twhile (keepers[i]) {\n\t\t\tif (!g_ascii_strcasecmp(elem->name, keepers[i])) {\n\t\t\t\tkeeper = TRUE;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\ti++;\n\t\t}\n\n\t\tif (!keeper) {\n\t\t\tGSList *to_delete = entry;\n\t\t\tSIPE_DEBUG_INFO(\"sipmsg_strip_headers: removing %s\", elem->name);\n\t\t\tentry = g_slist_next(entry);\n\t\t\tmsg->headers = g_slist_delete_link(msg->headers, to_delete);\n\t\t\tg_free(elem->name);\n\t\t\tg_free(elem->value);\n\t\t\tg_free(elem);\n\t\t} else {\n\t\t\tentry = g_slist_next(entry);\n\t\t}\n\t}\n}\n\n/**\n * Merges newly added headers to message\n */\nvoid sipmsg_merge_new_headers(struct sipmsg *msg) {\n\twhile(msg->new_headers) {\n\t\tmsg->headers = g_slist_append(msg->headers, msg->new_headers->data);\n\t\tmsg->new_headers = g_slist_remove(msg->new_headers, msg->new_headers->data);\n\t}\n}\n\nvoid sipmsg_free(struct sipmsg *msg) {\n\tif (msg) {\n\t\tsipe_utils_nameval_free(msg->headers);\n\t\tsipe_utils_nameval_free(msg->new_headers);\n\t\tg_free(msg->signature);\n\t\tg_free(msg->rand);\n\t\tg_free(msg->num);\n\t\tg_free(msg->responsestr);\n\t\tg_free(msg->method);\n\t\tg_free(msg->target);\n\t\tg_free(msg->body);\n\t\tg_free(msg);\n\t}\n}\n\nvoid sipmsg_remove_header_now(struct sipmsg *msg, const gchar *name) {\n\tstruct sipnameval *elem;\n\tGSList *tmp = msg->headers;\n\twhile(tmp) {\n\t\telem = tmp->data;\n\t\t// OCS2005 can send the same header in either all caps or mixed case\n\t\tif (sipe_strcase_equal(elem->name, name)) {\n\t\t\tmsg->headers = g_slist_remove(msg->headers, elem);\n\t\t\tg_free(elem->name);\n\t\t\tg_free(elem->value);\n\t\t\tg_free(elem);\n\t\t\treturn;\n\t\t}\n\t\ttmp = g_slist_next(tmp);\n\t}\n\treturn;\n}\n\nconst gchar *sipmsg_find_header(const struct sipmsg *msg, const gchar *name) {\n\treturn sipe_utils_nameval_find_instance (msg->headers, name, 0);\n}\n\nconst gchar *sipmsg_find_header_instance(const struct sipmsg *msg, const gchar *name, int which) {\n\treturn sipe_utils_nameval_find_instance(msg->headers, name, which);\n}\n\ngchar *sipmsg_find_part_of_header(const char *hdr, const char * before, const char * after, const char * def) {\n\tconst char *tmp;\n\tconst char *tmp2;\n\tgchar *res2;\n\tif (!hdr) {\n\t\treturn NULL;\n\t}\n\n\t//printf(\"partof %s w/ %s before and %s after\\n\", hdr, before, after);\n\n\ttmp = before == NULL ? hdr : strstr(hdr, before);\n\tif (!tmp) {\n\t\t//printf (\"not found, returning null\\n\");\n\t\treturn (gchar *)def;\n\t}\n\n\tif (before != NULL) {\n\t\ttmp += strlen(before);\n\t\t//printf (\"tmp now %s\\n\", tmp);\n\t}\n\n\tif (after != NULL && (tmp2 = strstr(tmp, after))) {\n\t\tgchar * res = g_strndup(tmp, tmp2 - tmp);\n\t\t//printf(\"returning %s\\n\", res);\n\t\treturn res;\n\t}\n\tres2 = g_strdup(tmp);\n\t//printf(\"returning %s\\n\", res2);\n\treturn res2;\n}\n\nint sipmsg_parse_cseq(struct sipmsg *msg)\n{\n\tint res = -1;\n\tgchar **items;\n\titems = g_strsplit(sipmsg_find_cseq_header(msg), \" \", 1);\n\tif (items[0]) {\n\t\tres = atoi(items[0]);\n\t}\n\tg_strfreev(items);\n\treturn res;\n}\n\n/**\n * Parse EndPoints header from INVITE request\n * Returns a list of end points: contact URI plus optional epid.\n * You must free the values and the list.\n *\n * Example headers:\n * EndPoints: \"alice alisson\" <sip:alice@atlanta.local>, <sip:bob@atlanta.local>;epid=ebca82d94d, <sip:carol@atlanta.local>\n * EndPoints: \"alice, alisson\" <sip:alice@atlanta.local>, <sip:bob@atlanta.local>\n * EndPoints: \"alice alisson\" <sip:alice@atlanta.local>, \"Super, Man\" <sip:super@atlanta.local>\n *\n * @param header (in) EndPoints header contents\n *\n * @return GSList with struct sipendpoint as elements\n */\nGSList *sipmsg_parse_endpoints_header(const gchar *header)\n{\n\tGSList *list = NULL;\n\tgchar **parts = g_strsplit(header, \",\", 0);\n\tgchar *part;\n\tint i;\n\n\tfor (i = 0; (part = parts[i]) != NULL; i++) {\n\t\t/* Does the part contain a URI? */\n\t\tgchar *contact = sipmsg_find_part_of_header(part, \"<\", \">\", NULL);\n\t\tif (contact) {\n\t\t\tstruct sipendpoint *end_point = g_new(struct sipendpoint, 1);\n\t\t\tend_point->contact = contact;\n\t\t\tend_point->epid = sipmsg_find_part_of_header(part, \"epid=\", NULL, NULL);\n\t\t\tlist = g_slist_append(list, end_point);\n\t\t}\n\t}\n\tg_strfreev(parts);\n\n\treturn(list);\n}\n\nvoid sipmsg_parse_p_asserted_identity(const gchar *header, gchar **sip_uri,\n\t\t\t\t      gchar **tel_uri) {\n\tgchar **parts, **p;\n\n\t*sip_uri = NULL;\n\t*tel_uri = NULL;\n\n\tif (g_ascii_strncasecmp(header, \"tel:\", 4) == 0) {\n\t\t*tel_uri = g_strdup(header);\n\t\treturn;\n\t}\n\n\tparts = g_strsplit(header, \",\", 0);\n\n\tfor (p = parts; *p; p++) {\n\t\tgchar *uri = sipmsg_find_part_of_header(*p, \"<\", \">\", NULL);\n\t\tif (!uri)\n\t\t\tcontinue;\n\n\t\tif (g_ascii_strncasecmp(uri, \"sip:\", 4) == 0) {\n\t\t\tif (*sip_uri) {\n\t\t\t\tSIPE_DEBUG_WARNING_NOFORMAT(\"More than one \"\n\t\t\t\t\t\"sip: URI found in P-Asserted-Identity!\");\n\t\t\t} else {\n\t\t\t\t*sip_uri = uri;\n\t\t\t\turi = NULL;\n\t\t\t}\n\t\t} else if (g_ascii_strncasecmp(uri, \"tel:\", 4) == 0){\n\t\t\tif (*tel_uri) {\n\t\t\t\tSIPE_DEBUG_WARNING_NOFORMAT(\"More than one \"\n\t\t\t\t\t\"tel: URI found in P-Asserted-Identity!\");\n\t\t\t} else {\n\t\t\t\t*tel_uri = uri;\n\t\t\t\turi = NULL;\n\t\t\t}\n\t\t}\n\n\t\tg_free(uri);\n\t}\n\n\tg_strfreev(parts);\n}\n\n/*\n *  sipmsg_find_auth_header will return the particular WWW-Authenticate\n *  header specified by *name.\n *\n *  Use this function when you want to look for a specific authentication\n *  method such as NTLM or Kerberos\n */\n\nconst gchar *sipmsg_find_auth_header(struct sipmsg *msg, const gchar *name) {\n\tGSList *tmp;\n\tstruct sipnameval *elem;\n\tint name_len;\n\n\tif (!name) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipmsg_find_auth_header: no authentication scheme specified\");\n\t\treturn NULL;\n\t}\n\n\tname_len = strlen(name);\n\ttmp = msg->headers;\n\twhile(tmp) {\n\t\telem = tmp->data;\n\t\t/* SIPE_DEBUG_INFO(\"Current header: %s\", elem->value); */\n\t\tif (elem && elem->name &&\n\t\t    (sipe_strcase_equal(elem->name,\"WWW-Authenticate\") ||\n\t\t     sipe_strcase_equal(elem->name,\"Authentication-Info\")) ) {\n\t\t\tif (!g_ascii_strncasecmp((gchar *)elem->value, name, name_len)) {\n\t\t\t\t/* SIPE_DEBUG_INFO(\"elem->value: %s\", elem->value); */\n\t\t\t\treturn elem->value;\n\t\t\t}\n\t\t}\n\t\t/* SIPE_DEBUG_INFO_NOFORMAT(\"moving to next header\"); */\n\t\ttmp = g_slist_next(tmp);\n\t}\n\tSIPE_DEBUG_INFO(\"sipmsg_find_auth_header: '%s' not found\", name);\n\treturn NULL;\n}\n\n/**\n * Parses headers-like 'msgr' attribute of INVITE's 'ms_text_format' header.\n * Then retrieves value of 'X-MMS-IM-Format'.\n\n * 'msgr' typically looks like:\n * X-MMS-IM-Format: FN=Microsoft%20Sans%20Serif; EF=BI; CO=800000; CS=0; PF=22\n */\nstatic gchar *sipmsg_get_x_mms_im_format(gchar *msgr) {\n\tgchar *msgr2;\n\tgsize msgr_dec64_len;\n\tguchar *msgr_dec64;\n\tgchar *msgr_utf8;\n\tgchar **lines;\n\tgchar **parts;\n\tgchar *x_mms_im_format;\n\tgchar *tmp;\n\n\tif (!msgr) return NULL;\n\tmsgr2 = g_strdup(msgr);\n\twhile (strlen(msgr2) % 4 != 0) {\n\t\tgchar *tmp_msgr2 = msgr2;\n\t\tmsgr2 = g_strdup_printf(\"%s=\", msgr2);\n\t\tg_free(tmp_msgr2);\n\t}\n\tmsgr_dec64 = g_base64_decode(msgr2, &msgr_dec64_len);\n\tmsgr_utf8 = g_convert((gchar *) msgr_dec64, msgr_dec64_len, \"UTF-8\", \"UTF-16LE\", NULL, NULL, NULL);\n\tg_free(msgr_dec64);\n\tg_free(msgr2);\n\tlines = g_strsplit(msgr_utf8,\"\\r\\n\\r\\n\",0);\n\tg_free(msgr_utf8);\n\t//@TODO: make extraction like parsing of message headers.\n\tparts = g_strsplit(lines[0],\"X-MMS-IM-Format:\",0);\n\tx_mms_im_format = g_strdup(parts[1]);\n\tg_strfreev(parts);\n\tg_strfreev(lines);\n\ttmp = x_mms_im_format;\n\tif (x_mms_im_format) {\n\t\twhile(*x_mms_im_format==' ' || *x_mms_im_format=='\\t') x_mms_im_format++;\n\t}\n\tx_mms_im_format = g_strdup(x_mms_im_format);\n\tg_free(tmp);\n\treturn x_mms_im_format;\n}\n\ngchar *sipmsg_get_msgr_string(const gchar *x_mms_im_format) {\n\tgchar *msgr_orig;\n\tgsize msgr_utf16_len;\n\tgchar *msgr_utf16;\n\tgchar *msgr_enc;\n\tgchar *res;\n\tint len;\n\n\tif (!x_mms_im_format) return NULL;\n\tmsgr_orig = g_strdup_printf(\"X-MMS-IM-Format: %s\\r\\n\\r\\n\", x_mms_im_format);\n\tmsgr_utf16 = g_convert(msgr_orig, -1, \"UTF-16LE\", \"UTF-8\", NULL, &msgr_utf16_len, NULL);\n\tg_free(msgr_orig);\n\tmsgr_enc = g_base64_encode((guchar *) msgr_utf16, msgr_utf16_len);\n\tg_free(msgr_utf16);\n\tlen = strlen(msgr_enc);\n\twhile (msgr_enc[len - 1] == '=') len--;\n\tres = g_strndup(msgr_enc, len);\n\tg_free(msgr_enc);\n\treturn res;\n}\n\nstatic void msn_parse_format(const char *mime, char **pre_ret, char **post_ret);\n\n/**\n * Translates X-MMS-IM format to HTML presentation.\n */\nstatic gchar *sipmsg_apply_x_mms_im_format(const char *x_mms_im_format, gchar *body) {\n\tchar *pre, *post;\n\tgchar *res;\n\n\tif (!x_mms_im_format) {\n\t\treturn body ? g_strdup(body) : NULL;\n\t}\n\tmsn_parse_format(x_mms_im_format, &pre, &post);\n\tres = g_strdup_printf(\"%s%s%s\", pre ? pre :  \"\", body ? body : \"\", post ? post : \"\");\n\tg_free(pre);\n\tg_free(post);\n\treturn res;\n}\n\nstruct html_message_data {\n\tgchar *ms_text_format;\n\tgchar *body;\n\tgboolean preferred;\n};\n\nstatic void get_html_message_mime_cb(gpointer user_data,\n\t\t\t\t     const GSList *fields,\n\t\t\t\t     const gchar *body,\n\t\t\t\t     gsize length)\n{\n\tconst gchar *type = sipe_utils_nameval_find(fields, \"Content-Type\");\n\tstruct html_message_data *data = user_data;\n\n\tif (!data->preferred) {\n\t\tgboolean copy = FALSE;\n\n\t\t/* preferred formats */\n\t\tif (g_str_has_prefix(type, \"text/html\") ||\n\t\t    g_str_has_prefix(type, \"text/rtf\")) {\n\t\t\tcopy = TRUE;\n\t\t\tdata->preferred = TRUE;\n\n\t\t/* fallback format */\n\t\t} else if (g_str_has_prefix(type, \"text/plain\")) {\n\t\t\tcopy = TRUE;\n\t\t}\n\n\t\tif (copy) {\n\t\t\tg_free(data->ms_text_format);\n\t\t\tg_free(data->body);\n\t\t\tdata->ms_text_format = g_strdup(type);\n\t\t\tdata->body = g_strndup(body, length);\n\t\t}\n\t}\n}\n\n/* ms-text-format: text/plain; charset=UTF-8;msgr=WAAtAE0...DIADQAKAA0ACgA;ms-body=SGk= */\ngchar *get_html_message(const gchar *ms_text_format_in, const gchar *body_in)\n{\n\tgchar *msgr;\n\tgchar *res;\n\tgchar *ms_text_format = NULL;\n\tgchar *body = NULL;\n\n\tif (g_str_has_prefix(ms_text_format_in, \"multipart/related\") ||\n\t    g_str_has_prefix(ms_text_format_in, \"multipart/alternative\")) {\n\t\tstruct html_message_data data = { NULL, NULL, FALSE };\n\n\t\tsipe_mime_parts_foreach(ms_text_format_in, body_in,\n\t\t\t\t\tget_html_message_mime_cb, &data);\n\n\t\tms_text_format = data.ms_text_format;\n\t\tbody = data.body;\n\n\t} else {\n\t\tms_text_format = g_strdup(ms_text_format_in);\n\t\tbody = g_strdup(body_in);\n\t}\n\n\tif (body) {\n\t\tres = body;\n\t} else {\n\t\tgchar *tmp = sipmsg_find_part_of_header(ms_text_format, \"ms-body=\", NULL, NULL);\n\t\tgsize len;\n\t\tif (!tmp) {\n\t\t\tg_free(ms_text_format);\n\t\t\treturn NULL;\n\t\t}\n\t\tres = (gchar *) g_base64_decode(tmp, &len);\n\t\tg_free(tmp);\n\t\tif (!res) {\n\t\t\tg_free(ms_text_format);\n\t\t\treturn NULL;\n\t\t}\n\t}\n\n\tif (g_str_has_prefix(ms_text_format, \"text/html\")) {\n\t\t/*\n\t\t * HTML uses tags for formatting, not line breaks. But\n\t\t * clients still might render them, so we need to remove\n\t\t * them to avoid incorrect text rendering.\n\t\t */\n\t\tgchar *d = res;\n\t\tconst gchar *s = res;\n\t\tgchar c;\n\n\t\t/* No ANSI C nor glib function seems to exist for this :-( */\n\t\twhile ((c = *s++))\n\t\t\tif ((c != '\\n') && (c != '\\r'))\n\t\t\t\t*d++ = c;\n\t\t*d = c;\n\n\t} else if (g_str_has_prefix(ms_text_format, \"text/rtf\")) {\n\t\tchar *tmp = res;\n\t\tres = sipe_rtf_to_html(res);\n\t\tg_free(tmp);\n\t} else {\n\t\tchar *tmp = res;\n\t\tres = g_markup_escape_text(res, -1); // as this is not html\n\t\tg_free(tmp);\n\t}\n\n\tmsgr = sipmsg_find_part_of_header(ms_text_format, \"msgr=\", \";\", NULL);\n\tif (msgr) {\n\t\tgchar *x_mms_im_format = sipmsg_get_x_mms_im_format(msgr);\n\t\tgchar *tmp = res;\n\t\tg_free(msgr);\n\t\tres = sipmsg_apply_x_mms_im_format(x_mms_im_format, res);\n\t\tg_free(tmp);\n\t\tg_free(x_mms_im_format);\n\t}\n\n\tg_free(ms_text_format);\n\n\treturn res;\n}\n\nstatic gchar *\nget_reason(struct sipmsg *msg, const gchar *header)\n{\n\tconst gchar *diagnostics = sipmsg_find_header(msg, header);\n\tif (diagnostics)\n\t\treturn sipmsg_find_part_of_header(diagnostics, \"reason=\\\"\", \"\\\"\", NULL);\n\n\treturn NULL;\n}\n\ngchar *\nsipmsg_get_ms_diagnostics_reason(struct sipmsg *msg)\n{\n\treturn get_reason(msg, \"ms-diagnostics\");\n}\n\ngchar *\nsipmsg_get_ms_diagnostics_public_reason(struct sipmsg *msg)\n{\n\treturn get_reason(msg, \"ms-diagnostics-public\");\n}\n\nint\nsipmsg_parse_warning(struct sipmsg *msg, gchar **reason)\n{\n\t/*\n\t * Example header:\n\t * Warning: 310 lcs.microsoft.com \"You are currently not using the recommended version of the client\"\n\t */\n\tconst gchar *hdr = sipmsg_find_header(msg, \"Warning\");\n\tint code = -1;\n\n\tif (reason)\n\t\t*reason = NULL;\n\n\tif (hdr) {\n\t\tgchar **parts = g_strsplit(hdr, \" \", 3);\n\n\t\tif (parts[0]) {\n\t\t\tcode = atoi(parts[0]);\n\n\t\t\tif (reason && parts[1] && parts[2]) {\n\t\t\t\tsize_t len = strlen(parts[2]);\n\t\t\t\tif (len > 2 && parts[2][0] == '\"' && parts[2][len - 1] == '\"')\n\t\t\t\t\t*reason = g_strndup(parts[2] + 1, len - 2);\n\t\t\t}\n\t\t}\n\n\t\tg_strfreev(parts);\n\t}\n\n\treturn code;\n}\n\nconst gchar *sipmsg_find_call_id_header(const struct sipmsg *msg) {\n\treturn(sipmsg_find_header(msg, \"Call-ID\"));\n}\n\nconst gchar *sipmsg_find_content_type_header(const struct sipmsg *msg) {\n\treturn(sipmsg_find_header(msg, \"Content-Type\"));\n}\n\nconst gchar *sipmsg_find_cseq_header(const struct sipmsg *msg) {\n\treturn(sipmsg_find_header(msg, \"CSeq\"));\n}\n\nconst gchar *sipmsg_find_event_header(const struct sipmsg *msg) {\n\treturn(sipmsg_find_header(msg, \"Event\"));\n}\n\nconst gchar *sipmsg_find_expires_header(const struct sipmsg *msg) {\n\treturn(sipmsg_find_header(msg, \"Expires\"));\n}\n\nconst gchar *sipmsg_find_from_header(const struct sipmsg *msg) {\n\treturn(sipmsg_find_header(msg, \"From\"));\n}\n\nconst gchar *sipmsg_find_to_header(const struct sipmsg *msg) {\n\treturn(sipmsg_find_header(msg, \"To\"));\n}\n\ngchar *sipmsg_parse_address_from_header(const struct sipmsg *msg,\n\t\t\t\t\tconst gchar *name) {\n\treturn(parse_from(sipmsg_find_header(msg, name)));\n}\n\ngchar *sipmsg_parse_contact_address(const struct sipmsg *msg) {\n\treturn(sipmsg_parse_address_from_header(msg, \"Contact\"));\n}\n\ngchar *sipmsg_parse_from_address(const struct sipmsg *msg) {\n\treturn(sipmsg_parse_address_from_header(msg, \"From\"));\n}\n\ngchar *sipmsg_parse_to_address(const struct sipmsg *msg) {\n\treturn(sipmsg_parse_address_from_header(msg, \"To\"));\n}\n\nvoid sipmsg_update_to_header_tag(struct sipmsg *msg) {\n\tconst gchar *old = sipmsg_find_to_header(msg);\n\tgchar *tag       = gentag();\n\tgchar *new       = g_strdup_printf(\"%s;tag=%s\", old, tag);\n\tg_free(tag);\n\tsipmsg_remove_header_now(msg, \"To\");\n\tsipmsg_add_header_now(msg, \"To\", new);\n\tg_free(new);\n}\n\n\n//------------------------------------------------------------------------------------------\n//TEMP solution to include it here (copy from purple's msn protocol\n//How to reuse msn's util methods from sipe?\n\n/* from internal.h */\n#define MSG_LEN 2048\n#define BUF_LEN MSG_LEN\n\nvoid\nmsn_parse_format(const char *mime, char **pre_ret, char **post_ret)\n{\n\tchar *cur;\n\tGString *pre  = g_string_new(NULL);\n\tGString *post = g_string_new(NULL);\n\tunsigned int colors[3];\n\n\tif (pre_ret  != NULL) *pre_ret  = NULL;\n\tif (post_ret != NULL) *post_ret = NULL;\n\n\tcur = strstr(mime, \"FN=\");\n\n\tif (cur && (*(cur = cur + 3) != ';'))\n\t{\n\t\tpre = g_string_append(pre, \"<FONT FACE=\\\"\");\n\n\t\twhile (*cur && *cur != ';')\n\t\t{\n\t\t\tpre = g_string_append_c(pre, *cur);\n\t\t\tcur++;\n\t\t}\n\n\t\tpre = g_string_append(pre, \"\\\">\");\n\t\tpost = g_string_prepend(post, \"</FONT>\");\n\t}\n\n\tcur = strstr(mime, \"EF=\");\n\n\tif (cur && (*(cur = cur + 3) != ';'))\n\t{\n\t\twhile (*cur && *cur != ';')\n\t\t{\n\t\t\tpre = g_string_append_c(pre, '<');\n\t\t\tpre = g_string_append_c(pre, *cur);\n\t\t\tpre = g_string_append_c(pre, '>');\n\t\t\tpost = g_string_prepend_c(post, '>');\n\t\t\tpost = g_string_prepend_c(post, *cur);\n\t\t\tpost = g_string_prepend_c(post, '/');\n\t\t\tpost = g_string_prepend_c(post, '<');\n\t\t\tcur++;\n\t\t}\n\t}\n\n\tcur = strstr(mime, \"CO=\");\n\n\tif (cur && (*(cur = cur + 3) != ';'))\n\t{\n\t\tint i;\n\n\t\ti = sscanf(cur, \"%02x%02x%02x;\", &colors[0], &colors[1], &colors[2]);\n\n\t\tif (i > 0)\n\t\t{\n\t\t\tchar tag[64];\n\n\t\t\tif (i == 1)\n\t\t\t{\n\t\t\t\tcolors[1] = 0;\n\t\t\t\tcolors[2] = 0;\n\t\t\t}\n\t\t\telse if (i == 2)\n\t\t\t{\n\t\t\t\tunsigned int temp = colors[0];\n\n\t\t\t\tcolors[0] = colors[1];\n\t\t\t\tcolors[1] = temp;\n\t\t\t\tcolors[2] = 0;\n\t\t\t}\n\t\t\telse if (i == 3)\n\t\t\t{\n\t\t\t\tunsigned int temp = colors[2];\n\n\t\t\t\tcolors[2] = colors[0];\n\t\t\t\tcolors[0] = temp;\n\t\t\t}\n\n\t\t\t/* hh is undefined in mingw's gcc 4.4\n\t\t\t *  https://sourceforge.net/tracker/index.php?func=detail&aid=2818436&group_id=2435&atid=102435\n\t\t\t */\n\t\t\tg_snprintf(tag, sizeof(tag),\n\t\t\t\t\t   \"<FONT COLOR=\\\"#%02x%02x%02x\\\">\",\n\t\t\t\t\t   (unsigned char)colors[0], (unsigned char)colors[1], (unsigned char)colors[2]);\n\n\t\t\tpre = g_string_append(pre, tag);\n\t\t\tpost = g_string_prepend(post, \"</FONT>\");\n\t\t}\n\t}\n\n\tcur = strstr(mime, \"RL=\");\n\n\tif (cur && (*(cur = cur + 3) != ';'))\n\t{\n\t\tif (*cur == '1')\n\t\t{\n\t\t\t/* RTL text was received */\n\t\t\tpre = g_string_append(pre, \"<SPAN style=\\\"direction:rtl;text-align:right;\\\">\");\n\t\t\tpost = g_string_prepend(post, \"</SPAN>\");\n\t\t}\n\t}\n\n\tcur = sipe_utils_uri_unescape(pre->str);\n\tg_string_free(pre, TRUE);\n\n\tif (pre_ret != NULL)\n\t\t*pre_ret = cur;\n\telse\n\t\tg_free(cur);\n\n\tcur = sipe_utils_uri_unescape(post->str);\n\tg_string_free(post, TRUE);\n\n\tif (post_ret != NULL)\n\t\t*post_ret = cur;\n\telse\n\t\tg_free(cur);\n}\n\nstatic const char *\nencode_spaces(const char *str)\n{\n\tstatic char buf[BUF_LEN];\n\tconst char *c;\n\tchar *d;\n\n\tg_return_val_if_fail(str != NULL, NULL);\n\n\tfor (c = str, d = buf; *c != '\\0'; c++)\n\t{\n\t\tif (*c == ' ')\n\t\t{\n\t\t\t*d++ = '%';\n\t\t\t*d++ = '2';\n\t\t\t*d++ = '0';\n\t\t}\n\t\telse\n\t\t\t*d++ = *c;\n\t}\n\t*d = '\\0';\n\n\treturn buf;\n}\n\nvoid\nsipe_parse_html(const char *html, char **attributes, char **message)\n{\n\tint len, retcount = 0;\n\tconst char *c;\n\tchar *msg;\n\tchar *fontface = NULL;\n\tchar fonteffect[4];\n\tchar fontcolor[7];\n\tchar direction = '0';\n\n\tgboolean has_bold = FALSE;\n\tgboolean has_italic = FALSE;\n\tgboolean has_underline = FALSE;\n\tgboolean has_strikethrough = FALSE;\n\n\tg_return_if_fail(html       != NULL);\n\tg_return_if_fail(attributes != NULL);\n\tg_return_if_fail(message    != NULL);\n\n#define _HTML_UNESCAPE \\\n\tif (!g_ascii_strncasecmp(c, \"&lt;\", 4)) { \\\n\t\tmsg[retcount++] = '<'; \\\n\t\tc += 4; \\\n\t} else if (!g_ascii_strncasecmp(c, \"&gt;\", 4)) { \\\n\t\tmsg[retcount++] = '>'; \\\n\t\tc += 4; \\\n\t} else if (!g_ascii_strncasecmp(c, \"&nbsp;\", 6)) { \\\n\t\tmsg[retcount++] = ' '; \\\n\t\tc += 6; \\\n\t} else if (!g_ascii_strncasecmp(c, \"&quot;\", 6)) { \\\n\t\tmsg[retcount++] = '\"'; \\\n\t\tc += 6; \\\n\t} else if (!g_ascii_strncasecmp(c, \"&amp;\", 5)) { \\\n\t\tmsg[retcount++] = '&'; \\\n\t\tc += 5; \\\n\t} else if (!g_ascii_strncasecmp(c, \"&apos;\", 6)) { \\\n\t\tmsg[retcount++] = '\\''; \\\n\t\tc += 6; \\\n\t} else { \\\n\t\tmsg[retcount++] = *c++; \\\n\t}\n\n\tlen = strlen(html);\n\tmsg = g_malloc0(len + 1);\n\n\tmemset(fontcolor, 0, sizeof(fontcolor));\n\tstrcat(fontcolor, \"0\");\n\tmemset(fonteffect, 0, sizeof(fonteffect));\n\n\tfor (c = html; *c != '\\0';)\n\t{\n\t\tif (*c == '<')\n\t\t{\n\t\t\tif (!g_ascii_strncasecmp(c + 1, \"br>\", 3))\n\t\t\t{\n\t\t\t\tmsg[retcount++] = '\\r';\n\t\t\t\tmsg[retcount++] = '\\n';\n\t\t\t\tc += 4;\n\t\t\t}\n\t\t\telse if (!g_ascii_strncasecmp(c + 1, \"div>\", 4))\n\t\t\t{\n\t\t\t\tmsg[retcount++] = '\\r';\n\t\t\t\tmsg[retcount++] = '\\n';\n\t\t\t\tc += 5;\n\t\t\t\tif (!g_ascii_strncasecmp(c, \"<br></div>\", 10)) {\n\t\t\t\t\t/* This is an empty paragraph; replace it with\n\t\t\t\t\t * one line break. */\n\t\t\t\t\tc += 10;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (!g_ascii_strncasecmp(c + 1, \"i>\", 2))\n\t\t\t{\n\t\t\t\tif (!has_italic)\n\t\t\t\t{\n\t\t\t\t\tstrcat(fonteffect, \"I\");\n\t\t\t\t\thas_italic = TRUE;\n\t\t\t\t}\n\t\t\t\tc += 3;\n\t\t\t}\n\t\t\telse if (!g_ascii_strncasecmp(c + 1, \"b>\", 2))\n\t\t\t{\n\t\t\t\tif (!has_bold)\n\t\t\t\t{\n\t\t\t\t\tstrcat(fonteffect, \"B\");\n\t\t\t\t\thas_bold = TRUE;\n\t\t\t\t}\n\t\t\t\tc += 3;\n\t\t\t}\n\t\t\telse if (!g_ascii_strncasecmp(c + 1, \"u>\", 2))\n\t\t\t{\n\t\t\t\tif (!has_underline)\n\t\t\t\t{\n\t\t\t\t\tstrcat(fonteffect, \"U\");\n\t\t\t\t\thas_underline = TRUE;\n\t\t\t\t}\n\t\t\t\tc += 3;\n\t\t\t}\n\t\t\telse if (!g_ascii_strncasecmp(c + 1, \"s>\", 2))\n\t\t\t{\n\t\t\t\tif (!has_strikethrough)\n\t\t\t\t{\n\t\t\t\t\tstrcat(fonteffect, \"S\");\n\t\t\t\t\thas_strikethrough = TRUE;\n\t\t\t\t}\n\t\t\t\tc += 3;\n\t\t\t}\n\t\t\telse if (!g_ascii_strncasecmp(c + 1, \"a href=\\\"\", 8))\n\t\t\t{\n\t\t\t\tc += 9;\n\n\t\t\t\tif (!g_ascii_strncasecmp(c, \"mailto:\", 7))\n\t\t\t\t\tc += 7;\n\n\t\t\t\twhile ((*c != '\\0') && g_ascii_strncasecmp(c, \"\\\">\", 2))\n\t\t\t\t\tif (*c == '&') {\n\t\t\t\t\t\t_HTML_UNESCAPE;\n\t\t\t\t\t} else\n\t\t\t\t\t\tmsg[retcount++] = *c++;\n\n\t\t\t\tif (*c != '\\0')\n\t\t\t\t\tc += 2;\n\n\t\t\t\t/* ignore descriptive string */\n\t\t\t\twhile ((*c != '\\0') && g_ascii_strncasecmp(c, \"</a>\", 4))\n\t\t\t\t\tc++;\n\n\t\t\t\tif (*c != '\\0')\n\t\t\t\t\tc += 4;\n\t\t\t}\n\t\t\telse if (!g_ascii_strncasecmp(c + 1, \"span\", 4))\n\t\t\t{\n\t\t\t\t/* Bi-directional text support using CSS properties in span tags */\n\t\t\t\tc += 5;\n\n\t\t\t\twhile (*c != '\\0' && *c != '>')\n\t\t\t\t{\n\t\t\t\t\twhile (*c == ' ')\n\t\t\t\t\t\tc++;\n\t\t\t\t\tif (!g_ascii_strncasecmp(c, \"dir=\\\"rtl\\\"\", 9))\n\t\t\t\t\t{\n\t\t\t\t\t\tc += 9;\n\t\t\t\t\t\tdirection = '1';\n\t\t\t\t\t}\n\t\t\t\t\telse if (!g_ascii_strncasecmp(c, \"style=\\\"\", 7))\n\t\t\t\t\t{\n\t\t\t\t\t\t/* Parse inline CSS attributes */\n\t\t\t\t\t\tint attr_len = 0;\n\t\t\t\t\t\tc += 7;\n\t\t\t\t\t\twhile (*(c + attr_len) != '\\0' && *(c + attr_len) != '\"')\n\t\t\t\t\t\t\tattr_len++;\n\t\t\t\t\t\tif (*(c + attr_len) == '\"')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tchar *css_attributes;\n\t\t\t\t\t\t\tchar *attr_dir;\n\t\t\t\t\t\t\tcss_attributes = g_strndup(c, attr_len);\n\t\t\t\t\t\t\tattr_dir = sipe_backend_markup_css_property(css_attributes, \"direction\");\n\t\t\t\t\t\t\tg_free(css_attributes);\n\t\t\t\t\t\t\tif (attr_dir && (!g_ascii_strncasecmp(attr_dir, \"RTL\", 3)))\n\t\t\t\t\t\t\t\tdirection = '1';\n\t\t\t\t\t\t\tg_free(attr_dir);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tc++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (*c == '>')\n\t\t\t\t\tc++;\n\t\t\t}\n\t\t\telse if (!g_ascii_strncasecmp(c + 1, \"font\", 4))\n\t\t\t{\n\t\t\t\tc += 5;\n\n\t\t\t\twhile ((*c != '\\0') && !g_ascii_strncasecmp(c, \" \", 1))\n\t\t\t\t\tc++;\n\n\t\t\t\tif (!g_ascii_strncasecmp(c, \"color=\\\"#\", 7))\n\t\t\t\t{\n\t\t\t\t\tc += 8;\n\n\t\t\t\t\tfontcolor[0] = *(c + 4);\n\t\t\t\t\tfontcolor[1] = *(c + 5);\n\t\t\t\t\tfontcolor[2] = *(c + 2);\n\t\t\t\t\tfontcolor[3] = *(c + 3);\n\t\t\t\t\tfontcolor[4] = *c;\n\t\t\t\t\tfontcolor[5] = *(c + 1);\n\n\t\t\t\t\tc += 8;\n\t\t\t\t}\n\t\t\t\telse if (!g_ascii_strncasecmp(c, \"face=\\\"\", 6))\n\t\t\t\t{\n\t\t\t\t\tconst char *end = NULL;\n\t\t\t\t\tconst char *comma = NULL;\n\t\t\t\t\tunsigned int namelen = 0;\n\n\t\t\t\t\tc += 6;\n\t\t\t\t\tend = strchr(c, '\\\"');\n\t\t\t\t\tcomma = strchr(c, ',');\n\n\t\t\t\t\tif (comma == NULL || comma > end)\n\t\t\t\t\t\tnamelen = (unsigned int)(end - c);\n\t\t\t\t\telse\n\t\t\t\t\t\tnamelen = (unsigned int)(comma - c);\n\n\t\t\t\t\tg_free(fontface);\n\t\t\t\t\tfontface = g_strndup(c, namelen);\n\t\t\t\t\tc = end + 2;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t/* Drop all unrecognized/misparsed font tags */\n\t\t\t\t\twhile ((*c != '\\0') && g_ascii_strncasecmp(c, \"\\\">\", 2))\n\t\t\t\t\t\tc++;\n\n\t\t\t\t\tif (*c != '\\0')\n\t\t\t\t\t\tc += 2;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\twhile ((*c != '\\0') && (*c != '>'))\n\t\t\t\t\tc++;\n\t\t\t\tif (*c != '\\0')\n\t\t\t\t\tc++;\n\t\t\t}\n\t\t}\n\t\telse if (*c == '&')\n\t\t{\n\t\t\t_HTML_UNESCAPE;\n\t\t}\n\t\telse\n\t\t\tmsg[retcount++] = *c++;\n\t}\n\n\tif (fontface == NULL)\n\t\tfontface = g_strdup(\"MS Sans Serif\");\n\n\t*attributes = g_strdup_printf(\"FN=%s; EF=%s; CO=%s; PF=0; RL=%c\",\n\t\t\t\t\t\t\t\t  encode_spaces(fontface),\n\t\t\t\t\t\t\t\t  fonteffect, fontcolor, direction);\n\t*message = msg;\n\n\tg_free(fontface);\n\n#undef _HTML_UNESCAPE\n}\n// End of TEMP\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/sipmsg.h",
    "content": "/**\n * @file sipmsg.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2008 Novell, Inc.\n * Copyright (C) 2005, Thomas Butter <butter@uni-mannheim.de>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/*\n * Interface dependencies:\n *\n * <glib.h>\n */\n\n#define SIPMSG_RESPONSE_FATAL_ERROR -1\n#define SIPMSG_BODYLEN_CHUNKED      -1\n\nstruct sipmsg {\n\tint response; /* 0 means request, otherwise response code */\n\tgchar *responsestr;\n\tgchar *method;\n\tgchar *target;\n\tGSList *headers;\n\tGSList *new_headers;\n\tint bodylen;\n\tgchar *body;\n\tgchar *signature;\n\tgchar *rand;\n\tgchar *num;\n};\n\nstruct sipendpoint {\n\tgchar *contact;\n\tgchar *epid;\n};\n\n\nstruct sipmsg *sipmsg_parse_msg(const gchar *msg);\nstruct sipmsg *sipmsg_parse_header(const gchar *header);\nstruct sipmsg *sipmsg_copy(const struct sipmsg *other);\nvoid sipmsg_add_header_now(struct sipmsg *msg, const gchar *name, const gchar *value);\nvoid sipmsg_add_header(struct sipmsg *msg, const gchar *name, const gchar *value);\nvoid sipmsg_strip_headers(struct sipmsg *msg, const gchar *keepers[]);\nvoid sipmsg_merge_new_headers(struct sipmsg *msg);\nvoid sipmsg_free(struct sipmsg *msg);\n\n/**\n * Parses CSeq from SIP message\n *\n * @param msg (in) SIP message\n *\n * @return int type CSeq value (i.e. without method).\n */\nint sipmsg_parse_cseq(struct sipmsg *msg);\n\nGSList *sipmsg_parse_endpoints_header(const gchar *header);\n/**\n * Parses sip: and tel: URI out of P-Asserted-Identity header from INVITE request.\n * You must free the values.\n *\n * Example headers:\n * P-Asserted-Identity: \"Cullen Jennings\" <sip:fluffy@cisco.com>\n * P-Asserted-Identity: tel:+14085264000\n * P-Asserted-Identity: \"Lunch, Lucas\" <sip:llucas@cisco.com>,<tel:+420123456;ext=88463>\n *\n * @param header (in) P-Asserted-Identity header contents\n * @param sip_uri (out) parsed sip: URI or NULL if missing\n * @param tel_uri (out) parsed tel: URI or NULL if missing\n */\nvoid sipmsg_parse_p_asserted_identity(const gchar *header, gchar **sip_uri,\n\t\t\t\t      gchar **tel_uri);\nconst gchar *sipmsg_find_header(const struct sipmsg *msg, const gchar *name);\nconst gchar *sipmsg_find_header_instance(const struct sipmsg *msg, const gchar *name, int which);\ngchar *sipmsg_find_part_of_header(const char *hdr, const char * before, const char * after, const char * def);\nconst gchar *sipmsg_find_auth_header(struct sipmsg *msg, const gchar *name);\nvoid sipmsg_remove_header_now(struct sipmsg *msg, const gchar *name);\nchar *sipmsg_to_string(const struct sipmsg *msg);\n\n/**\n * Formats message to html if not yet.\n * Either - keep as is if text/html, or escape text, or escape text and apply format string if any\n *\n * @param body in case of 'ms_text_format is Content-Type header' or NULL otherwise\n * @param ms_text_format either ms-text-format ot Content-Type header.\n *\n * Allocates memory. Must be feed when done.\n */\ngchar *get_html_message(const gchar *ms_text_format, const gchar *body);\n\n/**\n * Returns UTF-16LE/'modified base64' encoded X-MMS-IM-Format\n * based on input x_mms_im_format.\n */\ngchar *sipmsg_get_msgr_string(const gchar *x_mms_im_format);\n\n/**\n * Parses the Purple message formatting (html) into the MSN format.\n *\n * @param html\t\t\tThe html message to format.\n * @param attributes\tThe returned attributes string.\n * @param message\t\tThe returned message string.\n *\n * @return The new message.\n */\nvoid sipe_parse_html(const char *html, char **attributes, char **message);\n\n/**\n * Extracts reason string from ms-diagnostics header of SIP message\n *\n * @param msg SIP message\n *\n * @return reason string. Must be g_free()'d after use.\n */\ngchar *sipmsg_get_ms_diagnostics_reason(struct sipmsg *msg);\n\n/**\n * Extracts reason string from ms-diagnostics-public header of SIP message\n *\n * @param msg SIP message\n *\n * @return reason string. Must be g_free()'d after use.\n */\ngchar *sipmsg_get_ms_diagnostics_public_reason(struct sipmsg *msg);\n\n/**\n * Parses Warning header of SIP message, if present.\n *\n * @param msg (in) SIP message\n * @param reason (out) parsed warning text or NULL if missing. Must be g_free()'d\n *               after use.\n *\n * @return warning code or -1 if warning header is not present in message.\n */\nint sipmsg_parse_warning(struct sipmsg *msg, gchar **reason);\n\n/**\n * Helpers to find some common headers in SIP message\n *\n * @param msg (in) SIP message\n *\n * @return header text or NULL if header is not present message.\n */\nconst gchar *sipmsg_find_call_id_header(const struct sipmsg *msg);\nconst gchar *sipmsg_find_content_type_header(const struct sipmsg *msg);\nconst gchar *sipmsg_find_cseq_header(const struct sipmsg *msg);\nconst gchar *sipmsg_find_event_header(const struct sipmsg *msg);\nconst gchar *sipmsg_find_expires_header(const struct sipmsg *msg);\nconst gchar *sipmsg_find_from_header(const struct sipmsg *msg);\nconst gchar *sipmsg_find_to_header(const struct sipmsg *msg);\n\n/**\n * Parse addresses out of SIP message headers\n *\n * @param msg (in)  SIP message\n * @param name (in) header name\n *\n * @return address or @c NULL if header not found or parse failure.\n *         Must be @c g_free()'d after use.\n */\ngchar *sipmsg_parse_contact_address(const struct sipmsg *msg);\ngchar *sipmsg_parse_from_address(const struct sipmsg *msg);\ngchar *sipmsg_parse_to_address(const struct sipmsg *msg);\ngchar *sipmsg_parse_address_from_header(const struct sipmsg *msg,\n\t\t\t\t\tconst gchar *name);\n\n/**\n * Generate and append new tag to the \"To:\" header in the message\n *\n * @param msg (in) SIP message\n */\nvoid sipmsg_update_to_header_tag(struct sipmsg *msg);\n"
  },
  {
    "path": "src/core/uuid.c",
    "content": "/**\n * @file uuid.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2008-2015 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <stdio.h>\n#include <string.h>\n\n#include <glib.h>\n#include <glib/gprintf.h>\n\n#include \"sipe-digest.h\"\n#include \"uuid.h\"\n\n/*\n * This assumes that the structure is correctly packed on all target\n * platforms, i.e. sizeof(uuid_t) == 16\n *\n * See also the test added to \"configure\". On Windows platform we know\n * that #pragma pack() exists and therefore can use it in the code.\n *\n */\n#ifdef _WIN32\n#pragma pack(push, 1)\n#endif\ntypedef struct {\n   guint32 time_low;\n   guint16 time_mid;\n   guint16 time_hi_and_version;\n   guint8  clock_seq_hi_and_reserved;\n   guint8  clock_seq_low;\n   guint8  node[6];\n} uuid_t;\n#ifdef _WIN32\n#pragma pack(pop)\n#endif\n\nstatic void printUUID(uuid_t *uuid, char *string)\n{\n\tint i;\n\tsize_t pos;\n\tsprintf(string, \"%08x-%04x-%04x-%02x%02x-\", uuid->time_low\n\t\t\t, uuid->time_mid, uuid->time_hi_and_version\n\t\t\t, uuid->clock_seq_hi_and_reserved\n\t\t\t, uuid->clock_seq_low\n\t\t\t);\n\tpos = strlen(string);\n\tfor(i=0;i<6;i++)\n\t{\n\t\tpos += sprintf(&string[pos], \"%02x\", uuid->node[i]);\n\t}\n}\n\nstatic void createUUIDfromHash(uuid_t *uuid, const unsigned char *hash)\n{\n\tmemcpy(uuid, hash, sizeof(uuid_t));\n\tuuid->time_hi_and_version &= GUINT16_TO_LE(0x0FFF);\n\tuuid->time_hi_and_version |= GUINT16_TO_LE(0x5000);\n\tuuid->clock_seq_hi_and_reserved &= 0x3F;\n\tuuid->clock_seq_hi_and_reserved |= 0x80;\n}\n\nchar *generateUUIDfromEPID(const gchar *epid)\n{\n#define UUID_STRING_LENGTH 36\n\t/* derived from \"fcacfb03-8a73-46ef-91b1-e5ebeeaba4fe\" */\n\tuuid_t result = {\n\t\t0xfcacfb03,\n\t\t0x8a73,\n\t\t0x46ef,\n\t\t0x91, 0xb1,\n\t\t{ 0xe5, 0xeb, 0xee, 0xab, 0xa4, 0xfe }\n\t};\n\tgchar *buf;\n\tguchar digest[SIPE_DIGEST_SHA1_LENGTH];\n\tguint digest_length = sizeof(uuid_t) + strlen(epid);\n\tguint buf_length    = digest_length;\n\n\tresult.time_low = GUINT32_FROM_LE(result.time_low);\n\tresult.time_mid = GUINT16_FROM_LE(result.time_mid);\n\tresult.time_hi_and_version = GUINT16_FROM_LE(result.time_hi_and_version);\n\n\t/* buffer must be able to hold at least the UUID string */\n\tif (buf_length < UUID_STRING_LENGTH)\n\t\tbuf_length = UUID_STRING_LENGTH;\n\tbuf = g_malloc(buf_length + 1);\n\n\tmemcpy(buf, &result, sizeof(uuid_t));\n\tstrcpy(buf + sizeof(uuid_t), epid);\n\n\tsipe_digest_sha1((guchar *)buf, digest_length, digest);\n\tcreateUUIDfromHash(&result, digest);\n\n\tresult.time_low = GUINT32_TO_LE(result.time_low);\n\tresult.time_mid = GUINT16_TO_LE(result.time_mid);\n\tresult.time_hi_and_version = GUINT16_TO_LE(result.time_hi_and_version);\n\n\tprintUUID(&result, buf);\n\treturn(buf);\n}\n\n/**\n * Generates epid from user SIP URI, hostname and IP address.\n * Thus epid will be the same each start and\n * not needed to be persistent.\n *\n * Using MAC address proved to be poorly portable solution.\n *\n * Must be g_free()'d\n */\nchar *sipe_get_epid(const char *self_sip_uri,\n\t\t\t   const char *hostname,\n\t\t\t   const char *ip_address)\n{\n/* 6 last digits of hash */\n#define SIPE_EPID_HASH_START 14\n#define SIPE_EPID_HASH_END   SIPE_DIGEST_SHA1_LENGTH\n#define SIPE_EPID_LENGTH     (2 * (SIPE_EPID_HASH_END - SIPE_EPID_HASH_START + 1))\n\n\tint i,j;\n\tchar out[SIPE_EPID_LENGTH + 1];\n\tchar *buf = g_strdup_printf(\"%s:%s:%s\", self_sip_uri, hostname, ip_address);\n\tguchar hash[SIPE_DIGEST_SHA1_LENGTH];\n\n\tsipe_digest_sha1((guchar *) buf, strlen(buf), hash);\n\tfor (i = SIPE_EPID_HASH_START, j = 0;\n\t     i < SIPE_EPID_HASH_END;\n\t     i++, j += 2) {\n\t\tg_sprintf(&out[j], \"%02x\", hash[i]);\n\t}\n\tout[SIPE_EPID_LENGTH] = 0;\n\n\tg_free(buf);\n\treturn g_strdup(out);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/core/uuid.h",
    "content": "/**\n * @file uuid.h\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/*\n * Interface dependencies:\n *\n * <glib.h>\n */\n\n/* Must be g_free'd */\nchar *generateUUIDfromEPID(const gchar *epid);\n\n/* Must be g_free'd */\nchar *sipe_get_epid(const char *self_sip_uri,\n\t\t    const char *hostname,\n\t\t    const char *ip_address);\n"
  },
  {
    "path": "src/miranda/INSTALL",
    "content": "FIXME: miranda client code compile instructions...\n"
  },
  {
    "path": "src/miranda/miranda-buddy.c",
    "content": "/**\n * @file miranda-buddy.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <windows.h>\n#include <stdio.h>\n\n#include <glib.h>\n\n#include \"miranda-version.h\"\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"m_protomod.h\"\n#include \"m_database.h\"\n#include \"m_clist.h\"\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"miranda-private.h\"\n\n#define ADD_PROP(key,value) g_hash_table_insert(info_to_property_table, (gpointer)key, value)\n\nstatic GHashTable *info_to_property_table = NULL;\n\nstatic void\ninit_property_hash(void)\n{\n\tinfo_to_property_table = g_hash_table_new(NULL, NULL);\n\n//\tADD_PROP(SIPE_BUDDY_INFO_DISPLAY_NAME, ALIAS_PROP);\n\tADD_PROP(SIPE_BUDDY_INFO_EMAIL       , \"e-mail\");\n\tADD_PROP(SIPE_BUDDY_INFO_WORK_PHONE  , \"CompanyPhone\");\n//\tADD_PROP(SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY, PHONE_DISPLAY_PROP);\n//\tADD_PROP(SIPE_BUDDY_INFO_SITE        , SITE_PROP);\n\tADD_PROP(SIPE_BUDDY_INFO_COMPANY     , \"Company\");\n\tADD_PROP(SIPE_BUDDY_INFO_DEPARTMENT  , \"CompanyDepartment\");\n\tADD_PROP(SIPE_BUDDY_INFO_JOB_TITLE   , \"CompanyPosition\");\n//\tADD_PROP(SIPE_BUDDY_INFO_OFFICE      , OFFICE_PROP);\n\tADD_PROP(SIPE_BUDDY_INFO_STREET      , \"CompanyStreet\");\n\tADD_PROP(SIPE_BUDDY_INFO_CITY        , \"CompanyCity\");\n\tADD_PROP(SIPE_BUDDY_INFO_STATE       , \"CompanyState\");\n\tADD_PROP(SIPE_BUDDY_INFO_ZIPCODE     , \"CompanyZIP\");\n\tADD_PROP(SIPE_BUDDY_INFO_COUNTRY     , \"CompanyCountry\");\n\n\t/* Summary values:\nSetValue(hwndDlg,IDC_NICK,hContact,szProto,\"Nick\",0);\nSetValue(hwndDlg,IDC_FIRSTNAME,hContact,szProto,\"FirstName\",0);\nSetValue(hwndDlg,IDC_LASTNAME,hContact,szProto,\"LastName\",0);\nSetValue(hwndDlg,IDC_EMAIL,hContact,szProto,\"e-mail\",0);\nSetValue(hwndDlg,IDC_AGE,hContact,szProto,\"Age\",SVS_ZEROISUNSPEC);\nSetValue(hwndDlg,IDC_GENDER,hContact,szProto,\"Gender\",SVS_GENDER);\nSetValue(hwndDlg,IDC_DOBDAY,hContact,szProto,\"BirthDay\",0);\nSetValue(hwndDlg,IDC_DOBMONTH,hContact,szProto,\"BirthMonth\",SVS_MONTH);\nSetValue(hwndDlg,IDC_DOBYEAR,hContact,szProto,\"BirthYear\",0);\n\n\t\tLocation values:\nSetValue(hwndDlg,IDC_STREET,hContact,szProto,\"Street\",SVS_ZEROISUNSPEC);\nSetValue(hwndDlg,IDC_CITY,hContact,szProto,\"City\",SVS_ZEROISUNSPEC);\nSetValue(hwndDlg,IDC_STATE,hContact,szProto,\"State\",SVS_ZEROISUNSPEC);\nSetValue(hwndDlg,IDC_ZIP,hContact,szProto,\"ZIP\",SVS_ZEROISUNSPEC);\nSetValue(hwndDlg,IDC_COUNTRY,hContact,szProto,\"Country\",SVS_COUNTRY);\nSetValue(hwndDlg,IDC_LANGUAGE1,hContact,szProto,\"Language1\",SVS_ZEROISUNSPEC);\nSetValue(hwndDlg,IDC_LANGUAGE2,hContact,szProto,\"Language2\",SVS_ZEROISUNSPEC);\nSetValue(hwndDlg,IDC_LANGUAGE3,hContact,szProto,\"Language3\",SVS_ZEROISUNSPEC);\nSetValue(hwndDlg,IDC_TIMEZONE,hContact,szProto,\"Timezone\",SVS_TIMEZONE);\n\n\t\tWork values:\nSetValue(hwndDlg,IDC_COMPANY,hContact,szProto,\"Company\",SVS_ZEROISUNSPEC);\nSetValue(hwndDlg,IDC_DEPARTMENT,hContact,szProto,\"CompanyDepartment\",SVS_ZEROISUNSPEC);\nSetValue(hwndDlg,IDC_POSITION,hContact,szProto,\"CompanyPosition\",SVS_ZEROISUNSPEC);\nSetValue(hwndDlg,IDC_STREET,hContact,szProto,\"CompanyStreet\",SVS_ZEROISUNSPEC);\nSetValue(hwndDlg,IDC_CITY,hContact,szProto,\"CompanyCity\",SVS_ZEROISUNSPEC);\nSetValue(hwndDlg,IDC_STATE,hContact,szProto,\"CompanyState\",SVS_ZEROISUNSPEC);\nSetValue(hwndDlg,IDC_ZIP,hContact,szProto,\"CompanyZIP\",SVS_ZEROISUNSPEC);\nSetValue(hwndDlg,IDC_COUNTRY,hContact,szProto,\"CompanyCountry\",SVS_COUNTRY);\nSetValue(hwndDlg,IDC_WEBPAGE,hContact,szProto,\"CompanyHomepage\",SVS_ZEROISUNSPEC);\n\n\t\tBackground:\nSetValue(hwndDlg,IDC_WEBPAGE,hContact,szProto,\"Homepage\",SVS_ZEROISUNSPEC);\n\n\t\tContact:\nif(DBGetContactSettingTString(hContact,szProto,\"e-mail\",&dbv))\nmir_snprintf(idstr, SIZEOF(idstr), \"e-mail%d\", i );\nmir_snprintf(idstr, SIZEOF(idstr), \"Mye-mail%d\",i);\nif(!DBGetContactSettingTString(hContact,szProto,\"Phone\",&dbv)) {\nif(!DBGetContactSettingTString(hContact,szProto,\"Fax\",&dbv)) {\nif(!DBGetContactSettingTString(hContact,szProto,\"Cellular\",&dbv)) {\nif(!DBGetContactSettingTString(hContact,szProto,\"CompanyPhone\",&dbv)) {\nif(!DBGetContactSettingTString(hContact,szProto,\"CompanyFax\",&dbv)) {\nmir_snprintf(idstr, SIZEOF(idstr), \"MyPhone%d\",i);\n\n\t*/\n}\n\nstatic const gchar *\nsipe_info_to_miranda_property(sipe_buddy_info_fields info)\n{\n\tif (!info_to_property_table)\n\t\tinit_property_hash();\n\treturn (const char *)g_hash_table_lookup(info_to_property_table, (gconstpointer)info);\n}\n\nsipe_backend_buddy sipe_miranda_buddy_find(SIPPROTO *pr,\n\t\t\t\t\t   const gchar *name,\n\t\t\t\t\t   const gchar *group)\n{\n\tHANDLE hContact;\n\n\thContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);\n\twhile (hContact) {\n\t\tgchar* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);\n\t\tif (szProto != NULL && !lstrcmpA(szProto, pr->proto.m_szModuleName)) {\n\t\t\tDBVARIANT dbv;\n\t\t\tif ( !DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv )) {\n\t\t\t\tint tCompareResult = lstrcmpiA( dbv.pszVal, name );\n\t\t\t\tDBFreeVariant( &dbv );\n\t\t\t\tif ( !tCompareResult ) {\n\t\t\t\t\tif (!group)\n\t\t\t\t\t{\n\t\t\t\t\t\tSIPE_DEBUG_INFO(\"buddy_name <%s> group <%s> found <%08x>\", name, group, hContact);\n\t\t\t\t\t\treturn hContact;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !DBGetContactSettingStringUtf(hContact, \"CList\", \"Group\", &dbv )) {\n\t\t\t\t\t\tint tCompareResult = lstrcmpiA( dbv.pszVal, group );\n\t\t\t\t\t\tDBFreeVariant( &dbv );\n\t\t\t\t\t\tif ( !tCompareResult )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tSIPE_DEBUG_INFO(\"buddy_name <%s> group <%s> found <%08x> in group\", name, group, hContact);\n\t\t\t\t\t\t\treturn hContact;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSIPE_DEBUG_INFO(\"buddy_name <%s> group <%s> ERROR getting contact group\", name, group);\n\t\t\t\t\t\treturn NULL;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\thContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);\n\t}\n\n\tSIPE_DEBUG_INFO(\"buddy_name <%s> group <%s> NOT FOUND\", name, group);\n\treturn NULL;\n}\nsipe_backend_buddy sipe_backend_buddy_find(struct sipe_core_public *sipe_public,\n\t\t\t\t\t   const gchar *name,\n\t\t\t\t\t   const gchar *group)\n{\n\treturn sipe_miranda_buddy_find(sipe_public->backend_private, name, group);\n}\n\nGSList* sipe_miranda_buddy_find_all(SIPPROTO *pr,\n\t\t\t\t    const gchar *buddy_name,\n\t\t\t\t    const gchar *group_name)\n{\n\tGSList *res = NULL;\n\tHANDLE hContact;\n\n\thContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);\n\twhile (hContact) {\n\t\tgchar* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);\n\t\tif (szProto != NULL && !lstrcmpA(szProto, pr->proto.m_szModuleName)) {\n\t\t\tif (DBGetContactSettingByte(hContact, pr->proto.m_szModuleName, \"ChatRoom\", 0) == 0) {\n\t\t\t\tDBVARIANT dbv;\n\t\t\t\tif (!buddy_name)\n\t\t\t\t\tres = g_slist_append(res, hContact);\n\t\t\t\telse if ( !DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv )) {\n\t\t\t\t\tint tCompareResult = lstrcmpiA( dbv.pszVal, buddy_name );\n\t\t\t\t\tDBFreeVariant( &dbv );\n\t\t\t\t\tif ( !tCompareResult ) {\n\t\t\t\t\t\tif (!group_name)\n\t\t\t\t\t\t\tres = g_slist_append(res, hContact);\n\n\t\t\t\t\t\telse if ( !DBGetContactSettingStringUtf(hContact, \"CList\", \"Group\", &dbv )) {\n\t\t\t\t\t\t\tint tCompareResult = lstrcmpiA( dbv.pszVal, group_name );\n\t\t\t\t\t\t\tDBFreeVariant( &dbv );\n\t\t\t\t\t\t\tif ( !tCompareResult )\n\t\t\t\t\t\t\t\tres = g_slist_append(res, hContact);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"Could not get SIP id from contact\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\thContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);\n\t}\n\n\tSIPE_DEBUG_INFO(\"name <%s> group <%s> found <%d> buddies\", buddy_name, group_name, g_slist_length(res));\n\treturn res;\n}\n\nGSList* sipe_backend_buddy_find_all(struct sipe_core_public *sipe_public,\n\t\t\t\t    const gchar *buddy_name,\n\t\t\t\t    const gchar *group_name)\n{\n\treturn sipe_miranda_buddy_find_all(sipe_public->backend_private, buddy_name, group_name);\n}\n\ngchar* sipe_backend_buddy_get_name(struct sipe_core_public *sipe_public,\n\t\t\t\t   const sipe_backend_buddy who)\n{\n\tDBVARIANT dbv;\n\tHANDLE hContact = (HANDLE)who;\n\tgchar *alias;\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tconst gchar *module = pr->proto.m_szModuleName;\n\n\tif ( !DBGetContactSettingString( hContact, module, SIP_UNIQUEID, &dbv )) {\n\t\talias = g_strdup(dbv.pszVal);\n\t\tDBFreeVariant( &dbv );\n\t\treturn alias;\n\t}\n\n\treturn NULL;\n}\n\ngchar* sipe_backend_buddy_get_alias(struct sipe_core_public *sipe_public,\n\t\t\t\t    const sipe_backend_buddy who)\n{\n\tDBVARIANT dbv;\n\tHANDLE hContact = (HANDLE)who;\n\tgchar *alias;\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tconst gchar *module = pr->proto.m_szModuleName;\n\n\tif ( DBGetContactSettingString( hContact, module, \"Nick\", &dbv )\n\t  && DBGetContactSettingString( hContact, module, \"Alias\", &dbv )\n\t  && DBGetContactSettingString( hContact, module, SIP_UNIQUEID, &dbv ))\n\t\t\treturn NULL;\n\n\talias = g_strdup(dbv.pszVal);\n\tDBFreeVariant( &dbv );\n\treturn alias;\n}\n\ngchar* sipe_backend_buddy_get_server_alias(struct sipe_core_public *sipe_public,\n\t\t\t\t\t   const sipe_backend_buddy who)\n{\n\tDBVARIANT dbv;\n\tHANDLE hContact = (HANDLE)who;\n\tchar *alias;\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tconst gchar *module = pr->proto.m_szModuleName;\n\n\tif ( !DBGetContactSettingString( hContact, module, \"Alias\", &dbv )) {\n\t\talias = g_strdup(dbv.pszVal);\n\t\tDBFreeVariant( &dbv );\n\t\treturn alias;\n\t}\n\n\treturn NULL;\n}\n\ngchar* sipe_backend_buddy_get_local_alias(struct sipe_core_public *sipe_public,\n\t\t\t\t\t   const sipe_backend_buddy who)\n{\n\tDBVARIANT dbv;\n\tHANDLE hContact = (HANDLE)who;\n\tchar *alias;\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tconst gchar *module = pr->proto.m_szModuleName;\n\n\tif ( DBGetContactSettingString( hContact, module, \"Nick\", &dbv )\n\t  && DBGetContactSettingString( hContact, module, SIP_UNIQUEID, &dbv ))\n\t\t\treturn NULL;\n\n\talias = g_strdup(dbv.pszVal);\n\tDBFreeVariant( &dbv );\n\treturn alias;\n}\n\ngchar* sipe_backend_buddy_get_group_name(struct sipe_core_public *sipe_public,\n\t\t\t\t\t const sipe_backend_buddy who)\n{\n\tDBVARIANT dbv;\n\tHANDLE hContact = (HANDLE)who;\n\tgchar *alias;\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tconst gchar *module = pr->proto.m_szModuleName;\n\n\tif ( !DBGetContactSettingString( hContact, \"CList\", \"Group\", &dbv )) {\n\t\talias = g_strdup(dbv.pszVal);\n\t\tDBFreeVariant( &dbv );\n\t\treturn alias;\n\t}\n\n\treturn NULL;\n}\n\nguint sipe_backend_buddy_get_status(struct sipe_core_public *sipe_public,\n\t\t\t\t\t   const gchar *uri)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tsipe_backend_buddy buddy = sipe_backend_buddy_find(sipe_public, uri, NULL);\n\tWORD rv = SIPE_ACTIVITY_UNSET;\n\n\tsipe_miranda_getWord(pr, buddy, \"Status\", &rv);\n\treturn MirandaStatusToSipe(rv);\n}\n\nvoid sipe_backend_buddy_set_alias(struct sipe_core_public *sipe_public,\n\t\t\t\t  const sipe_backend_buddy who,\n\t\t\t\t  const gchar *alias)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tHANDLE hContact = (HANDLE)who;\n\n\tSIPE_DEBUG_INFO(\"Set alias of contact <%08x> to <%s>\", who, alias);\n\tsipe_miranda_setContactStringUtf( pr, hContact, \"Nick\", alias );\n}\n\nvoid sipe_backend_buddy_set_server_alias(struct sipe_core_public *sipe_public,\n\t\t\t\t\t const sipe_backend_buddy who,\n\t\t\t\t\t const gchar *alias)\n{\n\tHANDLE hContact = (HANDLE)who;\n\tSIPPROTO *pr = sipe_public->backend_private;\n\n\tSIPE_DEBUG_INFO(\"Set alias of contact <%08x> to <%s>\", who, alias);\n\tsipe_miranda_setContactStringUtf( pr, hContact, \"Alias\", alias );\n}\n\ngchar* sipe_backend_buddy_get_string(struct sipe_core_public *sipe_public,\n\t\t\t\t     sipe_backend_buddy buddy,\n\t\t\t\t     const sipe_buddy_info_fields key)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tconst gchar *module = pr->proto.m_szModuleName;\n\tconst gchar *prop_name = sipe_info_to_miranda_property(key);\n\tchar *tmp;\n\tchar *prop_str;\n\n\tif (!prop_name)\n\t\treturn NULL;\n\n\ttmp = sipe_miranda_getContactString(pr, buddy, prop_name);\n\tprop_str = g_strdup(tmp);\n\tmir_free(tmp);\n\n\treturn prop_str;\n}\n\nvoid sipe_backend_buddy_set_string(struct sipe_core_public *sipe_public,\n\t\t\t\t   sipe_backend_buddy buddy,\n\t\t\t\t   const sipe_buddy_info_fields key,\n\t\t\t\t   const gchar *val)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tconst gchar *module = pr->proto.m_szModuleName;\n\tconst gchar *prop_name = sipe_info_to_miranda_property(key);\n\n\tSIPE_DEBUG_INFO(\"buddy <%08x> key <%d = %s> val <%s>\", buddy, key, prop_name, val);\n\tif (!prop_name)\n\t\treturn;\n\n\tsipe_miranda_setContactString(pr, buddy, prop_name, val);\n}\n\nvoid sipe_backend_buddy_refresh_properties(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t   SIPE_UNUSED_PARAMETER const gchar *uri,\n\t                                   SIPE_UNUSED_PARAMETER last_active)\n{\n\t/* nothing to do here: already taken care of by Miranda */\n}\n\nvoid sipe_backend_buddy_list_processing_start(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public)\n{\n}\n\nvoid sipe_backend_buddy_list_processing_finish(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public)\n{\n}\n\nsipe_backend_buddy sipe_backend_buddy_add(struct sipe_core_public *sipe_public,\n\t\t\t\t\t  const gchar *name,\n\t\t\t\t\t  const gchar *alias,\n\t\t\t\t\t  const gchar *groupname)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tHANDLE hContact;\n\n\tSIPE_DEBUG_INFO(\"Adding miranda contact for buddy <%s> alias <%s> in <%s>\", name, alias, groupname);\n\thContact = ( HANDLE )CallService( MS_DB_CONTACT_ADD, 0, 0 );\n\tCallService( MS_PROTO_ADDTOCONTACT, ( WPARAM )hContact,( LPARAM )pr->proto.m_szModuleName );\n\tsipe_miranda_setContactString( pr, hContact, SIP_UNIQUEID, name ); // name\n\tif (alias) sipe_miranda_setContactStringUtf( pr, hContact, \"Nick\", alias );\n\tDBWriteContactSettingString( hContact, \"CList\", \"Group\", groupname );\n\tsipe_miranda_setContactString( pr, hContact, \"Group\", groupname );\n\treturn (sipe_backend_buddy)hContact;\n}\n\nvoid sipe_backend_buddy_remove(struct sipe_core_public *sipe_public,\n\t\t\t       const sipe_backend_buddy who)\n{\n\tCallService( MS_DB_CONTACT_DELETE, (WPARAM)who, 0 );\n}\n\nvoid sipe_backend_buddy_request_authorization(struct sipe_core_public *sipe_public,\n\t\t\t\t\t      const gchar *who,\n\t\t\t\t\t      const gchar *alias,\n\t\t\t\t\t      gboolean on_list,\n\t\t\t\t\t      sipe_backend_buddy_request_authorization_cb auth_cb,\n\t\t\t\t\t      sipe_backend_buddy_request_authorization_cb deny_cb,\n\t\t\t\t\t      void *data)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tCCSDATA ccs;\n\tPROTORECVEVENT pre = {0};\n\tHANDLE hContact;\n\tBYTE *pblob;\n\n\thContact = sipe_backend_buddy_find( sipe_public, who, NULL );\n\tif (!hContact)\n\t{\n\t\tSIPE_DEBUG_INFO(\"Adding miranda contact for incoming talker <%s>\", who);\n\t\thContact = ( HANDLE )CallService( MS_DB_CONTACT_ADD, 0, 0 );\n\t\tCallService( MS_PROTO_ADDTOCONTACT, ( WPARAM )hContact,( LPARAM )pr->proto.m_szModuleName );\n\t\tDBWriteContactSettingByte( hContact, \"CList\", \"NotOnList\", 1 );\n\t\tsipe_miranda_setContactString( pr, hContact, SIP_UNIQUEID, who ); // name\n\t}\n\n\tccs.szProtoService\t= PSR_AUTH;\n\tccs.hContact\t\t= hContact;\n\tccs.wParam\t\t= 0;\n\tccs.lParam\t\t= (LPARAM) &pre;\n\n\tpre.flags\t\t= PREF_UTF;\n\tpre.timestamp\t\t= time(NULL);\n\tpre.lParam\t\t= sizeof(DWORD)+sizeof(HANDLE)+strlen(who)+strlen(alias)+5;\n\tpre.szMessage\t\t= malloc(pre.lParam);\n\n\tpblob = pre.szMessage;\n\n\t*(DWORD*)pblob = 0; /* UIN */\n\tpblob += sizeof(DWORD);\n\n\t*(HANDLE*)pblob = hContact; /* contact */\n\tpblob += sizeof(HANDLE);\n\n\tstrcpy(pblob, who); /* nick */\n\tpblob += strlen(pblob) + 1;\n\n\tstrcpy(pblob, alias); /* first name */\n\tpblob += strlen(pblob) + 1;\n\n\tstrcpy(pblob, \"\"); /* last name */\n\tpblob += strlen(pblob) + 1;\n\n\tstrcpy(pblob, \"\"); /* email */\n\tpblob += strlen(pblob) + 1;\n\n\tstrcpy(pblob, \"\"); /* msg */\n\tpblob += strlen(pblob) + 1;\n\n\tCallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);\n\n\t_NIF();\n\tauth_cb(data);\n}\n\nvoid sipe_backend_buddy_request_add(struct sipe_core_public *sipe_public,\n\t\t\t\t    const gchar *who,\n\t\t\t\t    const gchar *alias)\n{\n\t_NIF();\n}\n\ngboolean sipe_backend_buddy_is_blocked(struct sipe_core_public *sipe_public,\n\t\t\t\t       const gchar *who)\n{\n\t_NIF();\n\treturn FALSE;\n}\n\nvoid sipe_backend_buddy_set_blocked_status(struct sipe_core_public *sipe_public,\n\t\t\t\t\t   const gchar *who,\n\t\t\t\t\t   gboolean blocked)\n{\n\t_NIF();\n}\n\nvoid sipe_backend_buddy_set_status(struct sipe_core_public *sipe_public,\n\t\t\t\t   const gchar *who,\n\t\t\t\t   guint activity)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tGSList *contacts = sipe_backend_buddy_find_all(sipe_public, who, NULL);\n\n\tCONTACTS_FOREACH(contacts)\n\t\tsipe_miranda_setWord(pr, hContact, \"Status\", SipeStatusToMiranda(activity));\n\tCONTACTS_FOREACH_END;\n\n}\n\ngboolean sipe_backend_buddy_group_add(struct sipe_core_public *sipe_public,\n\t\t\t\t      const gchar *group_name)\n{\n\tTCHAR *mir_group_name = mir_a2t(group_name);\n\tHANDLE hGroup = (HANDLE)CallService(MS_CLIST_GROUPCREATE, 0, (LPARAM)mir_group_name);\n\tmir_free(mir_group_name);\n\treturn (hGroup?TRUE:FALSE);\n}\n\ngboolean sipe_backend_buddy_group_rename(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t SIPE_UNUSED_PARAMETER const gchar *old_name,\n\t\t\t\t\t SIPE_UNUSED_PARAMETER const gchar *new_name)\n{\n\t/* @TODO */\n\treturn(FALSE);\n}\n\nvoid sipe_backend_buddy_group_remove(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t     SIPE_UNUSED_PARAMETER const gchar *group_name)\n{\n\t/* @TODO */\n}\n\nstruct sipe_backend_buddy_info *sipe_backend_buddy_info_start(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public)\n{\n\treturn((struct sipe_backend_buddy_info *)g_hash_table_new_full(NULL,NULL,NULL,g_free));\n}\n\nvoid sipe_backend_buddy_info_add(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t struct sipe_backend_buddy_info *info,\n\t\t\t\t sipe_buddy_info_fields description,\n\t\t\t\t const gchar *value)\n{\n\tg_hash_table_insert((GHashTable*)info, (gpointer)description, g_strdup(value));\n}\n\nvoid sipe_backend_buddy_info_break(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t   struct sipe_backend_buddy_info *info)\n{\n\t/* Nothin to do */\n}\n\nstatic void set_if_defined(SIPPROTO *pr, GHashTable *store, HANDLE hContact, sipe_buddy_info_fields field, char *label)\n{\n\tchar *value = (char *)g_hash_table_lookup(store, (gpointer)field);\n\tif (value)\n\t\tsipe_miranda_setContactStringUtf(pr, hContact, label, value);\n}\n\nvoid sipe_backend_buddy_info_finalize(struct sipe_core_public *sipe_public,\n\t\t\t\t      struct sipe_backend_buddy_info *info,\n\t\t\t\t      const gchar *uri)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tHANDLE hContact = sipe_miranda_buddy_find(pr, uri, NULL); /* (HANDLE) data; */\n\tDBVARIANT dbv;\n\tGHashTable *results = (GHashTable*)info;\n\n\tGHashTableIter iter;\n\tconst char *id, *value;\n\n\tg_hash_table_iter_init( &iter, results);\n\twhile (g_hash_table_iter_next (&iter, (gpointer *)&id, (gpointer *)&value)) {\n\t\tSIPE_DEBUG_INFO(\"miranda_sipe_get_info_cb: user info field <%d> = <%s>\", id, value ? value : \"(none)\");\n\t}\n\tset_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_EMAIL, \"e-mail\");\n\tset_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_CITY, \"City\");\n\tset_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_STATE, \"State\");\n\tset_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_COUNTRY, \"Country\");\n\tset_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_COMPANY, \"Company\");\n\tset_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_JOB_TITLE, \"CompanyPosition\");\n\tset_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_WORK_PHONE, \"CompanyPhone\");\n\tset_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_STREET, \"CompanyStreet\");\n\tset_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_ZIPCODE, \"CompanyZIP\");\n\tset_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_DEPARTMENT, \"CompanyDepartment\");\n\n\tif ( !DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv )) {\n\t\tGString *content = g_string_new(NULL);\n\t\tWORD wstatus;\n\t\tgchar *status;\n/*\t\tGSList *info; */\n\t\tgboolean is_online;\n\n\t\tsipe_miranda_getWord(pr, hContact, \"Status\", &wstatus);\n\t\tstatus = (gchar*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM)wstatus, (LPARAM)GSMDF_PREFIXONLINE);\n\t\tis_online = g_str_has_prefix(status, \"Online: \") || !g_ascii_strcasecmp(status, \"Online\");\n/*\n\t\tinfo = sipe_core_buddy_info(sipe_public,\n\t\t\t\t\t    dbv.pszVal,\n\t\t\t\t\t    g_str_has_prefix(status, \"Online: \") ? status+8 : status,\n\t\t\t\t\t    is_online);\n\n\t\twhile (info) {\n\t\t\tstruct sipe_buddy_info *sbi = info->data;\n\t\t\tg_string_append_printf(content, \"%s: %s\\r\\n\", sbi->label, sbi->text);\n\t\t\tg_free(sbi->text);\n\t\t\tg_free(sbi);\n\t\t\tinfo = g_slist_delete_link(info, info);\n\t\t}\n\t\tsipe_miranda_setContactStringUtf(pr, hContact, \"About\", content->str);\n*/\n\t\tg_string_free(content, TRUE);\n\t}\n\n\tsipe_miranda_SendBroadcast(pr, hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE) 1, (LPARAM) 0);\n}\n\nstruct sipe_backend_buddy_menu *sipe_backend_buddy_menu_start(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public)\n{\n\treturn(NULL);\n}\n\nstruct sipe_backend_buddy_menu *sipe_backend_buddy_menu_add(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t    struct sipe_backend_buddy_menu *menu,\n\t\t\t\t\t\t\t    const gchar *label,\n\t\t\t\t\t\t\t    enum sipe_buddy_menu_type type,\n\t\t\t\t\t\t\t    gpointer parameter)\n{\n\t_NIF();\n\treturn(NULL);\n}\n\nstruct sipe_backend_buddy_menu *sipe_backend_buddy_menu_separator(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t\t  struct sipe_backend_buddy_menu *menu,\n\t\t\t\t\t\t\t\t  const gchar *label)\n{\n\t_NIF();\n\treturn(NULL);\n}\n\nstruct sipe_backend_buddy_menu *sipe_backend_buddy_sub_menu_add(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t\tstruct sipe_backend_buddy_menu *menu,\n\t\t\t\t\t\t\t\tconst gchar *label,\n\t\t\t\t\t\t\t\tstruct sipe_backend_buddy_menu *sub)\n{\n\t_NIF();\n\treturn(NULL);\n}\n\nvoid sipe_backend_buddy_tooltip_add(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t    struct sipe_backend_buddy_tooltip *tooltip,\n\t\t\t\t    const gchar *description,\n\t\t\t\t    const gchar *value)\n{\n\t_NIF();\n}\n\nint sipe_miranda_buddy_delete(SIPPROTO *pr, WPARAM wParam, LPARAM lParam)\n{\n\tDBVARIANT dbv;\n\tHANDLE hContact = (HANDLE)wParam;\n\tchar *name;\n\tchar *groupname;\n\n\tSIPE_DEBUG_INFO(\"Deleting contact <%08x>\", hContact);\n\n\tif ( DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv ))\n\t\treturn 0;\n\n\tname = g_strdup(dbv.pszVal);\n\tDBFreeVariant( &dbv );\n\n\tif ( DBGetContactSettingString( hContact, \"CList\", \"Group\", &dbv ))\n\t{\n\t\tg_free(name);\n\t\treturn 0;\n\t}\n\n\tgroupname = g_strdup(dbv.pszVal);\n\tDBFreeVariant( &dbv );\n\n\tLOCK;\n\tsipe_core_buddy_remove(pr->sip, name, groupname);\n\tUNLOCK;\n\n\treturn 0;\n}\n\nunsigned GetAwayMsgThread(SIPPROTO *pr, HANDLE hContact)\n{\n\tconst gchar *status;\n\tgchar *name = sipe_miranda_getContactString(pr, hContact, SIP_UNIQUEID);\n\tgchar *tmp = NULL;\n\n\tif (!name)\n\t{\n\t\tSIPE_DEBUG_INFO(\"Could not find name for contact <%08x>\", hContact);\n\t\tsipe_miranda_SendProtoAck(pr, hContact, 1, ACKRESULT_FAILED, ACKTYPE_AWAYMSG, NULL);\n\t\treturn 0;\n\t}\n\n\tLOCK;\n\tstatus = sipe_core_buddy_status(pr->sip,\n\t\t\t\t\tname,\n\t\t\t\t\tSIPE_ACTIVITY_BUSYIDLE,\n\t\t\t\t\t\"dummy test string\");\n\tUNLOCK;\n\n\tif (status)\n\t\ttmp = sipe_miranda_eliminate_html(status, strlen(status));\n\n\tsipe_miranda_SendProtoAck(pr, hContact, 1, ACKRESULT_SUCCESS, ACKTYPE_AWAYMSG, tmp);\n\n\tmir_free(tmp);\n\tmir_free(name);\n\treturn 0;\n}\n\nHANDLE\nsipe_miranda_GetAwayMsg( SIPPROTO *pr, HANDLE hContact )\n{\n\tCloseHandle((HANDLE)mir_forkthreadowner(&GetAwayMsgThread, pr, hContact, NULL ));\n\treturn (HANDLE)1;\n}\n\nint\nsipe_miranda_GetInfo( SIPPROTO *pr, HANDLE hContact, int infoType )\n{\n\tDBVARIANT dbv;\n\n\tSIPE_DEBUG_INFO(\"GetInfo: infotype <%x>\", infoType);\n\tif (!pr->sip) return 0;\n\n\tif ( !DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv )) {\n\t\tLOCK;\n\t\tsipe_core_buddy_get_info(pr->sip, dbv.pszVal);\n\t\tUNLOCK;\n\t\tDBFreeVariant( &dbv );\n\t}\n\n\treturn 0;\n}\n\ngboolean sipe_backend_uses_photo(void)\n{\n\treturn FALSE;\n}\n\nvoid sipe_backend_buddy_set_photo(struct sipe_core_public *sipe_public,\n\t\t\t\t  const gchar *who,\n\t\t\t\t  gpointer photo_data,\n\t\t\t\t  gsize data_len,\n\t\t\t\t  const gchar *photo_hash)\n{\n\tg_free(photo_data);\n}\n\nconst gchar *sipe_backend_buddy_get_photo_hash(struct sipe_core_public *sipe_public,\n\t\t\t\t\t       const gchar *who)\n{\n\tconst gchar *result = NULL;\n\treturn result;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-chat.c",
    "content": "/**\n * @file miranda-chat.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2018 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2009 pier11 <pier11@operamail.com>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <windows.h>\n#include <stdio.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"m_chat.h\"\n#include \"m_utils.h\"\n#include \"m_system.h\"\n\n#include \"miranda-private.h\"\n\nvoid sipe_backend_chat_session_destroy(SIPE_UNUSED_PARAMETER struct sipe_backend_chat_session *session)\n{\n\t/* Nothing to do here */\n}\n\nvoid sipe_backend_chat_add(struct sipe_backend_chat_session *backend_session,\n\t\t\t   const gchar *uri,\n\t\t\t   gboolean is_new)\n{\n\tSIPPROTO *pr = backend_session->pr;\n\tstruct sipe_core_public *sipe_public = pr->sip;\n\tgchar *self = sipe_miranda_uri_self(pr);\n\tGCDEST gcd = {0};\n\tGCEVENT gce = {0};\n\tint retval;\n\tHANDLE hContact = sipe_backend_buddy_find( sipe_public, uri, NULL );\n\tgchar *nick = sipe_miranda_getContactString(pr, hContact, \"Nick\");\n\n\tSIPE_DEBUG_INFO(\"sipe_backend_chat_add: Adding user <%s> to chat <%s>\", uri, backend_session->conv);\n\n\tgcd.pszModule = pr->proto.m_szModuleName;\n\tgcd.pszID = backend_session->conv;\n\tgcd.iType = GC_EVENT_JOIN;\n\n\tgce.cbSize = sizeof(gce);\n\tgce.pDest = &gcd;\n\tgce.pszNick = nick;\n\tgce.pszUID = uri;\n\tgce.pszStatus = \"Normal\";\n\tgce.bIsMe = !strcmp(self, uri);\n\n\tg_free(self);\n\tretval = CallService( MS_GC_EVENT, 0, (LPARAM)&gce );\n\tif (retval) {\n\t\tSIPE_DEBUG_WARNING(\"sipe_backend_chat_add: Failed to add user to chat: <%d>\", retval);\n\t}\n\tmir_free(nick);\n}\n\nvoid sipe_backend_chat_close(struct sipe_backend_chat_session *backend_session)\n{\n\tSIPPROTO *pr;\n\tGCEVENT gce = {0};\n\tGCDEST gcd = {0};\n\tstruct sipe_chat_session *session;\n\n\tif (!backend_session)\n\t{\n\t\tSIPE_DEBUG_WARNING_NOFORMAT(\"Attempted to close NULL backend_session\");\n\t\treturn;\n\t}\n\n\tpr = backend_session->pr;\n\n\tgce.cbSize = sizeof(gce);\n\tgce.pDest = &gcd;\n\n\tgcd.pszModule = pr->proto.m_szModuleName;\n\tgcd.pszID = backend_session->conv;\n\tgcd.iType = GC_EVENT_CONTROL;\n\n\tsession = (struct sipe_chat_session*)CallServiceSync( MS_GC_EVENT, SESSION_TERMINATE, (LPARAM)&gce );\n}\n\nstruct sipe_backend_chat_session *sipe_backend_chat_create(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t   struct sipe_chat_session *session,\n\t\t\t\t\t\t\t   const gchar *title,\n\t\t\t\t\t\t\t   const gchar *nick)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tGCSESSION gs;\n\tGCDEST gcd = {0};\n\tGCEVENT gce = {0};\n\tgchar *id = g_strdup(title); /* FIXME: Generate ID */\n\tstruct sipe_backend_chat_session *conv = g_new0(struct sipe_backend_chat_session,1);\n\n\tgs.cbSize = sizeof(gs);\n\tgs.iType = GCW_CHATROOM;\n\tgs.pszModule = pr->proto.m_szModuleName;\n\tgs.pszName = title;\n\tgs.pszID = id;\n\tgs.pszStatusbarText = NULL;\n\tgs.dwFlags = 0;\n\tgs.dwItemData = (DWORD)session;\n\n\tif (CallServiceSync( MS_GC_NEWSESSION, 0, (LPARAM)&gs ))\n\t{\n\t\tSIPE_DEBUG_ERROR(\"Failed to create chat session <%d> <%s>\", id, title);\n\t}\n\n\tgcd.pszModule = pr->proto.m_szModuleName;\n\tgcd.pszID = id;\n\n\tgce.cbSize = sizeof(gce);\n\tgce.pDest = &gcd;\n\n\tgcd.iType = GC_EVENT_ADDGROUP;\n\tgce.pszStatus = \"Normal\";\n\tif (CallService( MS_GC_EVENT, 0, (LPARAM)&gce ))\n\t{\n\t\tSIPE_DEBUG_WARNING_NOFORMAT(\"Failed to add normal status to chat session\");\n\t}\n\n\tgce.pszStatus = \"Presenter\";\n\tif (CallService( MS_GC_EVENT, 0, (LPARAM)&gce ))\n\t{\n\t\tSIPE_DEBUG_WARNING_NOFORMAT(\"Failed to add presenter status to chat session\");\n\t}\n\n\n\tgcd.iType = GC_EVENT_CONTROL;\n\n\tif (CallServiceSync( MS_GC_EVENT, SESSION_INITDONE, (LPARAM)&gce ))\n\t{\n\t\tSIPE_DEBUG_WARNING_NOFORMAT(\"Failed to initdone chat session\");\n\t}\n\tif (CallServiceSync( MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce ))\n\t{\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"Failed to set chat session online\");\n\t}\n\n\tconv->conv = id;\n\tconv->pr = pr;\n\n\treturn conv;\n}\n\ngboolean sipe_backend_chat_find(struct sipe_backend_chat_session *backend_session,\n\t\t\t\tconst gchar *uri)\n{\n\tSIPPROTO *pr = backend_session->pr;\n\tGC_INFO gci = {0};\n\tgchar *context;\n\tconst gchar *user;\n\n\tgci.Flags = BYID | USERS;\n\tgci.pszID = mir_a2t(backend_session->conv);\n\tgci.pszModule = pr->proto.m_szModuleName;\n\n\tif(CallServiceSync( MS_GC_GETINFO, 0, (LPARAM)&gci )) {\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"Failed to get chat user list\");\n\t\treturn FALSE;\n\t}\n\n\tif (!gci.pszUsers)\n\t\treturn FALSE;\n\n\tuser = strtok_s(gci.pszUsers, \" \", &context);\n\twhile (user)\n\t{\n\t\tSIPE_DEBUG_INFO(\"sipe_backend_chat_find: Found user <%s>\", user);\n\t\tif (!strcmp(uri, user)) {\n\t\t\tmir_free(gci.pszUsers);\n\t\t\treturn TRUE;\n\t\t}\n\t\tuser = strtok_s(NULL, \" \", &context);\n\t}\n\n\tmir_free(gci.pszUsers);\n\treturn FALSE;\n}\n\ngboolean sipe_backend_chat_is_operator(struct sipe_backend_chat_session *backend_session,\n\t\t\t\t       const gchar *uri)\n{\n\t_NIF();\n\treturn TRUE;\n}\n\nvoid sipe_backend_chat_message(struct sipe_core_public *sipe_public,\n\t\t\t       struct sipe_backend_chat_session *backend_session,\n\t\t\t       const gchar *from,\n\t\t\t       time_t when,\n\t\t\t       const gchar *html)\n{\n\tSIPPROTO *pr = backend_session->pr;\n\tgchar *self = sipe_miranda_uri_self(pr);\n\tgchar *msg;\n\tGCDEST gcd = {0};\n\tGCEVENT gce = {0};\n\tHANDLE hContact = sipe_backend_buddy_find( sipe_public, from, NULL );\n\tgchar *nick = sipe_miranda_getContactString(pr, hContact, \"Nick\");\n\n\tgcd.pszModule = pr->proto.m_szModuleName;\n\tgcd.pszID = backend_session->conv;\n\tgcd.iType = GC_EVENT_MESSAGE;\n\n\tmsg = sipe_miranda_eliminate_html(html, strlen(html));\n\n\tgce.cbSize = sizeof(gce);\n\tgce.pDest = &gcd;\n\tgce.pszNick = nick;\n\tgce.pszUID = from;\n\tgce.pszText = msg;\n\tgce.bIsMe = !strcmp(self, from);\n//\tgce.time = mtime; // FIXME: Generate timestamp\n\tg_free(self);\n\n\tCallService( MS_GC_EVENT, 0, (LPARAM)&gce );\n\tmir_free(nick);\n\tmir_free(msg);\n}\n\nvoid sipe_backend_chat_operator(struct sipe_backend_chat_session *backend_session,\n\t\t\t\tconst gchar *uri)\n{\n\tSIPPROTO *pr;\n\tGCEVENT gce = {0};\n\tGCDEST gcd = {0};\n\tHANDLE hContact;\n\tgchar *nick;\n\tstruct sipe_core_public *sipe_public;\n\n\tif (!backend_session)\n\t{\n\t\tSIPE_DEBUG_WARNING_NOFORMAT(\"Attempted to set operator on NULL backend_session\");\n\t\treturn;\n\t}\n\n\tpr = backend_session->pr;\n\tsipe_public = pr->sip;\n\n\thContact = sipe_backend_buddy_find( sipe_public, uri, NULL );\n\tnick = sipe_miranda_getContactString(pr, hContact, \"Nick\");\n\n\tgce.cbSize = sizeof(gce);\n\tgce.pDest = &gcd;\n\tgce.pszNick = nick;\n\tgce.pszUID = uri;\n\tgce.pszText = \"Presenter\";\n\tgce.pszStatus = \"Presenter\";\n\n\tgcd.pszModule = pr->proto.m_szModuleName;\n\tgcd.pszID = backend_session->conv;\n\tgcd.iType = GC_EVENT_ADDSTATUS;\n\n\tif (CallServiceSync( MS_GC_EVENT, 0, (LPARAM)&gce ))\n\t{\n\t\tSIPE_DEBUG_WARNING_NOFORMAT(\"Failed to set presenter status\");\n\t}\n\tmir_free(nick);\n}\n\nvoid sipe_backend_chat_rejoin(struct sipe_core_public *sipe_public,\n\t\t\t      struct sipe_backend_chat_session *backend_session,\n\t\t\t      const gchar *nick,\n\t\t\t      const gchar *title)\n{\n\t_NIF();\n}\n\n/**\n * Connection re-established: tell core what chats need to be rejoined\n */\nvoid sipe_backend_chat_rejoin_all(struct sipe_core_public *sipe_public)\n{\n\t_NIF();\n}\n\nvoid sipe_backend_chat_remove(struct sipe_backend_chat_session *backend_session,\n\t\t\t      const gchar *uri)\n{\n\tSIPPROTO *pr = backend_session->pr;\n\tstruct sipe_core_public *sipe_public = pr->sip;\n\tgchar *self = sipe_miranda_uri_self(pr);\n\tGCDEST gcd = {0};\n\tGCEVENT gce = {0};\n\tHANDLE hContact = sipe_backend_buddy_find( sipe_public, uri, NULL );\n\tgchar *nick = sipe_miranda_getContactString(pr, hContact, \"Nick\");\n\n\tSIPE_DEBUG_INFO(\"sipe_backend_chat_remove: Removing user <%s> from chat <%s>\", uri, backend_session->conv);\n\n\tgcd.pszModule = pr->proto.m_szModuleName;\n\tgcd.pszID = backend_session->conv;\n\tgcd.iType = GC_EVENT_PART;\n\n\tgce.cbSize = sizeof(gce);\n\tgce.pDest = &gcd;\n\tgce.pszNick = nick;\n\tgce.pszUID = uri;\n\tgce.pszStatus = 0;\n\tgce.bIsMe = !strcmp(self, uri);\n\n\tg_free(self);\n\tCallService( MS_GC_EVENT, 0, (LPARAM)&gce );\n\tmir_free(nick);\n}\n\nvoid sipe_backend_chat_show(struct sipe_backend_chat_session *backend_session)\n{\n\t_NIF();\n}\n\nvoid sipe_backend_chat_topic(struct sipe_backend_chat_session *backend_session,\n\t\t\t      const gchar *topic)\n{\n\tSIPPROTO *pr = backend_session->pr;\n\tGCDEST gcd = {0};\n\tGCEVENT gce = {0};\n\n\tSIPE_DEBUG_INFO(\"sipe_backend_chat_topic: conv <%s> topic <%s>\", backend_session->conv, topic);\n\n\tgcd.pszModule = pr->proto.m_szModuleName;\n\tgcd.pszID = backend_session->conv;\n\tgcd.iType = GC_EVENT_TOPIC;\n\n\tgce.cbSize = sizeof(gce);\n\tgce.pDest = &gcd;\n\tgce.pszNick = NULL;\n\tgce.pszUID = NULL;\n\tgce.pszText = topic;\n\n\tCallService( MS_GC_EVENT, 0, (LPARAM)&gce );\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-connection.c",
    "content": "/**\n * @file miranda-connection.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-11 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <windows.h>\n#include <stdio.h>\n#include <glib.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"miranda-private.h\"\n\nvoid sipe_miranda_connection_destroy(SIPPROTO *pr)\n{\n\tint oldStatus;\n\n\tSIPE_DEBUG_INFO(\"valid <%d> state <%d>\", pr->valid, pr->state);\n\tif (!pr->valid) return;\n\n\tset_buddies_offline(pr);\n\tsipe_miranda_close(pr);\n\tpr->state = SIPE_MIRANDA_DISCONNECTED;\n\tpr->valid = FALSE;\n\n\toldStatus = pr->proto.m_iStatus;\n\tpr->proto.m_iDesiredStatus = ID_STATUS_OFFLINE;\n\tpr->proto.m_iStatus = pr->proto.m_iDesiredStatus;\n\tsipe_miranda_SendBroadcast(pr, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, pr->proto.m_iStatus);\n}\n\nstatic void disconnect_cb(SIPPROTO *pr)\n{\n\tSIPE_DEBUG_INFO_NOFORMAT(\"\");\n\tif (!pr->valid) return;\n\tif (pr->state == SIPE_MIRANDA_DISCONNECTED) return;\n\tpr->disconnecting = TRUE;\n\tsipe_miranda_connection_destroy(pr);\n\tpr->valid = FALSE;\n\tpr->disconnecting = FALSE;\n\tpr->disconnect_timeout = NULL;\n}\n\nvoid sipe_miranda_connection_error_reason(SIPPROTO *pr, sipe_connection_error error, const gchar *msg)\n{\n\tif (!pr->disconnect_timeout)\n\t{\n\t\tSIPE_DEBUG_INFO(\"valid <%d> state <%d> error <%d> message <%s>\", pr->valid, pr->state, error, msg);\n\t\tpr->disconnect_timeout = sipe_miranda_schedule_mseconds(disconnect_cb, 1000, pr);\n\t}\n}\n\nvoid sipe_backend_connection_completed(struct sipe_core_public *sipe_public)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tint oldStatus = pr->proto.m_iStatus;\n\tpr->state = SIPE_MIRANDA_CONNECTED;\n\tpr->proto.m_iStatus = pr->proto.m_iDesiredStatus;\n\tsipe_miranda_SendBroadcast(pr, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, pr->proto.m_iStatus);\n}\n\nvoid sipe_backend_connection_error(struct sipe_core_public *sipe_public,\n\t\t\t\t   sipe_connection_error error,\n\t\t\t\t   const gchar *msg)\n{\n\tSIPE_DEBUG_INFO(\"reason <%d> message <%s>\", error, msg);\n\tsipe_miranda_connection_error_reason(sipe_public->backend_private, error, msg);\n}\n\ngboolean sipe_backend_connection_is_disconnecting(struct sipe_core_public *sipe_public)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\treturn (pr->disconnecting);\n}\n\ngboolean sipe_backend_connection_is_valid(struct sipe_core_public *sipe_public)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\treturn (pr->state == SIPE_MIRANDA_CONNECTED);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-debug.c",
    "content": "/**\n * @file miranda-debug.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <windows.h>\n#include <process.h>\n#include <stdio.h>\n\n#include <glib.h>\n\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"m_netlib.h\"\n\n#include \"sipe-backend.h\"\n#include \"miranda-private.h\"\n\nextern HANDLE sipe_miranda_incoming_netlibuser;\nextern CRITICAL_SECTION sipe_miranda_debug_CriticalSection;\n\nvoid sipe_backend_debug_literal(sipe_debug_level level,\n\t\t\t\tconst gchar *message)\n{\n\tif (sipe_miranda_incoming_netlibuser)\n\t{\n\t\tgchar *msg = g_strdup_printf(\"[%5d] %s\", GetCurrentThreadId(), message);\n\t\tEnterCriticalSection(&sipe_miranda_debug_CriticalSection);\n\t\tCallService(MS_NETLIB_LOG, (WPARAM)sipe_miranda_incoming_netlibuser, (LPARAM)msg);\n\t\tLeaveCriticalSection(&sipe_miranda_debug_CriticalSection);\n\t\tg_free(msg);\n\t}\n}\n\nvoid sipe_backend_debug(sipe_debug_level level,\n\t\t\tconst gchar *format,\n\t\t\t...) G_GNUC_PRINTF(2, 3)\n{\n\tva_list ap;\n\n\tva_start(ap,format);\n\n\tif ((level < SIPE_DEBUG_LEVEL_LOWEST) || sipe_backend_debug_enabled()) {\n\t\tgchar *msg = g_strdup_vprintf(format, ap);\n\t\tsipe_backend_debug_literal(level, msg);\n\t\tg_free(msg);\n\t}\n\n\tva_end(ap);\n}\n\ngboolean sipe_backend_debug_enabled(void)\n{\n\treturn TRUE;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-dnsquery.c",
    "content": "/**\n * @file miranda-dnsquery.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-12 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <windows.h>\n#include <win2k.h>\n#include <stdio.h>\n#include <windns.h>\n\n#include <glib.h>\n\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"m_utils.h\"\n\n#include \"sipe-backend.h\"\n#include \"miranda-private.h\"\n\ntypedef DNS_STATUS (WINAPI *DNSQUERYA)(IN PCSTR pszName, IN WORD wType, IN DWORD Options, IN PIP4_ARRAY aipServers OPTIONAL, IN OUT PDNS_RECORD *ppQueryResults OPTIONAL, IN OUT PVOID *pReserved OPTIONAL);\ntypedef void (WINAPI *DNSFREELIST)(IN OUT PDNS_RECORD pRecordList, IN DNS_FREE_TYPE FreeType);\n\ntypedef struct srv_reply_t {\n        char *host;\n        int port;\n} srv_reply;\n\nstatic srv_reply* srv_lookup(WORD wType,\n\t\t\t     const gchar* service,\n\t\t\t     const gchar* protocol,\n\t\t\t     const gchar* domain )\n{\n\tsrv_reply *res = NULL;\n\tHINSTANCE hDnsapi = LoadLibraryA( \"dnsapi.dll\" );\n\tDNSQUERYA pDnsQuery;\n\tDNSFREELIST pDnsRecordListFree;\n\tgchar temp[256];\n\tDNS_RECORD *results = NULL;\n\tDNS_STATUS status;\n\n\tif ( hDnsapi == NULL )\n\t\treturn res;\n\n\tpDnsQuery = (DNSQUERYA)GetProcAddress(hDnsapi, \"DnsQuery_A\");\n\tpDnsRecordListFree = (DNSFREELIST)GetProcAddress(hDnsapi, \"DnsRecordListFree\");\n\tif ( pDnsQuery == NULL ) {\n\t\t//dnsapi.dll is not the needed dnsapi ;)\n\t\tFreeLibrary( hDnsapi );\n\t\treturn res;\n\t}\n\n\tmir_snprintf( temp, SIZEOF(temp), \"_%s._%s.%s\", service, protocol, domain );\n\n\tstatus = pDnsQuery(temp, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &results, NULL);\n\tif (FAILED(status)||!results || results[0].Data.Srv.pNameTarget == 0||results[0].wType != DNS_TYPE_SRV) {\n\t\tFreeLibrary(hDnsapi);\n\t\treturn res;\n\t}\n\n\tres = g_new0(srv_reply,1);\n\tres->host = g_strdup((const gchar*)results[0].Data.Srv.pNameTarget);\n\tres->port = (int)results[0].Data.Srv.wPort;\n\n\tpDnsRecordListFree(results, DnsFreeRecordList);\n\tFreeLibrary(hDnsapi);\n\treturn res;\n}\n\n\nstruct sipe_dns_query *sipe_backend_dns_query_a(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\tconst gchar *hostname,\n\t\t\t\t\t\tguint port,\n\t\t\t\t\t\tsipe_dns_resolved_cb callback,\n\t\t\t\t\t\tgpointer data)\n{\n\tsrv_reply* sr = srv_lookup( DNS_TYPE_A, \"protocol\", \"transport\", \"domain\" );\n\tSIPE_DEBUG_INFO(\"Type A lookup for host <%s> port <%d>\", hostname, port);\n\n\tif (sr) {\n\t\tcallback( data, sr->host, sr->port);\n\n\t\tg_free(sr->host);\n\t\tg_free(sr);\n\t} else {\n\t\tcallback( data, NULL, 0);\n\t}\n\n\treturn NULL;\n}\n\nstruct sipe_dns_query *sipe_backend_dns_query_srv(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t  const gchar *protocol,\n\t\t\t\t\t\t  const gchar *transport,\n\t\t\t\t\t\t  const gchar *domain,\n\t\t\t\t\t\t  sipe_dns_resolved_cb callback,\n\t\t\t\t\t\t  gpointer data)\n{\n\tsrv_reply* sr = srv_lookup( DNS_TYPE_SRV, protocol, transport, domain );\n\n\tSIPE_DEBUG_INFO(\"Type SRV lookup for proto <%s> transport <%s> domain <%s>\",\n\t\t\tprotocol, transport, domain);\n\n\tif (sr) {\n\t\tcallback( data, sr->host, sr->port);\n\n\t\tg_free(sr->host);\n\t\tg_free(sr);\n\t} else {\n\t\tcallback( data, NULL, 0);\n\t}\n\n\treturn NULL;\n}\n\nvoid sipe_backend_dns_query_cancel(struct sipe_dns_query *query)\n{\n\t_NIF();\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-ft.c",
    "content": "/**\n * @file miranda-ft.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2018 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2010 Jakub Adam <jakub.adam@ktknet.cz>\n * Copyright (C) 2010 Tomáš Hrabčík <tomas.hrabcik@tieto.com>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <winsock2.h>\n#include <windows.h>\n#include <stdio.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n\n#include <glib.h>\n#include <glib/gstdio.h>\n\n#include \"miranda-version.h\"\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"m_database.h\"\n#include \"m_protomod.h\"\n#include \"m_netlib.h\"\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"miranda-private.h\"\n\n#define FT_SIPE_DEBUG_INFO(fmt, ...)        sipe_backend_debug(SIPE_DEBUG_LEVEL_INFO,    \"[FT:%08x] %s: \" fmt, ft, __func__, __VA_ARGS__)\n#define FT_SIPE_DEBUG_INFO_NOFORMAT(msg)    sipe_backend_debug(SIPE_DEBUG_LEVEL_INFO,    \"[FT:%08x] %s: %s\", ft, __func__, msg)\n\n#define FT_INITIAL_BUFFER_SIZE 4096\n#define FT_MAX_BUFFER_SIZE     65535\n\ntypedef enum\n{\n\tSIPE_MIRANDA_XFER_STATUS_UNKNOWN = 0,   /**< Unknown, the xfer may be null. */\n//        SIPE_MIRANDA_XFER_STATUS_NOT_STARTED,   /**< It hasn't started yet. */\n//        SIPE_MIRANDA_XFER_STATUS_ACCEPTED,      /**< Receive accepted, but destination file not selected yet */\n\tSIPE_MIRANDA_XFER_STATUS_STARTED,       /**< purple_xfer_start has been called. */\n\tSIPE_MIRANDA_XFER_STATUS_DONE,          /**< The xfer completed successfully. */\n\tSIPE_MIRANDA_XFER_STATUS_CANCEL_LOCAL,  /**< The xfer was cancelled by us. */\n        SIPE_MIRANDA_XFER_STATUS_CANCEL_REMOTE  /**< The xfer was cancelled by the other end, or we couldn't connect. */\n} sipe_miranda_xfer_status;\n\nstruct sipe_backend_file_transfer {\n\tgboolean incoming;\n\tHANDLE fd;\n\tSIPPROTO *pr;\n\tstruct sipe_file_transfer *ft;\n\tgsize file_size;\n\tsize_t bytes_sent;\n\tsize_t bytes_remaining;\n\tsize_t current_buffer_size;\n\tstruct sipe_miranda_sel_entry *watcher;\n\tgchar *filename;\n\tgchar *local_filename;\n\tFILE *dest_fp;\n\tHANDLE hContact;\n\ttime_t start_time;\n\ttime_t end_time;\n\tGByteArray *buffer;\n\tPROTOFILETRANSFERSTATUS st;\n\tsipe_miranda_xfer_status status;\n};\n\nstatic void\nupdate_progress(struct sipe_backend_file_transfer *xfer)\n{\n#if 0\n        ZeroMemory(pfts, sizeof(PROTOFILETRANSFERSTATUS));\n        pfts->flags = PFTS_UTF | (ft->sending ? PFTS_SENDING : PFTS_RECEIVING); /* Standard FT is Ansi only */\n        if (ft->sending)\n                pfts->pszFiles = ft->pszFiles;\n        else\n                pfts->pszFiles = NULL;  /* FIXME */\n        pfts->currentFileTime = ft->dwThisFileDate;\n\n#endif\n\txfer->st.flags = (xfer->incoming ? PFTS_RECEIVING : PFTS_SENDING);\n\txfer->st.szWorkingDir = \"none\";\n\txfer->st.szCurrentFile = xfer->filename;\n\txfer->st.totalFiles = 1;\n\txfer->st.totalBytes = xfer->file_size;\n\txfer->st.totalProgress = xfer->bytes_sent;\n\txfer->st.currentFileNumber = 1;\n\txfer->st.currentFileSize = xfer->file_size;\n\txfer->st.currentFileProgress = xfer->bytes_sent;\n\n\tProtoBroadcastAck(xfer->pr->proto.m_szModuleName,\n\t\t\t  xfer->hContact,\n\t\t\t  ACKTYPE_FILE,\n\t\t\t  ACKRESULT_DATA,\n\t\t\t  (HANDLE)xfer,\n\t\t\t  (LPARAM)&xfer->st);\n}\n\nstatic void\nincrease_buffer_size(struct sipe_backend_file_transfer *xfer)\n{\n\txfer->current_buffer_size = MIN(xfer->current_buffer_size * 1.5,\n\t\t\tFT_MAX_BUFFER_SIZE);\n}\n\nvoid sipe_backend_ft_error(struct sipe_file_transfer *ft,\n\t\t\t   const gchar *errmsg)\n{\n\tgchar *msg;\n\n\tFT_SIPE_DEBUG_INFO(\"file transfer error: <%s>\", errmsg);\n\n\tif (ft->backend_private->incoming)\n\t{\n\t\tmsg = g_strdup_printf(\"Incoming file transfer failed\");\n\t} else {\n\t\tmsg = g_strdup_printf(\"Outgoing file transfer failed\");\n\t}\n\n\tsipe_miranda_AddEvent(ft->backend_private->pr, ft->backend_private->hContact, SIPE_EVENTTYPE_ERROR_NOTIFY, time(NULL), DBEF_UTF, strlen(msg), (PBYTE)msg);\n\tg_free(msg);\n\n}\n\nconst gchar *sipe_backend_ft_get_error(SIPE_UNUSED_PARAMETER struct sipe_file_transfer *ft)\n{\n\t_NIF();\n\treturn strerror(errno); /* FIXME: Only valid for the file side i think */\n}\n\nstatic void\nfree_xfer_struct(struct sipe_backend_file_transfer *xfer)\n{\n\tstruct sipe_file_transfer *ft = xfer->ft;\n\n\tif (ft) {\n\t\tif (xfer->watcher) {\n\t\t\tsipe_miranda_input_remove(xfer->watcher);\n\t\t\txfer->watcher = 0;\n\t\t}\n\t\tif (ft->deallocate) {\n\t\t\tft->deallocate(ft);\n\t\t}\n\t\txfer->ft = NULL;\n\t}\n}\n\nstatic void\ncancel_remote(struct sipe_backend_file_transfer *xfer)\n{\n\tstruct sipe_file_transfer *ft = xfer->ft;\n\tgchar *msg;\n\tFT_SIPE_DEBUG_INFO_NOFORMAT(\"\");\n\n\tif (!xfer) return;\n\n\txfer->status = SIPE_MIRANDA_XFER_STATUS_CANCEL_REMOTE;\n        xfer->end_time = time(NULL);\n\n\tmsg = g_strdup_printf(\"File transfer cancelled by peer\");\n\tsipe_miranda_AddEvent(ft->backend_private->pr, ft->backend_private->hContact, SIPE_EVENTTYPE_ERROR_NOTIFY, time(NULL), DBEF_UTF, strlen(msg), (PBYTE)msg);\n\tg_free(msg);\n\n\tfree_xfer_struct(xfer);\n\n\tif (xfer->watcher != 0) {\n\t\tsipe_miranda_input_remove(xfer->watcher);\n\t\txfer->watcher = 0;\n\t}\n\n\tif (xfer->fd)\n\t\tNetlib_CloseHandle(xfer->fd);\n\n\tif (xfer->dest_fp != NULL) {\n\t\tfclose(xfer->dest_fp);\n\t\txfer->dest_fp = NULL;\n\t}\n\n\txfer->bytes_remaining = 0;\n\tg_free(xfer->filename);\n/*\tg_free(xfer);  FIXME: needs refcounting like purple i guess */\n}\n\nvoid sipe_backend_ft_deallocate(struct sipe_file_transfer *ft)\n{\n\tstruct sipe_backend_file_transfer *xfer = ft->backend_private;\n\n\t/* If file transfer is not finished, cancel it */\n\tif (xfer->status != SIPE_MIRANDA_XFER_STATUS_DONE\n\t    && xfer->status != SIPE_MIRANDA_XFER_STATUS_CANCEL_LOCAL\n\t    && xfer->status != SIPE_MIRANDA_XFER_STATUS_CANCEL_REMOTE)\n\t{\n\t\tcancel_remote(xfer);\n        }\n\n}\n\ngssize sipe_backend_ft_read(struct sipe_file_transfer *ft,\n\t\t\t    guchar *data,\n\t\t\t    gsize size)\n{\n\tgssize bytes_read;\n\n\tFT_SIPE_DEBUG_INFO(\"reading up to <%d> bytes\", size);\n\tbytes_read = Netlib_Recv(ft->backend_private->fd, data, size, MSG_NODUMP);\n\tFT_SIPE_DEBUG_INFO(\"came back from read <%d>\", bytes_read);\n\tif (bytes_read == 0) {\n\t\t/* Sender canceled transfer before it was finished */\n\t\tFT_SIPE_DEBUG_INFO_NOFORMAT(\"no read cause sender cancelled\");\n\t\treturn -2;\n\t} else if (bytes_read == SOCKET_ERROR) {\n\t\tint err = WSAGetLastError();\n\t\tif (err == WSAEWOULDBLOCK) {\n\t\t\treturn 0;\n\t\t} else {\n\t\t\tFT_SIPE_DEBUG_INFO(\"Error reading <%d>\", err);\n\t\t\treturn -1;\n\t\t}\n\t}\n\tFT_SIPE_DEBUG_INFO(\"read <%d> bytes [%02x:%c]\", bytes_read, *data, *data);\n\treturn bytes_read;\n}\n\ngssize sipe_backend_ft_write(struct sipe_file_transfer *ft,\n\t\t\t     const guchar *data,\n\t\t\t     gsize size)\n{\n\tint bytes_written;\n\tFT_SIPE_DEBUG_INFO(\"writing <%d> bytes\", size);\n\tbytes_written = Netlib_Send(ft->backend_private->fd, data, size, MSG_NODUMP );\n\tif (bytes_written == SOCKET_ERROR) {\n\t\tint err = WSAGetLastError();\n\t\tif (err == WSAEWOULDBLOCK) {\n\t\t\treturn 0;\n\t\t} else {\n\t\t\tFT_SIPE_DEBUG_INFO(\"Error writing <%u>\", err);\n\t\t\treturn -1;\n\t\t}\n\t}\n\tFT_SIPE_DEBUG_INFO(\"wrote <%d> bytes\", bytes_written);\n\treturn bytes_written;\n}\n\nstatic void\ncancel_local(struct sipe_backend_file_transfer *xfer)\n{\n\tstruct sipe_file_transfer *ft = xfer->ft;\n\tgchar *msg;\n\tFT_SIPE_DEBUG_INFO_NOFORMAT(\"\");\n\n\txfer->status = SIPE_MIRANDA_XFER_STATUS_CANCEL_LOCAL;\n\txfer->end_time = time(NULL);\n\n\tmsg = g_strdup_printf(\"File transfer cancelled\");\n\tsipe_miranda_AddEvent(ft->backend_private->pr, ft->backend_private->hContact, SIPE_EVENTTYPE_ERROR_NOTIFY, time(NULL), DBEF_UTF, strlen(msg), (PBYTE)msg);\n\tg_free(msg);\n\n\tfree_xfer_struct(xfer);\n\n\tif (xfer->watcher != 0) {\n\t\tsipe_miranda_input_remove(xfer->watcher);\n\t\txfer->watcher = 0;\n\t}\n\n\tif (xfer->fd)\n\t\tNetlib_CloseHandle(xfer->fd);\n\n\tif (xfer->dest_fp != NULL) {\n\t\tfclose(xfer->dest_fp);\n\t\txfer->dest_fp = NULL;\n\t}\n\n\txfer->bytes_remaining = 0;\n\n\tg_free(xfer->filename);\n\tg_free(xfer);\n}\n\nvoid sipe_backend_ft_set_completed(struct sipe_file_transfer *ft)\n{\n\t_NIF();\n}\n\nvoid sipe_backend_ft_cancel_local(struct sipe_file_transfer *ft)\n{\n\tcancel_local(ft->backend_private);\n}\n\nvoid sipe_backend_ft_cancel_remote(struct sipe_file_transfer *ft)\n{\n\tcancel_remote(ft->backend_private);\n}\n\nstatic struct sipe_backend_file_transfer *\nnew_xfer(SIPPROTO *pr,\n\t struct sipe_file_transfer *ft,\n\t HANDLE hContact)\n{\n\tstruct sipe_backend_file_transfer *xfer = g_new0(struct sipe_backend_file_transfer, 1);\n\n\txfer->current_buffer_size = FT_INITIAL_BUFFER_SIZE;\n\txfer->buffer = g_byte_array_sized_new(FT_INITIAL_BUFFER_SIZE);\n\txfer->ft = ft;\n\txfer->hContact = hContact;\n\txfer->pr = pr;\n\n\txfer->st.cbSize = sizeof(PROTOFILETRANSFERSTATUS);\n\txfer->st.hContact = hContact;\n\n\treturn xfer;\n}\n\nvoid sipe_backend_ft_incoming(struct sipe_core_public *sipe_public,\n\t\t\t      struct sipe_file_transfer *ft,\n\t\t\t      const gchar *who,\n\t\t\t      const gchar *file_name,\n\t\t\t      gsize file_size)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tPROTORECVFILET pre = {0};\n\tCCSDATA ccs;\n\tHANDLE hContact;\n\n\tFT_SIPE_DEBUG_INFO(\"Incoming ft <%08x> from <%s> file <%s> size <%d>\", ft, who, file_name, file_size);\n\thContact = sipe_backend_buddy_find( sipe_public, who, NULL );\n\tif (!hContact)\n\t{\n\t\tFT_SIPE_DEBUG_INFO(\"Adding miranda contact for incoming transfer from <%s>\", who);\n\t\thContact = ( HANDLE )CallService( MS_DB_CONTACT_ADD, 0, 0 );\n\t\tCallService( MS_PROTO_ADDTOCONTACT, ( WPARAM )hContact,( LPARAM )pr->proto.m_szModuleName );\n\t\tDBWriteContactSettingByte( hContact, \"CList\", \"NotOnList\", 1 );\n\t\tsipe_miranda_setContactString( pr, hContact, SIP_UNIQUEID, who ); // name\n\t}\n\n\tft->backend_private = new_xfer(pr, ft, hContact);\n\tft->backend_private->incoming = TRUE;\n\tft->backend_private->file_size = file_size;\n\tft->backend_private->bytes_remaining = file_size;\n\tft->backend_private->bytes_sent = 0;\n\tft->backend_private->filename = g_strdup(file_name);\n\n\tpre.flags = PREF_TCHAR;\n\tpre.timestamp = time(NULL);\n\tpre.tszDescription = mir_a2t(file_name);\n\tpre.fileCount = 1;\n\tpre.ptszFiles = &pre.tszDescription;\n\tpre.lParam = (LPARAM)ft;\n\n        ccs.szProtoService = PSR_FILE;\n        ccs.hContact = hContact;\n        ccs.wParam = 0;\n        ccs.lParam = (LPARAM)&pre;\n        CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);\n\n}\n\nvoid\nsipe_backend_ft_outgoing(struct sipe_core_public *sipe_public,\n\t\t\t struct sipe_file_transfer *ft,\n\t\t\t const gchar *who,\n\t\t\t const gchar *file_name)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tHANDLE hContact;\n\tint result;\n\tstruct __stat64 buf;\n\n\tLOCK;\n\thContact = sipe_backend_buddy_find( sipe_public, who, NULL );\n\tft->backend_private = new_xfer(pr, ft, hContact);\n\tft->backend_private->incoming = FALSE;\n\tresult = _tstat64( file_name, &buf );\n\tif (result != 0)\n\t{\n\t\tFT_SIPE_DEBUG_INFO(\"Could not stat file, error<%d>\", result);\n\t\tft->backend_private->file_size = 0;\n\t}\n\telse\n\t{\n\t\tft->backend_private->file_size = buf.st_size;\n\t\tft->backend_private->bytes_remaining = ft->backend_private->file_size;\n\t\tft->backend_private->bytes_sent = 0;\n\t}\n\tft->backend_private->local_filename = g_strdup(file_name);\n\tft->backend_private->filename = g_path_get_basename(ft->backend_private->local_filename);\n\tFT_SIPE_DEBUG_INFO(\"set filename to <%s>\", ft->backend_private->filename);\n\tft->init(ft, ft->backend_private->filename, ft->backend_private->file_size, who);\n\tsipe_miranda_SendBroadcast(pr, hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, (HANDLE)ft->backend_private, 0);\n\tUNLOCK;\n}\n\ngboolean\nsipe_backend_ft_incoming_accept(struct sipe_file_transfer *ft,\n\t\t\t\tconst gchar *ip,\n\t\t\t\tunsigned short port_min,\n\t\t\t\tunsigned short port_max)\n{\n\t_NIF();\n\treturn FALSE;\n}\n\nstatic void\nset_completed(struct sipe_backend_file_transfer *xfer, gboolean completed)\n{\n\tif (completed == TRUE) {\n\t\tchar *msg = NULL;\n\n\t\txfer->status = SIPE_MIRANDA_XFER_STATUS_DONE;\n\n\t\tif (xfer->filename != NULL)\n\t\t{\n\t\t\tchar *filename = g_markup_escape_text(xfer->filename, -1);\n\t\t\tif (xfer->local_filename && xfer->incoming)\n\t\t\t{\n\t\t\t\tchar *local = g_markup_escape_text(xfer->local_filename, -1);\n\t\t\t\tmsg = g_strdup_printf(\"Transfer of file <A HREF=\\\"file://%s\\\">%s</A> complete\",\n\t\t\t\t                      local, filename);\n\t\t\t\tg_free(local);\n\t\t\t}\n\t\t\telse\n\t\t\t\tmsg = g_strdup_printf(\"Transfer of file %s complete\",\n\t\t\t\t                      filename);\n\t\t\tg_free(filename);\n\t\t}\n\t\telse\n\t\t\tmsg = g_strdup(\"File transfer complete\");\n\n\t\tsipe_miranda_AddEvent(xfer->pr, xfer->hContact, SIPE_EVENTTYPE_ERROR_NOTIFY, time(NULL), DBEF_UTF, strlen(msg), (PBYTE)msg);\n\t\tsipe_miranda_SendBroadcast(xfer->pr, xfer->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, (HANDLE)xfer, 0);\n\n\t\tg_free(msg);\n\t}\n\n\tupdate_progress(xfer);\n}\n\nstatic void\ndo_transfer(struct sipe_backend_file_transfer *xfer)\n{\n\n\tguchar *buffer = NULL;\n\tgssize r = 0;\n\tstruct sipe_file_transfer *ft = xfer->ft;\n\n\tFT_SIPE_DEBUG_INFO(\"incoming <%d>\", xfer->incoming);\n\tif (xfer->incoming) {\n\t\tFT_SIPE_DEBUG_INFO_NOFORMAT(\"incoming branch\");\n\t\tr = ft->read(xfer->ft, &buffer, xfer->bytes_remaining,\n\t\t\t     xfer->current_buffer_size);\n\t\tif (r > 0) {\n\t\t\tsize_t wc;\n\t\t\twc = fwrite(buffer, 1, r, xfer->dest_fp);\n\n\t\t\tif (wc != r) {\n\t\t\t\tSIPE_DEBUG_ERROR(\"Unable to write whole buffer.\");\n\t\t\t\tcancel_local(xfer);\n\t\t\t\tg_free(buffer);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ((xfer->file_size > 0) && ((xfer->bytes_sent+r) >= xfer->file_size))\n\t\t\t\tset_completed(xfer, TRUE);\n\n\t\t} else if(r < 0) {\n\t\t\tcancel_remote(xfer);\n\t\t\tg_free(buffer);\n\t\t\treturn;\n\t\t}\n\t} else {\n\t\tsize_t result = 0;\n\t\tsize_t s = MIN(xfer->bytes_remaining, xfer->current_buffer_size);\n\t\tgboolean read = TRUE;\n\t\tFT_SIPE_DEBUG_INFO(\"outgoing branch, size <%u>\", s);\n\n\t\t/* this is so the prpl can keep the connection open\n\t\t   if it needs to for some odd reason. */\n\t\tif (s == 0) {\n\t\t\tif (xfer->watcher) {\n\t\t\t\tsipe_miranda_input_remove(xfer->watcher);\n\t\t\t\txfer->watcher = 0;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (xfer->buffer) {\n\t\t\tif (xfer->buffer->len < s) {\n\t\t\t\ts -= xfer->buffer->len;\n\t\t\t\tread = TRUE;\n\t\t\t} else {\n\t\t\t\tread = FALSE;\n\t\t\t}\n\t\t}\n\n\t\tif (read) {\n\t\t\tbuffer = g_malloc(s);\n\t\t\tresult = fread(buffer, 1, s, xfer->dest_fp);\n\t\t\tif (result != s) {\n\t\t\t\tFT_SIPE_DEBUG_INFO_NOFORMAT(\"Unable to read whole buffer.\");\n\t\t\t\tcancel_local(xfer);\n\t\t\t\tg_free(buffer);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (xfer->buffer) {\n\t\t\tg_byte_array_append(xfer->buffer, buffer, result);\n\t\t\tg_free(buffer);\n\t\t\tbuffer = xfer->buffer->data;\n\t\t\tresult = xfer->buffer->len;\n\t\t}\n\n\t\ts = MIN(xfer->bytes_remaining, result);\n\t\tr = ft->write(ft, buffer, s);\n\n\t\tif ((xfer->bytes_remaining - r) == 0)\n\t\t\tset_completed(xfer, TRUE);\n\n\t\tif (r >= 0 && (xfer->bytes_sent+r) >= xfer->file_size && xfer->status != SIPE_MIRANDA_XFER_STATUS_DONE)\n\t\t\tset_completed(xfer, TRUE);\n\n\t\tif (r == -1) {\n\t\t\tcancel_remote(xfer);\n\n\t\t\tif (!xfer->buffer)\n\t\t\t\t/* We don't free buffer if priv->buffer is set, because in\n\t\t\t\t   that case buffer doesn't belong to us. */\n\t\t\t\tg_free(buffer);\n\t\t\treturn;\n\t\t} else if (r == result) {\n\t\t\t/*\n\t\t\t * We managed to write the entire buffer.  This means our\n\t\t\t * network is fast and our buffer is too small, so make it\n\t\t\t * bigger.\n\t\t\t */\n\t\t\tincrease_buffer_size(xfer);\n\t\t}\n\n\t\tif (xfer->buffer) {\n\t\t\t/*\n\t\t\t * Remove what we wrote\n\t\t\t * If we wrote the whole buffer the byte array will be empty\n\t\t\t * Otherwise we'll keep what wasn't sent for next time.\n\t\t\t */\n\t\t\tbuffer = NULL;\n\t\t\tg_byte_array_remove_range(xfer->buffer, 0, r);\n\t\t}\n\t}\n\n\tFT_SIPE_DEBUG_INFO_NOFORMAT(\"back to common code\");\n\tif (r > 0) {\n\t\tif (xfer->file_size > 0)\n\t\t\txfer->bytes_remaining -= r;\n\n\t\txfer->bytes_sent += r;\n\n\t\tg_free(buffer);\n\t\tupdate_progress(xfer);\n\t}\n\n\tif (xfer->status == SIPE_MIRANDA_XFER_STATUS_DONE)\n\t{\n\t\txfer->end_time = time(NULL);\n\t\tif (xfer->ft->end && xfer->ft->end(xfer->ft)) {\n\t\t\t/* We're done with this transfer */\n\t\t\tfree_xfer_struct(xfer);\n\t\t} else if (xfer->incoming) {\n\t\t\t_unlink(xfer->local_filename);\n\t\t}\n\n\t\tif (xfer->watcher != 0) {\n\t\t\tsipe_miranda_input_remove(xfer->watcher);\n\t\t\txfer->watcher = 0;\n\t\t}\n\n\t\tif (xfer->fd)\n\t\t\tNetlib_CloseHandle(xfer->fd);\n\n\t\tif (xfer->dest_fp != NULL) {\n\t\t\tfclose(xfer->dest_fp);\n\t\t\txfer->dest_fp = NULL;\n\t\t}\n\n\t\tg_free(xfer->filename);\n\t\tg_free(xfer);\n\t}\n}\n\nstatic void\ntransfer_cb(gpointer data, gint source, sipe_miranda_input_condition condition)\n{\n\tstruct sipe_backend_file_transfer *xfer = data;\n\tSIPE_DEBUG_INFO_NOFORMAT(\"\");\n\tdo_transfer(xfer);\n}\n\nstatic void\nbegin_transfer(struct sipe_file_transfer *ft)\n{\n\tstruct sipe_backend_file_transfer *xfer = ft->backend_private;\n\tSIPPROTO *pr = xfer->pr;\n\n\txfer->dest_fp = fopen(xfer->local_filename, xfer->incoming ? \"wb\" : \"rb\");\n\tif (xfer->dest_fp == NULL) {\n\t\tint err = errno;\n\t\tgchar *msg;\n\t\tif (xfer->incoming)\n\t\t{\n\t\t\tmsg = g_strdup_printf(\"Error reading %s: \\n%s.\\n\", xfer->local_filename, g_strerror(err));\n\t\t} else {\n\t\t\tmsg = g_strdup_printf(\"Error writing %s: \\n%s.\\n\", xfer->local_filename, g_strerror(err));\n\t\t}\n\t\tsipe_miranda_AddEvent(ft->backend_private->pr, ft->backend_private->hContact, SIPE_EVENTTYPE_ERROR_NOTIFY, time(NULL), DBEF_UTF, strlen(msg), (PBYTE)msg);\n\t\tg_free(msg);\n\t\tFT_SIPE_DEBUG_INFO(\"error opening local file: %s\",  g_strerror(errno));\n\t\tcancel_local(xfer);\n\t\treturn;\n\t}\n\n\tfseek(xfer->dest_fp, xfer->bytes_sent, SEEK_SET);\n\n\txfer->start_time = time(NULL);\n\n\tLOCK;\n\tFT_SIPE_DEBUG_INFO(\"incoming <%d> size <%d>\", ft->backend_private->incoming, ft->backend_private->file_size);\n\tif (!ft->backend_private->incoming) {\n\t\t/* Set socket to nonblocking */\n\t\tSOCKET sock = CallService(MS_NETLIB_GETSOCKET, (WPARAM)xfer->fd, (LPARAM)0);\n\t\tunsigned long parm = 1;\n\n\t\tif (ioctlsocket(sock, FIONBIO, &parm) == SOCKET_ERROR)\n\t\t{\n\t\t\tFT_SIPE_DEBUG_INFO(\"Error ioctlsocket <%d>\", WSAGetLastError());\n\t\t}\n\t\t\n\t\tFT_SIPE_DEBUG_INFO(\"outgoing ft <%08x> size <%d>\", ft, ft->backend_private->file_size);\n\t}\n\tif (ft->start) {\n\t\tft->start(ft, ft->backend_private->file_size);\n\t}\n\tUNLOCK;\n\n\tif (xfer->fd)\n\t\txfer->watcher = sipe_miranda_input_add(xfer->fd, xfer->incoming?SIPE_MIRANDA_INPUT_READ:SIPE_MIRANDA_INPUT_WRITE, transfer_cb, xfer);\n\n\tFT_SIPE_DEBUG_INFO(\"watcher [%08x]\", xfer->watcher);\n}\n\nstatic void\nft_connected_callback(HANDLE fd, void* data, const gchar *reason)\n{\n\tstruct sipe_file_transfer *ft = (struct sipe_file_transfer *)data;\n\tstruct sipe_backend_file_transfer *xfer = ft->backend_private;\n\tSIPPROTO *pr = ft->backend_private->pr;\n\n\tif (!fd)\n\t{\n\t\tcancel_local(xfer);\n\t} else {\n\t\tft->backend_private->fd = fd;\n\t\tbegin_transfer(ft);\n\t}\n\n}\n\nvoid\nsipe_backend_ft_start(struct sipe_file_transfer *ft, struct sipe_backend_fd *fd,\n                      const char* ip, unsigned port)\n{\n\tft->backend_private->status = SIPE_MIRANDA_XFER_STATUS_STARTED;\n\n\tif (ip && port)\n\t{\n\t\tFT_SIPE_DEBUG_INFO(\"Should connect to <%s:%d>\", ip, port);\n\t\tsipe_miranda_connect(ft->backend_private->pr, ip, port, FALSE, 5, ft_connected_callback, ft);\n\t\treturn;\n\t}\n\n\tFT_SIPE_DEBUG_INFO(\"Should use incoming fd <%08x>\", fd);\n\tft->backend_private->fd = fd;\n\tbegin_transfer(ft);\n}\n\ngboolean\nsipe_backend_ft_is_incoming(struct sipe_file_transfer *ft)\n{\n\tFT_SIPE_DEBUG_INFO(\"ft <%08x> incoming <%d>\", ft, ft->backend_private->incoming);\n\treturn ft->backend_private->incoming;\n}\n\nHANDLE\nsipe_miranda_SendFile( SIPPROTO *pr, HANDLE hContact, const PROTOCHAR* szDescription, PROTOCHAR** ppszFiles )\n{\n\tDBVARIANT dbv;\n\n\tif ( !DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv )) {\n\t\tstruct sipe_file_transfer *ft;\n\n\t\tft = sipe_core_ft_create_outgoing(pr->sip, dbv.pszVal, TCHAR2CHAR(ppszFiles[0]));\n\n\t\tFT_SIPE_DEBUG_INFO(\"SendFile: desc <%ls> name <%s> size <%d> to <%s>\", szDescription, TCHAR2CHAR(ppszFiles[0]), ft->backend_private->file_size, dbv.pszVal);\n\n\t\tDBFreeVariant( &dbv );\n\n\t\treturn ft->backend_private;\n\t}\n\n\treturn NULL;\n}\n\nint\nsipe_miranda_RecvFile( SIPPROTO *pr, HANDLE hContact, PROTOFILEEVENT* evt )\n{\n        CCSDATA ccs = { hContact, PSR_FILE, 0, (LPARAM)evt };\n        return CallService(MS_PROTO_RECVFILET, 0, (LPARAM)&ccs);\n}\n\nHANDLE\nsipe_miranda_FileAllow( SIPPROTO *pr, HANDLE hContact, HANDLE hTransfer, const PROTOCHAR* szPath )\n{\n\tstruct sipe_file_transfer *ft = (struct sipe_file_transfer *)hTransfer;\n\tFT_SIPE_DEBUG_INFO(\"Incoming ft <%08x> allowed\", ft);\n\tft->backend_private->local_filename = g_strdup_printf(\"%s%s\", TCHAR2CHAR(szPath), ft->backend_private->filename);\n\tsipe_miranda_SendBroadcast(pr, hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, (HANDLE)ft->backend_private, 0);\n\tft->init(ft, ft->backend_private->filename, ft->backend_private->file_size, NULL);\n\treturn ft->backend_private;\n}\n\nint\nsipe_miranda_FileDeny( SIPPROTO *pr, HANDLE hContact, HANDLE hTransfer, const PROTOCHAR* szReason )\n{\n\tstruct sipe_file_transfer *ft = (struct sipe_file_transfer *)hTransfer;\n\tFT_SIPE_DEBUG_INFO(\"FileDeny: reason <%s>\", szReason);\n\tif (ft->backend_private->incoming && ft->request_denied)\n\t\tft->request_denied(ft);\n\tfree_xfer_struct(ft->backend_private);\n\treturn 0;\n}\n\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-groupchat.c",
    "content": "/**\n * @file miranda-groupchat.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <windows.h>\n#include <stdio.h>\n\n#include <glib.h>\n\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"m_chat.h\"\n\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"miranda-private.h\"\n\nvoid sipe_backend_groupchat_room_add(struct sipe_core_public *sipe_public,\n\t\t\t\t     const gchar *uri,\n\t\t\t\t     const gchar *name,\n\t\t\t\t     const gchar *description,\n\t\t\t\t     guint users,\n\t\t\t\t     guint32 flags)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tGCSESSION gs;\n\tGCEVENT gce = {0};\n\tGCDEST gcd = {0};\n\n\tgs.cbSize = sizeof(gs);\n\tgs.iType = GCW_CHATROOM;\n\tgs.pszModule = pr->proto.m_szModuleName;\n\tgs.pszName = name;\n\tgs.pszID = uri;\n\tgs.pszStatusbarText = description;\n\tgs.dwFlags = 0;\n\tgs.dwItemData = 0;\n\n\tif (CallServiceSync( MS_GC_NEWSESSION, 0, (LPARAM)&gs ))\n\t{\n\t\tSIPE_DEBUG_ERROR(\"sipe_backend_groupchat_room_add: Failed to create chat session <%d> <%s>\", uri, name);\n\t}\n\n\tgcd.pszModule = pr->proto.m_szModuleName;\n\tgcd.pszID = uri;\n\n\tgce.cbSize = sizeof(gce);\n\tgce.pDest = &gcd;\n\n\tgcd.iType = GC_EVENT_CONTROL;\n\t\n\tif (CallService( MS_GC_EVENT, 0, (LPARAM)&gce ))\n\t{\n\t\tSIPE_DEBUG_WARNING_NOFORMAT(\"sipe_backend_groupchat_room_add: Failed to add normal status to chat session\");\n\t}\n\n\tgce.pszStatus = \"Presenter\";\n\tif (CallService( MS_GC_EVENT, 0, (LPARAM)&gce ))\n\t{\n\t\tSIPE_DEBUG_WARNING_NOFORMAT(\"sipe_backend_groupchat_room_add: Failed to add presenter status to chat session\");\n\t}\n\n\n\tgcd.iType = GC_EVENT_CONTROL;\n\n\tif (CallServiceSync( MS_GC_EVENT, SESSION_INITDONE, (LPARAM)&gce ))\n\t{\n\t\tSIPE_DEBUG_WARNING_NOFORMAT(\"sipe_backend_groupchat_room_add: Failed to initdone chat session\");\n\t}\n\tif (CallServiceSync( MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce ))\n\t{\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_backend_groupchat_room_add: Failed to set chat session online\\n\");\n\t}\n\n}\n\nvoid sipe_backend_groupchat_room_terminate(struct sipe_core_public *sipe_public)\n{\n\t_NIF();\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-im.c",
    "content": "/**\n * @file miranda-im.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-11 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <windows.h>\n#include <stdio.h>\n\n#include <glib.h>\n\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"m_system.h\"\n#include \"m_database.h\"\n#include \"m_protomod.h\"\n\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"miranda-private.h\"\n\nvoid sipe_backend_im_message(struct sipe_core_public *sipe_public,\n\t\t\t     const gchar *from,\n\t\t\t     const gchar *html)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\n\tCCSDATA ccs;\n\tPROTORECVEVENT pre = {0};\n\tHANDLE hContact;\n\tgchar *msg;\n\n\thContact = sipe_backend_buddy_find( sipe_public, from, NULL );\n\tif (!hContact)\n\t{\n\t\tSIPE_DEBUG_INFO(\"Adding miranda contact for incoming talker <%s>\", from);\n\t\thContact = ( HANDLE )CallService( MS_DB_CONTACT_ADD, 0, 0 );\n\t\tCallService( MS_PROTO_ADDTOCONTACT, ( WPARAM )hContact,( LPARAM )pr->proto.m_szModuleName );\n\t\tDBWriteContactSettingByte( hContact, \"CList\", \"NotOnList\", 1 );\n\t\tsipe_miranda_setContactString( pr, hContact, SIP_UNIQUEID, from ); // name\n\t}\n\n\tmsg = sipe_miranda_eliminate_html(html, strlen(html));\n\n\tpre.szMessage = msg;\n//\tpre.flags = PREF_UTF + (isRtl ? PREF_RTL : 0);\n\tpre.timestamp = (DWORD)time(NULL);\n\tpre.lParam = 0;\n\n\tccs.szProtoService = PSR_MESSAGE;\n\tccs.hContact = hContact;\n\tccs.wParam = 0;\n\tccs.lParam = (LPARAM)&pre;\n\tCallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);\n\n\tmir_free(msg);\n\n}\n\nint sipe_miranda_SendMsg(SIPPROTO *pr,\n\t\t\t HANDLE hContact,\n\t\t\t int flags,\n\t\t\t const char* msg )\n{\n\tDBVARIANT dbv;\n\n\tSIPE_DEBUG_INFO(\"SendMsg: flags <%x> msg <%s>\", flags, msg);\n\n\tif ( !DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv )) {\n\t\tLOCK;\n\t\tsipe_core_im_send(pr->sip, dbv.pszVal, msg);\n\t\tUNLOCK;\n\t\tsipe_miranda_SendProtoAck( pr, hContact, 1, ACKRESULT_SUCCESS, ACKTYPE_MESSAGE, NULL );\n\t\tDBFreeVariant(&dbv);\n\t} else {\n\t\tsipe_miranda_SendProtoAck( pr, hContact, 1, ACKRESULT_FAILED, ACKTYPE_MESSAGE, NULL );\n\t}\n\treturn 1;\n}\n\nint sipe_miranda_RecvMsg(SIPPROTO *pr,\n\t\t\t HANDLE hContact,\n\t\t\t PROTORECVEVENT* pre)\n{\n//\tchar *msg = EliminateHtml( pre->szMessage, strlen(pre->szMessage));\n//\tmir_free(pre->szMessage);\n//\tpre->szMessage = msg;\n\n\tCCSDATA ccs = { hContact, PSR_MESSAGE, 0, ( LPARAM )pre };\n\treturn CallService( MS_PROTO_RECVMSG, 0, ( LPARAM )&ccs );\n}\n\nvoid sipe_backend_im_topic(struct sipe_core_public *sipe_public,\n\t\t\t   const gchar *with,\n\t\t\t   const gchar *topic)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tHANDLE hContact;\n\n\thContact = sipe_backend_buddy_find( sipe_public, with, NULL );\n\tif (!hContact)\n\t{\n\t\t_NIF();\n\t} else {\n\t\tsipe_miranda_AddEvent(pr, hContact, SIPE_EVENTTYPE_IM_TOPIC, time(NULL), DBEF_UTF, strlen(topic), (PBYTE)topic);\n\t}\n\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-input.c",
    "content": "/**\n * @file miranda-input.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-11 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n#include <windows.h>\n#include <stdio.h>\n\n#include <glib.h>\n\n#include \"sipe-backend.h\"\n\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"m_netlib.h\"\n#include \"miranda-private.h\"\n\n#define ENTRY_SIG 0x88442211\n\nstatic NETLIBSELECTEX m_select = {0};\nstatic GHashTable *m_readhash = NULL;\nstatic GHashTable *m_writehash = NULL;\nstatic GList *m_entries = NULL;\n\ntypedef struct sipe_miranda_sel_entry\n{\n\tint sig;\n\tHANDLE fd;\n\tsipe_miranda_input_function func;\n\tgpointer user_data;\n\tgboolean async;\n\n\t/* Private. For locking only */\n\tHANDLE hDoneEvent;\n\tgint source;\n\tsipe_miranda_input_condition cond;\n};\n\nstatic void __stdcall\ninput_cb_async(void *data)\n{\n\tstruct sipe_miranda_sel_entry *entry = (struct sipe_miranda_sel_entry*)data;\n\tif (entry->fd == NULL)\n\t{\n\t\tSIPE_DEBUG_INFO(\"[IE:%08x] Entry already removed. Not calling read/write function\", entry);\n\t} else {\n\t\tSIPE_DEBUG_INFO(\"[IE:%08x] Calling real read/write function\", entry);\n\t\tentry->func(entry->user_data, entry->source, entry->cond);\n\t}\n\tSetEvent(entry->hDoneEvent);\n}\n\nstatic unsigned __stdcall\ninputloop(void* data)\n{\n\tint cnt;\n\tstruct sipe_miranda_sel_entry *entry;\n\tINT_PTR lstRes;\n\n\tm_select.cbSize = sizeof(m_select);\n\tm_select.dwTimeout = 6000;\n\n\twhile( m_select.hReadConns[0] || m_select.hWriteConns[0])\n\t{\n\t\tint rc=0;\n\t\tint wc=0;\n\t\tfor ( rc=0 ; m_select.hReadConns[rc] ; rc++ );\n\t\tfor ( wc=0 ; m_select.hWriteConns[wc] ; wc++ );\n\n\t\tSIPE_DEBUG_INFO(\"About to run select on <%d> read and <%d> write\", rc, wc);\n\t\tlstRes = CallService(MS_NETLIB_SELECTEX, 0, (LPARAM)&m_select);\n\n\t\tif (lstRes < 0)\n\t\t{\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"Connection failed while waiting.\");\n\t\t\tbreak;\n\t\t}\n\t\telse if (lstRes == 0)\n\t\t{\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"Select Timeout.\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"Back from select\");\n\n\t\t\tfor ( cnt=0 ; m_select.hReadConns[cnt] ; cnt++ )\n\t\t\t{\n\t\t\t\tDWORD wr;\n\t\t\t\tif (!m_select.hReadStatus[cnt]) continue;\n\t\t\t\tSIPE_DEBUG_INFO(\"FD at position <%d> ready to read.\", cnt);\n\t\t\t\tentry = (struct sipe_miranda_sel_entry*)g_hash_table_lookup(m_readhash, (gconstpointer)m_select.hReadConns[cnt]);\n\t\t\t\tif (!entry)\n\t\t\t\t{\n\t\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"ERROR: no read handler found.\");\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tSIPE_DEBUG_INFO(\"[IE:%08x] About to call read function.\", entry);\n\t\t\t\tentry->source = (gint)m_select.hReadConns[cnt];\n\t\t\t\tentry->cond = SIPE_MIRANDA_INPUT_READ;\n\t\t\t\tentry->hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\n\t\t\t\tif (entry->async)\n\t\t\t\t{\n\t\t\t\t\tCallFunctionAsync(input_cb_async, entry);\n\t\t\t\t\twr = WaitForSingleObject(entry->hDoneEvent, INFINITE);\n\t\t\t\t} else {\n\t\t\t\t\tinput_cb_async(entry);\n\t\t\t\t}\n\t\t\t\tCloseHandle(entry->hDoneEvent);\n\t\t\t\tSIPE_DEBUG_INFO(\"[IE:%08x] read function returned.\", entry);\n\t\t\t}\n\n\t\t\tfor ( cnt=0 ; m_select.hWriteConns[cnt] ; cnt++ )\n\t\t\t{\n\t\t\t\tif (!m_select.hWriteStatus[cnt]) continue;\n\t\t\t\tSIPE_DEBUG_INFO(\"FD at position <%d> ready to write.\", cnt);\n\t\t\t\tentry = (struct sipe_miranda_sel_entry*)g_hash_table_lookup(m_writehash, (gconstpointer)m_select.hWriteConns[cnt]);\n\t\t\t\tif (!entry)\n\t\t\t\t{\n\t\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"ERROR: no write handler found.\");\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tSIPE_DEBUG_INFO(\"[IE:%08x] About to call write function.\", entry);\n\t\t\t\tentry->source = (gint)m_select.hWriteConns[cnt];\n\t\t\t\tentry->cond = SIPE_MIRANDA_INPUT_WRITE;\n\t\t\t\tentry->hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\n\t\t\t\tif (entry->async)\n\t\t\t\t{\n\t\t\t\t\tCallFunctionAsync(input_cb_async, entry);\n\t\t\t\t\tWaitForSingleObject(entry->hDoneEvent, INFINITE);\n\t\t\t\t} else {\n\t\t\t\t\tinput_cb_async(entry);\n\t\t\t\t}\n\t\t\t\tCloseHandle(entry->hDoneEvent);\n\t\t\t\tSIPE_DEBUG_INFO(\"[IE:%08x] write function returned.\", entry);\n\t\t\t}\n\t\t}\n\n\t\t/* Free all removed entries */\n\t\twhile (m_entries) g_list_delete_link(m_entries, g_list_last(m_entries));\n\t}\n\n\treturn 0;\n}\n\nstruct sipe_miranda_sel_entry*\nsipe_miranda_input_add(HANDLE fd, sipe_miranda_input_condition cond, sipe_miranda_input_function func, gpointer user_data)\n{\n\tint rcnt = 0;\n\tint wcnt = 0;\n\tstruct sipe_miranda_sel_entry *entry;\n\n\tif (!m_readhash)\n\t\tm_readhash = g_hash_table_new(NULL, NULL);\n\n\tif (!m_writehash)\n\t\tm_writehash = g_hash_table_new(NULL, NULL);\n\n\tif ((cond != SIPE_MIRANDA_INPUT_READ) && (cond != SIPE_MIRANDA_INPUT_WRITE))\n\t{\n\t\tSIPE_DEBUG_INFO(\"Invalid input condition <%d> cond.\", cond);\n\t\treturn 0;\n\t}\n\n\tentry = g_new0(struct sipe_miranda_sel_entry,1);\n\tentry->sig = ENTRY_SIG;\n\tentry->func = func;\n\tentry->user_data = user_data;\n\tentry->fd = fd;\n\tentry->async = FALSE;\n\n\tif (cond == SIPE_MIRANDA_INPUT_READ)\n\t{\n\t\tfor ( wcnt=0 ; m_select.hWriteConns[wcnt] ; wcnt++ );\n\t\tfor ( rcnt=0 ; m_select.hReadConns[rcnt] && m_select.hReadConns[rcnt]!=(HANDLE)fd ; rcnt++ );\n\t\tg_hash_table_replace( m_readhash, (gpointer)fd, entry );\n\t\tm_select.hReadStatus[rcnt] = FALSE;\n\t\tm_select.hReadConns[rcnt] = (HANDLE)fd;\n\t}\n\telse if (cond == SIPE_MIRANDA_INPUT_WRITE)\n\t{\n\t\tfor ( rcnt=0 ; m_select.hReadConns[rcnt] ; rcnt++ );\n\t\tfor ( wcnt=0 ; m_select.hWriteConns[wcnt] && m_select.hWriteConns[wcnt]!=(HANDLE)fd ; wcnt++ );\n\t\tg_hash_table_replace( m_writehash, (gpointer)fd, entry );\n\t\tm_select.hWriteStatus[rcnt] = FALSE;\n\t\tm_select.hWriteConns[rcnt] = (HANDLE)fd;\n\t}\n\n\tif (!(rcnt+wcnt))\n\t\tCloseHandle((HANDLE) mir_forkthreadex( inputloop, NULL, 8192, NULL ));\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"Added input handler.\");\n\treturn entry;\n}\n\ngboolean\nsipe_miranda_input_remove(struct sipe_miranda_sel_entry *entry)\n{\n\tint cnt;\n\n\tif (!entry)\n\t{\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"Not a valid entry. NULL.\");\n\t\treturn FALSE;\n\t}\n\n\tif (entry->sig != ENTRY_SIG)\n\t{\n\t\tSIPE_DEBUG_INFO(\"Not a valid entry. Sig is <%08x>.\", entry->sig);\n\t\treturn FALSE;\n\t}\n\n\tif (g_hash_table_lookup(m_readhash, (gconstpointer)entry->fd) == entry)\n\t{\n\t\tfor ( cnt=0 ; m_select.hReadConns[cnt] && m_select.hReadConns[cnt]!=(HANDLE)entry->fd ; cnt++ );\n\t\tfor ( ; m_select.hReadConns[cnt] ; cnt++ ) m_select.hReadConns[cnt] = m_select.hReadConns[cnt+1];\n\t\tg_hash_table_remove(m_readhash, (gconstpointer)entry->fd);\n\t}\n\n\tif (g_hash_table_lookup(m_writehash, (gconstpointer)entry->fd) == entry)\n\t{\n\t\tfor ( cnt=0 ; m_select.hWriteConns[cnt] && m_select.hWriteConns[cnt]!=(HANDLE)entry->fd ; cnt++ );\n\t\tfor ( ; m_select.hWriteConns[cnt] ; cnt++ ) m_select.hWriteConns[cnt] = m_select.hWriteConns[cnt+1];\n\t\tg_hash_table_remove(m_writehash, (gconstpointer)entry->fd);\n\t}\n\n\t/* Set fd to NULL so we won't try to call the callback if we're\n\t   currently waiting to get back to the main thread */\n\tentry->fd = NULL;\n\n\t/* Add it to the list of entries that can be freed after the next select\n\t * loop in the thread that's handling the actual select\n\t */\n\tg_list_append( m_entries, entry );\n\n\treturn TRUE;\n}\n\n\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-markup.c",
    "content": "/**\n * @file miranda-markup.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-11 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include \"glib.h\"\n\n#include <string.h>\n\n#include \"sipe-backend.h\"\n\ngchar *sipe_backend_markup_css_property(const gchar *style,\n\t\t\t\t\tconst gchar *opt)\n{\n\tconst gchar *css_str = style;\n\tconst gchar *css_value_start;\n\tconst gchar *css_value_end;\n\tgchar *tmp;\n\tgchar *ret;\n\n\tg_return_val_if_fail(opt != NULL, NULL);\n\n\tif (!css_str)\n\t\treturn NULL;\n\n\t/* find the CSS property */\n\twhile (1)\n\t{\n\t\t/* skip whitespace characters */\n\t\twhile (*css_str && g_ascii_isspace(*css_str))\n\t\t\tcss_str++;\n\t\tif (!g_ascii_isalpha(*css_str))\n\t\t\treturn NULL;\n\t\tif (g_ascii_strncasecmp(css_str, opt, strlen(opt)))\n\t\t{\n\t\t\t/* go to next css property positioned after the next ';' */\n\t\t\twhile (*css_str && *css_str != '\"' && *css_str != ';')\n\t\t\t\tcss_str++;\n\t\t\tif(*css_str != ';')\n\t\t\t\treturn NULL;\n\t\t\tcss_str++;\n\t\t}\n\t\telse\n\t\t\tbreak;\n\t}\n\n\t/* find the CSS value position in the string */\n\tcss_str += strlen(opt);\n\twhile (*css_str && g_ascii_isspace(*css_str))\n\t\tcss_str++;\n\tif (*css_str != ':')\n\t\treturn NULL;\n\tcss_str++;\n\twhile (*css_str && g_ascii_isspace(*css_str))\n\t\tcss_str++;\n\tif (*css_str == '\\0' || *css_str == '\"' || *css_str == ';')\n\t\treturn NULL;\n\n\t/* mark the CSS value */\n\tcss_value_start = css_str;\n\twhile (*css_str && *css_str != '\"' && *css_str != ';')\n\t\tcss_str++;\n\tcss_value_end = css_str - 1;\n\n\t/* Removes trailing whitespace */\n\twhile (css_value_end > css_value_start && g_ascii_isspace(*css_value_end))\n\t\tcss_value_end--;\n\n\ttmp = g_strndup(css_value_start, css_value_end - css_value_start + 1);\n//\tret = purple_unescape_html(tmp);\n//\tg_free(tmp);\n\tret = tmp;\n\n\treturn ret;\n}\n\ngchar *sipe_backend_markup_strip_html(const gchar *html)\n{\n\tchar *tmp = g_malloc(strlen(html)+1);\n\tconst char *src;\n\tchar *tgt;\n\tgboolean in_tag = FALSE;\n\n\tfor ( src=html, tgt=tmp ; *src ; src++ )\n\t{\n\t\tif (*src == '<') in_tag = TRUE;\n\t\tif (!in_tag) *tgt++ = *src;\n\t\tif (*src == '>') in_tag = FALSE;\n\t}\n\t*tgt = '\\0';\n\n\ttgt = g_strdup(tmp);\n\tg_free(tmp);\n\treturn tgt;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-media.c",
    "content": "/**\n * @file miranda-media.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <windows.h>\n#include <stdio.h>\n\n#include <glib.h>\n\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"miranda-private.h\"\n\nstruct sipe_backend_media {\n\tint dummy;\n};\n\nstruct sipe_backend_media *\nsipe_backend_media_new(struct sipe_core_public *sipe_public,\n\t\t       struct sipe_media_call *call,\n\t\t       const gchar *participant,\n\t\t       SipeMediaCallFlags flags)\n{\n\tstruct sipe_backend_media *m = g_new0(struct sipe_backend_media,1);\n\n\treturn m;\n}\n\nvoid\nsipe_backend_media_free(struct sipe_backend_media *media)\n{\n\t_NIF();\n}\n\nvoid\nsipe_backend_media_set_cname(struct sipe_backend_media *media, gchar *cname)\n{\n\t_NIF();\n}\n\nstruct sipe_backend_media_relays *\nsipe_backend_media_relays_convert(GSList *media_relays, gchar *username, gchar *password)\n{\n\t_NIF();\n\treturn NULL;\n}\n\nvoid\nsipe_backend_media_relays_free(struct sipe_backend_media_relays *media_relays)\n{\n\t_NIF();\n}\n\nstruct sipe_backend_media_stream *\nsipe_backend_media_add_stream(struct sipe_media_stream *stream,\n\t\t\t      SipeMediaType type,\n\t\t\t      SipeIceVersion ice_version,\n\t\t\t      gboolean initiator,\n\t\t\t      struct sipe_backend_media_relays *media_relays,\n\t\t\t      guint min_port, guint max_port)\n{\n\t_NIF();\n\treturn NULL;\n}\n\nvoid\nsipe_backend_media_add_remote_candidates(struct sipe_media_call *media,\n\t\t\t\t\t struct sipe_media_stream *stream,\n\t\t\t\t\t GList *candidates)\n{\n\t_NIF();\n}\n\ngboolean sipe_backend_media_is_initiator(struct sipe_media_call *media,\n\t\t\t\t\t struct sipe_media_stream *stream)\n{\n\t_NIF();\n\treturn FALSE;\n}\n\ngboolean sipe_backend_media_accepted(struct sipe_backend_media *media)\n{\n\t_NIF();\n\treturn FALSE;\n}\n\ngboolean\nsipe_backend_stream_initialized(struct sipe_media_call *media,\n\t\t\t\tstruct sipe_media_stream *stream)\n{\n\t_NIF();\n\treturn FALSE;\n}\n\nGList *\nsipe_backend_media_stream_get_active_local_candidates(struct sipe_media_stream *stream)\n{\n\t_NIF();\n\treturn NULL;\n}\n\nGList *\nsipe_backend_media_stream_get_active_remote_candidates(struct sipe_media_stream *stream)\n{\n\t_NIF();\n\treturn NULL;\n}\n\nsipe_backend_media_set_encryption_keys(struct sipe_media_call *media,\n\t\t\t\t       struct sipe_media_stream *stream,\n\t\t\t\t       const guchar *encryption_key,\n\t\t\t\t       const guchar *decryption_key)\n{\n\t_NIF();\n}\n\nvoid\nsipe_backend_media_set_require_encryption(struct sipe_media_call *media,\n\t\t\t\t\t  struct sipe_media_stream *stream,\n\t\t\t\t\t  const gboolean require_encryption)\n{\n\t_NIF();\n}\n\nvoid\nsipe_backend_stream_hold(struct sipe_media_call *media,\n\t\t\t struct sipe_media_stream *stream,\n\t\t\t gboolean local)\n{\n\t_NIF();\n}\n\nvoid\nsipe_backend_stream_unhold(struct sipe_media_call *media,\n\t\t\t   struct sipe_media_stream *stream,\n\t\t\t   gboolean local)\n{\n\t_NIF();\n}\n\ngboolean\nsipe_backend_stream_is_held(struct sipe_media_stream *stream)\n{\n\t_NIF();\n\treturn FALSE;\n}\n\nvoid\nsipe_backend_media_stream_end(struct sipe_media_call *media,\n\t\t\t      struct sipe_media_stream *stream)\n{\n\t_NIF();\n}\n\nvoid\nsipe_backend_media_stream_free(struct sipe_backend_media_stream *stream)\n{\n\t_NIF();\n}\n\nstruct sipe_backend_codec *\nsipe_backend_codec_new(int id, const char *name, SipeMediaType type,\n\t\t       guint clock_rate, guint channels)\n{\n\t_NIF();\n\treturn NULL;\n}\n\nvoid\nsipe_backend_codec_free(struct sipe_backend_codec *codec)\n{\n\t_NIF();\n}\n\nint\nsipe_backend_codec_get_id(struct sipe_backend_codec *codec)\n{\n\t_NIF();\n\treturn 0;\n}\n\ngchar *\nsipe_backend_codec_get_name(struct sipe_backend_codec *codec)\n{\n\t_NIF();\n\treturn NULL;\n}\n\nguint\nsipe_backend_codec_get_clock_rate(struct sipe_backend_codec *codec)\n{\n\t_NIF();\n\treturn 0;\n}\n\nvoid\nsipe_backend_codec_add_optional_parameter(struct sipe_backend_codec *codec,\n\t\t\t\t\t  const gchar *name, const gchar *value)\n{\n\t_NIF();\n}\n\nGList *\nsipe_backend_codec_get_optional_parameters(struct sipe_backend_codec *codec)\n{\n\t_NIF();\n\treturn NULL;\n}\n\ngboolean\nsipe_backend_set_remote_codecs(struct sipe_media_call *media,\n\t\t\t       struct sipe_media_stream *stream,\n\t\t\t       GList *codecs)\n{\n\t_NIF();\n\treturn FALSE;\n}\n\nGList*\nsipe_backend_get_local_codecs(struct sipe_media_call *media,\n\t\t\t      struct sipe_media_stream *stream)\n{\n\t_NIF();\n\treturn NULL;\n}\n\nstruct sipe_backend_candidate *\nsipe_backend_candidate_new(const gchar *foundation,\n\t\t\t   SipeComponentType component,\n\t\t\t   SipeCandidateType type, SipeNetworkProtocol proto,\n\t\t\t   const gchar *ip, guint port,\n\t\t\t   const gchar *username,\n\t\t\t   const gchar *password)\n{\n\t_NIF();\n\treturn NULL;\n}\n\nvoid\nsipe_backend_candidate_free(struct sipe_backend_candidate *candidate)\n{\n\t_NIF();\n}\n\ngchar *\nsipe_backend_candidate_get_username(struct sipe_backend_candidate *candidate)\n{\n\t_NIF();\n\treturn NULL;\n}\n\ngchar *\nsipe_backend_candidate_get_password(struct sipe_backend_candidate *candidate)\n{\n\t_NIF();\n\treturn NULL;\n}\n\ngchar *\nsipe_backend_candidate_get_foundation(struct sipe_backend_candidate *candidate)\n{\n\t_NIF();\n\treturn NULL;\n}\n\ngchar *\nsipe_backend_candidate_get_ip(struct sipe_backend_candidate *candidate)\n{\n\t_NIF();\n\treturn NULL;\n}\n\nguint\nsipe_backend_candidate_get_port(struct sipe_backend_candidate *candidate)\n{\n\t_NIF();\n\treturn 0;\n}\n\ngchar *\nsipe_backend_candidate_get_base_ip(struct sipe_backend_candidate *candidate)\n{\n\t_NIF();\n\treturn FALSE;\n}\n\nguint\nsipe_backend_candidate_get_base_port(struct sipe_backend_candidate *candidate)\n{\n\t_NIF();\n\treturn 0;\n}\n\nguint32\nsipe_backend_candidate_get_priority(struct sipe_backend_candidate *candidate)\n{\n\t_NIF();\n\treturn 0;\n}\n\nvoid\nsipe_backend_candidate_set_priority(struct sipe_backend_candidate *candidate, guint32 priority)\n{\n\t_NIF();\n}\n\nSipeComponentType\nsipe_backend_candidate_get_component_type(struct sipe_backend_candidate *candidate)\n{\n\t_NIF();\n\treturn SIPE_COMPONENT_NONE;\n}\n\nSipeCandidateType\nsipe_backend_candidate_get_type(struct sipe_backend_candidate *candidate)\n{\n\t_NIF();\n\treturn SIPE_CANDIDATE_TYPE_ANY;\n}\n\nSipeNetworkProtocol\nsipe_backend_candidate_get_protocol(struct sipe_backend_candidate *candidate)\n{\n\t_NIF();\n\treturn SIPE_NETWORK_PROTOCOL_TCP_ACTIVE;\n}\n\nGList *\nsipe_backend_get_local_candidates(struct sipe_media_call *media,\n\t\t\t\t  struct sipe_media_stream *stream)\n{\n\t_NIF();\n\treturn FALSE;\n}\n\nvoid\nsipe_backend_media_accept(struct sipe_backend_media *media, gboolean local)\n{\n\t_NIF();\n}\n\nvoid\nsipe_backend_media_hangup(struct sipe_backend_media *media, gboolean local)\n{\n\t_NIF();\n}\n\nvoid\nsipe_backend_media_reject(struct sipe_backend_media *media, gboolean local)\n{\n\t_NIF();\n}\n\nSipeEncryptionPolicy\nsipe_backend_media_get_encryption_policy(struct sipe_core_public *sipe_public)\n{\n\treturn SIPE_ENCRYPTION_POLICY_REJECTED;\n}\n\ngssize\nsipe_backend_media_stream_read(struct sipe_media_stream *stream,\n\t\t\t       guint8 *buffer, gsize len)\n{\n\t_NIF();\n}\n\ngssize\nsipe_backend_media_stream_write(struct sipe_media_stream *stream,\n\t\t\t\tguint8 *buffer, gsize len)\n{\n\t_NIF();\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-network.c",
    "content": "/**\n * @file miranda-network.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <windows.h>\n#include <stdio.h>\n\n#include <glib.h>\n\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"m_system.h\"\n#include \"m_netlib.h\"\n\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n#include \"sipe-backend.h\"\n#include \"miranda-private.h\"\n\nextern HANDLE sipe_miranda_incoming_netlibuser;\n\nconst gchar *sipe_miranda_get_local_ip(void)\n{\n\tstruct hostent *localHost = gethostbyname(\"\");\n\treturn inet_ntoa(*(struct in_addr *)*localHost->h_addr_list);\n}\n\nstruct sipe_backend_listendata {\n\tsipe_listen_start_cb listen_cb;\n\tsipe_client_connected_cb connect_cb;\n\tgpointer data;\n\tunsigned short port_min;\n\tunsigned short port_max;\n\n\tHANDLE boundport;\n\tHANDLE fd;\n\tWORD port;\n\n\t/* Private. For locking only */\n\tHANDLE hDoneEvent;\n\tHANDLE hDoneEventL;\n};\n\n\nstatic void __stdcall\nclient_connected_cb_async(void *data)\n{\n\tstruct sipe_backend_listendata *ldata = (struct sipe_backend_listendata *)data;\n\n\tSIPE_DEBUG_INFO(\"[CN:%08x] About to call real connect callback\", ldata);\n\n\tif (ldata->connect_cb)\n                ldata->connect_cb((struct sipe_backend_fd *)ldata->fd, ldata->data);\n\n\t/* Can't close the handle before the SetEvent or we'll deadlock */\n\tSetEvent(ldata->hDoneEvent);\n\t/* MS_NETLIB_CLOSEHANDLE doesn't come back until the accept thread\n\t   is done. That in turn doesn't end until the pfnNewConnectionV2\n\t   function comes back. So we know that client_connected_callback\n\t   will be done and it's safe to free ldata here. */\n\tCallService(MS_NETLIB_CLOSEHANDLE,(WPARAM)ldata->boundport,0);\n        g_free(ldata);\n}\n\nstatic void client_connected_callback(HANDLE hNewConnection, DWORD dwRemoteIP, void *data)\n{\n\tstruct sipe_backend_listendata *ldata = (struct sipe_backend_listendata *)data;\n\n\tSIPE_DEBUG_INFO(\"[CN:%08x] Remote connection from <%08x>\", ldata, dwRemoteIP);\n\n\tldata->fd = hNewConnection;\n\tldata->hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\n\tCallFunctionAsync(client_connected_cb_async, ldata);\n\tWaitForSingleObject(ldata->hDoneEvent, INFINITE);\n\tCloseHandle(ldata->hDoneEvent);\n\n}\n\nstatic void __stdcall\nlisten_cb_async(void *data)\n{\n\tstruct sipe_backend_listendata *ldata = (struct sipe_backend_listendata *)data;\n\tldata->listen_cb(ldata->port, ldata->data);\n\tSetEvent(ldata->hDoneEventL);\n}\n\nstatic unsigned __stdcall listen_callback(void* data)\n{\n\tNETLIBBIND nlb = {0};\n\tNETLIBUSERSETTINGS nls = {0};\n\tWORD iptype;\n\tstruct sipe_backend_listendata *ldata = (struct sipe_backend_listendata *)data;\n\n\tnls.cbSize = sizeof(NETLIBUSERSETTINGS);\n\tCallService(MS_NETLIB_GETUSERSETTINGS, (WPARAM)sipe_miranda_incoming_netlibuser, (LPARAM)&nls);\n\tnls.specifyIncomingPorts = 1;\n\tnls.szIncomingPorts = mir_alloc(20);\n\tmir_snprintf( nls.szIncomingPorts, 20, \"%d-%d\", ldata->port_min, ldata->port_max);\n\tCallService(MS_NETLIB_SETUSERSETTINGS, (WPARAM)sipe_miranda_incoming_netlibuser, (LPARAM)&nls);\n\n\tnlb.cbSize = sizeof(NETLIBBIND);\n\tnlb.pfnNewConnectionV2 = client_connected_callback;\n\tnlb.pExtra = ldata;\n\tSetLastError(ERROR_INVALID_PARAMETER); // this must be here - NetLib does not set any error :((\n\n\tldata->boundport = (HANDLE)CallService(MS_NETLIB_BINDPORT, (WPARAM)sipe_miranda_incoming_netlibuser, (LPARAM)&nlb);\n\tldata->port = nlb.wPort;\n\n\tsipe_miranda_getGlobalWord(\"iptype\", &iptype);\n\tif (iptype == SIPE_MIRANDA_IP_PROG)\n\t{\n\t\tgchar rc[20];\n\t\tDWORD bytesread = sizeof(rc);\n\t\tgchar *cmd = sipe_miranda_getGlobalString(\"ipprog\");\n\t\tgchar *cmdline = g_strdup_printf(\"%s listen %d\", cmd, nlb.wPort);\n\t\tmir_free(cmd);\n\n\t\tif (!sipe_miranda_cmd(cmdline, rc, &bytesread))\n\t\t{\n\t\t\tSIPE_DEBUG_INFO(\"Could not run child program <%s> (%d)\", cmdline, GetLastError());\n\t\t}\n\t}\n\n\tif (ldata->listen_cb)\n\t{\n\t\tldata->hDoneEventL = CreateEvent(NULL, FALSE, FALSE, NULL);\n\t\tCallFunctionAsync(listen_cb_async, ldata);\n\t\tWaitForSingleObject(ldata->hDoneEventL, INFINITE);\n\t\tCloseHandle(ldata->hDoneEventL);\n\t}\n\n\treturn 0;\n}\n\nstruct sipe_backend_listendata *\nsipe_backend_network_listen_range(unsigned short port_min,\n\t\t\t\t  unsigned short port_max,\n\t\t\t\t  sipe_listen_start_cb listen_cb,\n\t\t\t\t  sipe_client_connected_cb connect_cb,\n\t\t\t\t  gpointer data)\n{\n\tstruct sipe_backend_listendata *ldata;\n\tldata = g_new0(struct sipe_backend_listendata, 1);\n\n\tldata->listen_cb = listen_cb;\n\tldata->connect_cb = connect_cb;\n\tldata->data = data;\n\tldata->port_min = port_min;\n\tldata->port_max = port_max;\n\n\tCloseHandle((HANDLE) mir_forkthreadex( listen_callback, ldata, 65536, NULL ));\n\n\treturn ldata;\n}\n\nvoid sipe_backend_network_listen_cancel(struct sipe_backend_listendata *ldata)\n{\n\t_NIF();\n}\n\nstruct sipe_backend_fd *\nsipe_backend_fd_from_int(int fd)\n{\n\t_NIF();\n\treturn NULL;\n}\n\ngboolean\nsipe_backend_fd_is_valid(struct sipe_backend_fd *fd)\n{\n\treturn (fd != NULL);\n}\n\nvoid sipe_backend_fd_free(struct sipe_backend_fd *fd)\n{\n\t/* N/A; sipe_backend_fd is the actual HANDLE */\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-notify.c",
    "content": "/**\n * @file miranda-notify.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-11 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <windows.h>\n#include <stdio.h>\n\n#include <glib.h>\n\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"m_chat.h\"\n#include \"m_database.h\"\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"miranda-private.h\"\n\nstatic void notify_message(struct sipe_core_public *sipe_public,\n\t\t\t   struct sipe_backend_chat_session *backend_session,\n\t\t\t   const gchar *who,\n\t\t\t   const gchar *message,\n\t\t\t   int eventtype,\n\t\t\t   const gchar *prefix\n\t\t\t   )\n{\n        SIPPROTO *pr = sipe_public->backend_private;\n\n\tif (backend_session)\n\t{\n\t\tGCDEST gcd = {0};\n\t\tGCEVENT gce = {0};\n\t\tgchar *msg;\n\n\t\tgcd.pszModule = pr->proto.m_szModuleName;\n\t\tgcd.pszID = backend_session->conv;\n\t\tgcd.iType = GC_EVENT_INFORMATION;\n\n\t\tmsg = mir_alloc(strlen(message)+strlen(prefix)+1);\n\t\tmir_snprintf(msg, strlen(message)+strlen(prefix)+1, \"%s%s\", prefix, message);\n\n\t\tgce.cbSize = sizeof(gce);\n\t\tgce.pDest = &gcd;\n\t\tgce.pszText = msg;\n//\tgce.time = mtime; // FIXME: Generate timestamp\n\n\t\tCallService( MS_GC_EVENT, 0, (LPARAM)&gce );\n\t\tmir_free(msg);\n\n\t} else {\n\t\tHANDLE hContact = sipe_backend_buddy_find( sipe_public, who, NULL );\n\t\tif (hContact)\n\t\t{\n\t\t\tsipe_miranda_AddEvent(pr, hContact, eventtype, time(NULL), DBEF_UTF, strlen(message), (PBYTE)message);\n\t\t}\n\t}\n\n}\n\nvoid sipe_backend_notify_message_error(struct sipe_core_public *sipe_public,\n\t\t\t\t       struct sipe_backend_chat_session *backend_session,\n\t\t\t\t       const gchar *who,\n\t\t\t\t       const gchar *message)\n{\n\tnotify_message(sipe_public, backend_session, who, message, SIPE_EVENTTYPE_ERROR_NOTIFY, \"Error: \");\n}\n\nvoid sipe_backend_notify_message_info(struct sipe_core_public *sipe_public,\n\t\t\t\t      struct sipe_backend_chat_session *backend_session,\n\t\t\t\t      const gchar *who,\n\t\t\t\t      const gchar *message)\n{\n\tnotify_message(sipe_public, backend_session, who, message, SIPE_EVENTTYPE_INFO_NOTIFY, \"Info: \");\n}\n\nvoid sipe_backend_notify_error(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t       const gchar *title,\n\t\t\t       const gchar *msg)\n{\n\tsipe_miranda_msgbox(msg, title);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-plugin.c",
    "content": "/**\n * @file miranda-plugin.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n#pragma comment(lib, \"Secur32.lib\")\n\n#ifdef HAVE_GSSAPI_GSSAPI_H\n#pragma comment(lib, \"krb5_32.lib\")\n#pragma comment(lib, \"gssapi32.lib\")\n#pragma comment(lib, \"comerr32.lib\")\n#endif\n\n#include <windows.h>\n#include <Windowsx.h>\n#include <win2k.h>\n#include <Richedit.h>\n#include <stdio.h>\n\n#include <glib.h>\n\n#include \"miranda-version.h\"\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"m_protomod.h\"\n#include \"m_system.h\"\n#include \"m_database.h\"\n#include \"m_options.h\"\n#include \"m_netlib.h\"\n#include \"m_chat.h\"\n#include \"m_clist.h\"\n#include \"m_langpack.h\"\n#include \"m_message.h\"\n#include \"m_genmenu.h\"\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n\n#include \"miranda-private.h\"\n#include \"miranda-resource.h\"\n\n/* FIXME: Not here */\nvoid CreateProtoService(const SIPPROTO *pr, const char* szService, SipSimpleServiceFunc serviceProc);\n\nHANDLE sipe_miranda_incoming_netlibuser = NULL;\nCRITICAL_SECTION sipe_miranda_debug_CriticalSection;\n\ngchar *sipe_backend_version(void)\n{\n\tchar version[200];\n\n\tif (CallService(MS_SYSTEM_GETVERSIONTEXT, sizeof(version), (LPARAM)version)) {\n\t\tstrcpy(version, \"Unknown\");\n\t}\n\n\treturn g_strdup_printf(\"Miranda %s SIPLCS \" __DATE__ \" \" __TIME__, version );\n}\n\n/*\n * Miranda globals\n *\n * Global variables related to miranda core or UI\n */\nstatic BOOL (WINAPI *pfnEnableThemeDialogTexture)(HANDLE, DWORD) = 0;\nHINSTANCE hInst;\nPLUGINLINK* pluginLink;\nstruct MM_INTERFACE mmi;\nint hLangpack;\n\n/*\n * Dialog boxes\n */\nstatic void\nEnableDlgItem(HWND hwndDlg, UINT control, gboolean enable)\n{\n\tEnableWindow(GetDlgItem(hwndDlg, control), enable);\n}\n\nstatic void\nCheckDlgItem(HWND hwndDlg, UINT control, int state)\n{\n\tButton_SetCheck(GetDlgItem(hwndDlg, control), state);\n}\n\nINT_PTR CALLBACK DlgProcSipSimpleOptsAbout(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)\n{\n\n\tswitch(msg)\n\t{\n\t\tcase WM_INITDIALOG:\n\t\t{\n\t\t\tSIPPROTO *pr = (SIPPROTO *)lParam;\n\t\t\tSETTEXTEX tex;\n\t\t\tgchar *tmp, *about;\n\t\t\tLOCK;\n\t\t\ttmp = sipe_core_about();\n\t\t\tabout = sipe_miranda_html2rtf(tmp);\n\t\t\tg_free(tmp);\n\t\t\tUNLOCK;\n\n\t\t\tTranslateDialogDefault(hwndDlg);\n\n\t\t\tSetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);\n\n\t\t\ttex.flags = ST_DEFAULT;\n\t\t\ttex.codepage = 437;\n\n\t\t\tSendDlgItemMessage(hwndDlg, IDC_ABOUTSIPE, EM_SETTEXTEX, (WPARAM)&tex, (LPARAM)about );\n\n\t\t\tg_free(about);\n\t\t}\n\t}\n\n\treturn FALSE;\n}\n\nstatic INT_PTR CALLBACK DlgProcSipSimpleOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)\n{\n\tstatic int lock=0;\n\n\tswitch(msg)\n\t{\n\t\tcase WM_INITDIALOG:\n\t\t{\n\t\t\tconst SIPPROTO *pr = (const SIPPROTO *)lParam;\n\t\t\tchar *str;\n\t\t\tgboolean state;\n\t\t\tWORD iptype;\n\n\t\t\tTranslateDialogDefault(hwndDlg);\n\n\t\t\tSetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);\n\n\t\t\tlock++;\n\n#if defined(HAVE_GSSAPI_GSSAPI_H) || defined(HAVE_SSPI)\n\t\t\tstate = sipe_miranda_getBool(pr, \"sso\", FALSE);\n\t\t\tif (state)\n\t\t\t{\n\t\t\t\tCheckDlgItem(hwndDlg, IDC_USESSO, BST_CHECKED);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_LOGIN, FALSE);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_PASSWORD, FALSE);\n\t\t\t} else {\n#endif\n\t\t\t\tCheckDlgItem(hwndDlg, IDC_USESSO, BST_UNCHECKED);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_LOGIN, TRUE);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_PASSWORD, TRUE);\n#if defined(HAVE_GSSAPI_GSSAPI_H) || defined(HAVE_SSPI)\n\t\t\t}\n#endif\n\n\t\t\tstr = sipe_miranda_getString(pr, \"username\");\n\t\t\tSetDlgItemTextA(hwndDlg, IDC_HANDLE, str);\n\t\t\tSendDlgItemMessage(hwndDlg, IDC_HANDLE, EM_SETLIMITTEXT, 50, 0);\n\t\t\tmir_free(str);\n\n\t\t\tstr = sipe_miranda_getString(pr, \"login\");\n\t\t\tSetDlgItemTextA(hwndDlg, IDC_LOGIN, str);\n\t\t\tSendDlgItemMessage(hwndDlg, IDC_LOGIN, EM_SETLIMITTEXT, 50, 0);\n\t\t\tmir_free(str);\n\n\t\t\tstr = sipe_miranda_getString(pr, \"password\");\n\t\t\tif (str) CallService(MS_DB_CRYPT_DECODESTRING, strlen(str),(LPARAM)str);\n\t\t\tSetDlgItemTextA(hwndDlg, IDC_PASSWORD, str);\n\t\t\tSendDlgItemMessage(hwndDlg, IDC_PASSWORD, EM_SETLIMITTEXT, 16, 0);\n\t\t\tmir_free(str);\n\n\t\t\tSendDlgItemMessage(hwndDlg, IDC_AUTHTYPE, CB_ADDSTRING, 0, (LPARAM)_T(\"Auto\"));\n\t\t\tSendDlgItemMessage(hwndDlg, IDC_AUTHTYPE, CB_ADDSTRING, 0, (LPARAM)_T(\"NTLM\"));\n#if defined(HAVE_GSSAPI_GSSAPI_H) || defined(HAVE_SSPI)\n\t\t\tSendDlgItemMessage(hwndDlg, IDC_AUTHTYPE, CB_ADDSTRING, 0, (LPARAM)_T(\"Kerberos\"));\n#endif\n\t\t\tSendDlgItemMessage(hwndDlg, IDC_AUTHTYPE, CB_ADDSTRING, 0, (LPARAM)_T(\"TLS-DSK\"));\n\n\t\t\tsipe_miranda_getWord(pr, NULL, \"authscheme\", &iptype);\n\t\t\tif (iptype == SIPE_AUTHENTICATION_TYPE_NTLM)\n\t\t\t\tSendDlgItemMessage(hwndDlg, IDC_AUTHTYPE, CB_SELECTSTRING, -1, (LPARAM)_T(\"NTLM\"));\n\t\t\telse if (iptype == SIPE_AUTHENTICATION_TYPE_KERBEROS)\n\t\t\t\tSendDlgItemMessage(hwndDlg, IDC_AUTHTYPE, CB_SELECTSTRING, -1, (LPARAM)_T(\"Kerberos\"));\n\t\t\telse if (iptype == SIPE_AUTHENTICATION_TYPE_TLS_DSK)\n\t\t\t\tSendDlgItemMessage(hwndDlg, IDC_AUTHTYPE, CB_SELECTSTRING, -1, (LPARAM)_T(\"TLS-DSK\"));\n\t\t\telse\n\t\t\t\tSendDlgItemMessage(hwndDlg, IDC_AUTHTYPE, CB_SELECTSTRING, -1, (LPARAM)_T(\"Auto\"));\n\n\t\t\tSendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_ADDSTRING, 0, (LPARAM)_T(\"Auto\"));\n\t\t\tSendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_ADDSTRING, 0, (LPARAM)_T(\"SSL/TLS\"));\n\t\t\tSendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_ADDSTRING, 0, (LPARAM)_T(\"TCP\"));\n\n\t\t\tstr = sipe_miranda_getString(pr, \"transport\");\n\t\t\tif (!str || !strcmp(str, \"auto\"))\n\t\t\t\tSendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_SELECTSTRING, -1, (LPARAM)_T(\"Auto\"));\n\t\t\telse if (!strcmp(str, \"tls\"))\n\t\t\t\tSendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_SELECTSTRING, -1, (LPARAM)_T(\"SSL/TLS\"));\n\t\t\telse if (!strcmp(str, \"tcp\"))\n\t\t\t\tSendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_SELECTSTRING, -1, (LPARAM)_T(\"TCP\"));\n\n\t\t\tstr = sipe_miranda_getGlobalString(\"public_ip\");\n\t\t\tSetDlgItemTextA(hwndDlg, IDC_PUBLICIP, str);\n\t\t\tSendDlgItemMessage(hwndDlg, IDC_PUBLICIP, EM_SETLIMITTEXT, 20, 0);\n\t\t\tmir_free(str);\n\n\t\t\tstr = sipe_miranda_getGlobalString(\"ipprog\");\n\t\t\tSetDlgItemTextA(hwndDlg, IDC_IPPROGEXE, str);\n\t\t\tSendDlgItemMessage(hwndDlg, IDC_IPPROGEXE, EM_SETLIMITTEXT, 60, 0);\n\t\t\tmir_free(str);\n\n\t\t\tstr = sipe_miranda_get_local_ip();\n\t\t\tSetDlgItemTextA(hwndDlg, IDC_IPLOCALFOUND, str);\n\n\t\t\tsipe_miranda_getGlobalWord(\"iptype\", &iptype);\n\t\t\tif (iptype == SIPE_MIRANDA_IP_LOCAL)\n\t\t\t{\n\t\t\t\tCheckRadioButton(hwndDlg, IDC_IPLOCAL, IDC_IPPROG, IDC_IPLOCAL);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_PUBLICIP, FALSE);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_IPPROGEXE, FALSE);\n\t\t\t} else if (iptype == SIPE_MIRANDA_IP_MANUAL) {\n\t\t\t\tCheckRadioButton(hwndDlg, IDC_IPLOCAL, IDC_IPPROG, IDC_IPMANUAL);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_PUBLICIP, TRUE);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_IPPROGEXE, FALSE);\n\t\t\t} else {\n\t\t\t\tCheckRadioButton(hwndDlg, IDC_IPLOCAL, IDC_IPPROG, IDC_IPPROG);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_PUBLICIP, FALSE);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_IPPROGEXE, TRUE);\n\t\t\t}\n\n\t\t\tlock--;\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tcase WM_COMMAND:\n\t\t{\n\t\t\tint code = wParam >> 16;\n\t\t\tint id = wParam & 0xffff;\n\n\t\t\tif (LOWORD(wParam) == IDC_IPLOCAL)\n\t\t\t{\n\t\t\t\tCheckRadioButton(hwndDlg, IDC_IPLOCAL, IDC_IPPROG, IDC_IPLOCAL);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_PUBLICIP, FALSE);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_IPPROGEXE, FALSE);\n\t\t\t\tSendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);\n\t\t\t} else if (LOWORD(wParam) == IDC_IPMANUAL) {\n\t\t\t\tCheckRadioButton(hwndDlg, IDC_IPLOCAL, IDC_IPPROG, IDC_IPMANUAL);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_PUBLICIP, TRUE);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_IPPROGEXE, FALSE);\n\t\t\t\tSendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);\n\t\t\t} else if (LOWORD(wParam) == IDC_IPPROG) {\n\t\t\t\tCheckRadioButton(hwndDlg, IDC_IPLOCAL, IDC_IPPROG, IDC_IPPROG);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_PUBLICIP, FALSE);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_IPPROGEXE, TRUE);\n\t\t\t\tSendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);\n\t\t\t} else if (LOWORD(wParam) == IDC_USESSO) {\n\t\t\t\tif (IsDlgButtonChecked(hwndDlg, IDC_USESSO) == BST_CHECKED)\n\t\t\t\t{\n\t\t\t\t\tEnableDlgItem(hwndDlg, IDC_LOGIN, FALSE);\n\t\t\t\t\tEnableDlgItem(hwndDlg, IDC_PASSWORD, FALSE);\n\t\t\t\t\tSendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);\n\t\t\t\t} else {\n\t\t\t\t\tCheckRadioButton(hwndDlg, IDC_SSO, IDC_MSO, IDC_MSO);\n\t\t\t\t\tEnableDlgItem(hwndDlg, IDC_LOGIN, TRUE);\n\t\t\t\t\tEnableDlgItem(hwndDlg, IDC_PASSWORD, TRUE);\n\t\t\t\t}\n\t\t\t} else if (!lock && (code == EN_CHANGE || code == CBN_SELCHANGE)) {\n\t\t\t\tSendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);\n\t\t\t}\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tcase WM_NOTIFY:\n\t\t{\n\t\t\tif (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY)\n\t\t\t{\n\t\t\t\tchar buf[100];\n\t\t\t\tTCHAR tbuf[100];\n\n\t\t\t\tconst SIPPROTO *pr = (const SIPPROTO *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);\n\n\t\t\t\tGetDlgItemTextA(hwndDlg, IDC_HANDLE, buf, sizeof(buf));\n\t\t\t\tsipe_miranda_setString(pr, \"username\", buf);\n\n\t\t\t\tGetDlgItemTextA(hwndDlg, IDC_LOGIN, buf, sizeof(buf));\n\t\t\t\tsipe_miranda_setString(pr, \"login\", buf);\n\n\t\t\t\tGetDlgItemTextA(hwndDlg, IDC_PASSWORD, buf, sizeof(buf));\n\t\t\t\tCallService(MS_DB_CRYPT_ENCODESTRING, sizeof(buf),(LPARAM)buf);\n\t\t\t\tsipe_miranda_setString(pr, \"password\", buf);\n\n\t\t\t\tSendDlgItemMessage(hwndDlg, IDC_CONNTYPE, WM_GETTEXT, 100, (LPARAM)tbuf );\n\n\t\t\t\tif (!_tcscmp(tbuf, _T(\"Auto\")))\n\t\t\t\t\tsipe_miranda_setString(pr, \"transport\", \"auto\");\n\t\t\t\telse if (!_tcscmp(tbuf, _T(\"SSL/TLS\")))\n\t\t\t\t\tsipe_miranda_setString(pr, \"transport\", \"tls\");\n\t\t\t\telse if (!_tcscmp(tbuf, _T(\"TCP\")))\n\t\t\t\t\tsipe_miranda_setString(pr, \"transport\", \"tcp\");\n\n\t\t\t\tSendDlgItemMessage(hwndDlg, IDC_AUTHTYPE, WM_GETTEXT, 100, (LPARAM)tbuf );\n\n\t\t\t\tif (!_tcscmp(tbuf, _T(\"NTLM\")))\n\t\t\t\t\tsipe_miranda_setWord(pr, NULL, \"authscheme\", SIPE_AUTHENTICATION_TYPE_NTLM);\n\t\t\t\telse if (!_tcscmp(tbuf, _T(\"Kerberos\")))\n\t\t\t\t\tsipe_miranda_setWord(pr, NULL, \"authscheme\", SIPE_AUTHENTICATION_TYPE_KERBEROS);\n\t\t\t\telse if (!_tcscmp(tbuf, _T(\"TLS-DSK\")))\n\t\t\t\t\tsipe_miranda_setWord(pr, NULL, \"authscheme\", SIPE_AUTHENTICATION_TYPE_TLS_DSK);\n\t\t\t\telse\n\t\t\t\t\tsipe_miranda_setWord(pr, NULL, \"authscheme\", SIPE_AUTHENTICATION_TYPE_AUTOMATIC);\n\n\t\t\t\tGetDlgItemTextA(hwndDlg, IDC_PUBLICIP, buf, sizeof(buf));\n\t\t\t\tsipe_miranda_setGlobalString(\"public_ip\", buf);\n\n\t\t\t\tGetDlgItemTextA(hwndDlg, IDC_IPPROGEXE, buf, sizeof(buf));\n\t\t\t\tsipe_miranda_setGlobalString(\"ipprog\", buf);\n\n\t\t\t\tif (IsDlgButtonChecked(hwndDlg, IDC_IPLOCAL) == BST_CHECKED)\n\t\t\t\t{\n\t\t\t\t\tsipe_miranda_setGlobalWord(\"iptype\", SIPE_MIRANDA_IP_LOCAL);\n\t\t\t\t} else if (IsDlgButtonChecked(hwndDlg, IDC_IPMANUAL) == BST_CHECKED) {\n\t\t\t\t\tsipe_miranda_setGlobalWord(\"iptype\", SIPE_MIRANDA_IP_MANUAL);\n\t\t\t\t} else {\n\t\t\t\t\tsipe_miranda_setGlobalWord(\"iptype\", SIPE_MIRANDA_IP_PROG);\n\t\t\t\t}\n\t\t\t\treturn TRUE;\n\t\t\t}\n\t\t\treturn TRUE;\n\t\t}\n\n\t}\n\n\treturn FALSE;\n}\n\nINT_PTR CALLBACK DlgProcAccMgrUI(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)\n{\n\tswitch(msg)\n\t{\n\t\tcase WM_INITDIALOG:\n\t\t{\n\t\t\tconst SIPPROTO *pr = (const SIPPROTO *)lParam;\n\t\t\tchar *str;\n\t\t\tgboolean sso;\n\n\t\t\tTranslateDialogDefault(hwndDlg);\n\n\t\t\tSetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);\n\n\t\t\tsso = sipe_miranda_getBool(pr, \"sso\", FALSE);\n\t\t\tif (sso)\n\t\t\t{\n\t\t\t\tCheckRadioButton(hwndDlg, IDC_SSO, IDC_MSO, IDC_SSO);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_LOGIN, FALSE);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_PASSWORD, FALSE);\n\t\t\t} else {\n\t\t\t\tCheckRadioButton(hwndDlg, IDC_SSO, IDC_MSO, IDC_MSO);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_LOGIN, TRUE);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_PASSWORD, TRUE);\n\t\t\t}\n\n\t\t\tstr = sipe_miranda_getString(pr, \"username\");\n\t\t\tSetDlgItemTextA(hwndDlg, IDC_HANDLE, str);\n\t\t\tmir_free(str);\n\n\t\t\tstr = sipe_miranda_getString(pr, \"login\");\n\t\t\tSetDlgItemTextA(hwndDlg, IDC_LOGIN, str);\n\t\t\tmir_free(str);\n\n\t\t\tstr = sipe_miranda_getString(pr, \"password\");\n\t\t\tif (str) CallService(MS_DB_CRYPT_DECODESTRING, strlen(str),(LPARAM)str);\n\t\t\tSetDlgItemTextA(hwndDlg, IDC_PASSWORD, str);\n\t\t\tmir_free(str);\n\n\t\t\tSendDlgItemMessage(hwndDlg, IDC_HANDLE, EM_SETLIMITTEXT, 50, 0);\n\t\t\tSendDlgItemMessage(hwndDlg, IDC_LOGIN, EM_SETLIMITTEXT, 50, 0);\n\t\t\tSendDlgItemMessage(hwndDlg, IDC_PASSWORD, EM_SETLIMITTEXT, 16, 0);\n\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tcase WM_COMMAND:\n\t\t\tif (LOWORD(wParam) == IDC_SSO)\n\t\t\t{\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_LOGIN, FALSE);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_PASSWORD, FALSE);\n\t\t\t\tSendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);\n\t\t\t} else if (LOWORD(wParam) == IDC_MSO) {\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_LOGIN, TRUE);\n\t\t\t\tEnableDlgItem(hwndDlg, IDC_PASSWORD, TRUE);\n\t\t\t\tSendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);\n\t\t\t} else if (HIWORD(wParam) == EN_CHANGE && (HWND)lParam == GetFocus()) {\n\t\t\t\tswitch(LOWORD(wParam))\n\t\t\t\t{\n\t\t\t\t\tcase IDC_HANDLE:\n\t\t\t\t\tcase IDC_LOGIN:\n\t\t\t\t\tcase IDC_PASSWORD:\n\t\t\t\t\t\tSendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WM_NOTIFY:\n\t\t\tif (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY)\n\t\t\t{\n\t\t\t\tchar buf[100];\n\n\t\t\t\tconst SIPPROTO *pr = (const SIPPROTO *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);\n\n\t\t\t\tif (IsDlgButtonChecked(hwndDlg, IDC_SSO) == BST_CHECKED)\n\t\t\t\t{\n\t\t\t\t\tsipe_miranda_setBool(pr, \"sso\", TRUE);\n\t\t\t\t} else {\n\t\t\t\t\tsipe_miranda_setBool(pr, \"sso\", FALSE);\n\t\t\t\t}\n\n\t\t\t\tGetDlgItemTextA(hwndDlg, IDC_HANDLE, buf, sizeof(buf));\n\t\t\t\tsipe_miranda_setString(pr, \"username\", buf);\n\n\t\t\t\tGetDlgItemTextA(hwndDlg, IDC_LOGIN, buf, sizeof(buf));\n\t\t\t\tsipe_miranda_setString(pr, \"login\", buf);\n\n\t\t\t\tGetDlgItemTextA(hwndDlg, IDC_PASSWORD, buf, sizeof(buf));\n\t\t\t\tCallService(MS_DB_CRYPT_ENCODESTRING, sizeof(buf),(LPARAM)buf);\n\t\t\t\tsipe_miranda_setString(pr, \"password\", buf);\n\n\t\t\t\treturn TRUE;\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n\treturn FALSE;\n}\n\n\n/*\n * Miranda service support functions\n *\n * Functions called by our service functions\n */\nstatic void fix_contact_groups(SIPPROTO *pr)\n{\n\tGSList *contacts = sipe_miranda_buddy_find_all(pr, NULL, NULL);\n\tchar *group;\n\n\tCONTACTS_FOREACH(contacts)\n\t\tgroup = DBGetString(hContact, \"CList\", \"Group\");\n\t\tsipe_miranda_setContactString(pr, hContact, \"Group\", group);\n\t\tmir_free(group);\n\tCONTACTS_FOREACH_END\n\n}\n\nstatic INT_PTR sipe_miranda_start_chat(SIPPROTO *pr, WPARAM wParam, LPARAM lParam)\n{\n\tHANDLE hContact = (HANDLE)wParam;\n\tstruct sipe_core_public *sipe_public = pr->sip;\n\n\tDBVARIANT dbv;\n\tif ( !DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv )) {\n\t\tLOCK;\n\t\tsipe_core_buddy_new_chat(sipe_public, dbv.pszVal);\n\t\tUNLOCK;\n\t\tDBFreeVariant( &dbv );\n\t\treturn TRUE;\n\t}\n\n\treturn FALSE;\n}\n\nstatic void OnModulesLoaded(SIPPROTO *pr)\n{\n\tTCHAR descr[MAX_PATH];\n\tNETLIBUSER nlu = {0};\n\tGCREGISTER gcr;\n\tDBEVENTTYPEDESCR eventType = {0};\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"OnEvent::OnModulesLoaded\");\n\n\tnlu.cbSize = sizeof(nlu);\n\tnlu.flags = NUF_OUTGOING | NUF_INCOMING | NUF_TCHAR;\n\tnlu.szSettingsModule = pr->proto.m_szModuleName;\n\t_sntprintf(descr, SIZEOF(descr), TranslateT(\"%s server connection\"), pr->proto.m_tszUserName );\n\tnlu.ptszDescriptiveName = descr;\n\n\tpr->m_hServerNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);\n\n\tgcr.cbSize = sizeof(gcr);\n\tgcr.dwFlags = 0;\n\tgcr.pszModule = pr->proto.m_szModuleName;\n\tgcr.pszModuleDispName = \"Sip/Simple\";\n\tgcr.iMaxText = 0;\n\tgcr.nColors = 0;\n\n\tif (CallService(MS_GC_REGISTER, 0, (LPARAM)&gcr))\n\t{\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"OnEvent::OnModulesLoaded Failed to register chat\");\n\t}\n\n        // Register custom database events\n\teventType.cbSize = DBEVENTTYPEDESCR_SIZE;\n\teventType.module = pr->proto.m_szModuleName;\n\teventType.eventType = SIPE_EVENTTYPE_ERROR_NOTIFY;\n\teventType.descr = \"Message error notification\";\n\teventType.textService = SIPE_DB_GETEVENTTEXT_ERROR_NOTIFY;\n\teventType.flags = DETF_HISTORY | DETF_MSGWINDOW;\n\t// for now keep default \"message\" icon\n\tCallService(MS_DB_EVENT_REGISTERTYPE, 0, (LPARAM)&eventType);\n\n\teventType.cbSize = DBEVENTTYPEDESCR_SIZE;\n\teventType.module = pr->proto.m_szModuleName;\n\teventType.eventType = SIPE_EVENTTYPE_INFO_NOTIFY;\n\teventType.descr = \"Message info notification\";\n\teventType.textService = SIPE_DB_GETEVENTTEXT_INFO_NOTIFY;\n\teventType.flags = DETF_HISTORY | DETF_MSGWINDOW;\n\t// for now keep default \"message\" icon\n\tCallService(MS_DB_EVENT_REGISTERTYPE, 0, (LPARAM)&eventType);\n\n\teventType.cbSize = DBEVENTTYPEDESCR_SIZE;\n\teventType.module = pr->proto.m_szModuleName;\n\teventType.eventType = SIPE_EVENTTYPE_IM_TOPIC;\n\teventType.descr = \"Chat topic set\";\n\teventType.textService = SIPE_DB_GETEVENTTEXT_IM_TOPIC;\n\teventType.flags = DETF_HISTORY | DETF_MSGWINDOW;\n\t// for now keep default \"message\" icon\n\tCallService(MS_DB_EVENT_REGISTERTYPE, 0, (LPARAM)&eventType);\n\n}\n\nint OnOptionsInit(const SIPPROTO *pr, WPARAM wParam, LPARAM lParam)\n{\n\tOPTIONSDIALOGPAGE odp = {0};\n\tHMODULE hUxTheme = 0;\n\n\tif (IsWinVerXPPlus())\n\t{\n\t\thUxTheme = GetModuleHandleA(\"uxtheme.dll\");\n\t\tif (hUxTheme)\n\t\t\tpfnEnableThemeDialogTexture = (BOOL (WINAPI *)(HANDLE, DWORD))GetProcAddress(hUxTheme, \"EnableThemeDialogTexture\");\n\t}\n\n\todp.cbSize = sizeof(odp);\n\todp.position = -800000000;\n\todp.hInstance = hInst;\n\todp.ptszGroup = LPGENT(\"Network\");\n\todp.dwInitParam = (LPARAM)pr;\n\todp.ptszTitle = pr->proto.m_tszUserName;\n\todp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;\n\n\todp.ptszTab = LPGENT(\"Account\");\n\todp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_SIPSIMPLE);\n\todp.pfnDlgProc = DlgProcSipSimpleOpts;\n\tCallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );\n\n\todp.ptszTab = LPGENT(\"About\");\n\todp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_SIPSIMPLE_ABOUT);\n\todp.pfnDlgProc = DlgProcSipSimpleOptsAbout;\n\tCallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );\n\n#if 0\n\n        odp.ptszTab = LPGENT(\"Features\");\n        odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ICQFEATURES);\n        odp.pfnDlgProc = DlgProcIcqFeaturesOpts;\n        CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );\n\n        odp.ptszTab = LPGENT(\"Privacy\");\n        odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ICQPRIVACY);\n        odp.pfnDlgProc = DlgProcIcqPrivacyOpts;\n        CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );\n\n        if (bPopUpService)\n        {\n                odp.position = 100000000;\n                odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_POPUPS);\n                odp.groupPosition = 900000000;\n                odp.pfnDlgProc = DlgProcIcqPopupOpts;\n                odp.ptszGroup = LPGENT(\"Popups\");\n                odp.ptszTab = NULL;\n                CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );\n        }\n#endif\n        return 0;\n}\n\nvoid sipe_miranda_close(SIPPROTO *pr)\n{\n\tstruct sipe_core_public *sipe_public = pr->sip;\n\n\tif (sipe_public) {\n\t\tLOCK;\n\t\tsipe_core_deallocate(sipe_public);\n\t\tpr->sip = NULL;\n\t\tUNLOCK;\n\n//\t\tsipe_purple_chat_destroy_rejoin(purple_private);\n//\t\tg_free(purple_private);\n\t}\n}\n\nvoid set_buddies_offline(const SIPPROTO* pr)\n{\n\tHANDLE hContact;\n\n\thContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);\n\twhile (hContact) {\n\t\tchar* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);\n\t\tif (szProto != NULL && !lstrcmpA(szProto, pr->proto.m_szModuleName)) {\n\t\t\tif (DBGetContactSettingByte(hContact, pr->proto.m_szModuleName, \"ChatRoom\", 0) == 0)\n\t\t\t\tDBWriteContactSettingWord(hContact, pr->proto.m_szModuleName, \"Status\", ID_STATUS_OFFLINE);\n\t\t}\n\t\thContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);\n\t}\n}\n\nint __stdcall show_vlc(void *data);\nvoid sipe_miranda_login(SIPPROTO *pr) {\n\tgchar *username = sipe_miranda_getString(pr, \"username\");\n\tgchar *login = sipe_miranda_getString(pr, \"login\");\n\tgchar *email = sipe_miranda_getString(pr, \"email\");\n\tgchar *email_url = sipe_miranda_getString(pr, \"email_url\");\n\tconst gchar *errmsg;\n\tgchar *password;\n\tgchar *tmp = (char*)mir_calloc(1024);\n\tint tmpstatus;\n\tint ttype;\n\tguint authentication_type = SIPE_AUTHENTICATION_TYPE_AUTOMATIC;\n\tstruct sipe_core_public *sipe_public;\n\n//\tCloseHandle((HANDLE) mir_forkthreadex(show_vlc, NULL, 65536, NULL));\n\n\tif (sipe_miranda_getStaticString(pr, NULL, \"password\", tmp, 1024 )) tmp[0] = '\\0';\n\tCallService(MS_DB_CRYPT_DECODESTRING, sizeof(tmp),(LPARAM)tmp);\n\tpassword = g_strdup(tmp);\n\tmir_free(tmp);\n\n\tLOCK;\n\tpr->sip = sipe_core_allocate(username,\n//\t/* @TODO: is this correct?\n//\t   \"sso\" is only available when SSPI/Kerberos support is compiled in */\n\t\t\t\t     sipe_miranda_getBool(pr, \"sso\", FALSE),\n\t\t\t\t     login,\n\t\t\t\t     password,\n\t\t\t\t     email,\n\t\t\t\t     email_url,\n\t\t\t\t     &errmsg);\n\tif (pr->sip) pr->sip->backend_private = pr;\n\tsipe_public = pr->sip;\n\tUNLOCK;\n\n\tmir_free(username);\n\tmir_free(login);\n\tmir_free(email);\n\tmir_free(email_url);\n\tg_free(password);\n\n\tif (!pr->sip) {\n\t\tsipe_miranda_connection_error_reason(pr,\n\t\t\t\t\t\t     SIPE_CONNECTION_ERROR_INVALID_USERNAME, \n\t\t\t\t\t\t     errmsg);\n\t\treturn;\n\t}\n\n\t//sipe_miranda_chat_setup_rejoin(pr);\n\n\t/* default is Auto */\n\tsipe_miranda_getWord(pr, NULL, \"authscheme\", &authentication_type);\n\n\t/* Set display name */\n\tsipe_miranda_setStringUtf(pr, \"Nick\", pr->sip->sip_name);\n\n\t/* Update connection progress */\n\ttmpstatus = pr->proto.m_iStatus;\n\tpr->proto.m_iStatus = ID_STATUS_CONNECTING;\n\tsipe_miranda_SendBroadcast(pr, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)tmpstatus, ID_STATUS_CONNECTING);\n\n\ttmp = sipe_miranda_getString(pr, \"transport\");\n\tif (sipe_strequal(tmp, \"auto\")) {\n\t\tttype = SIPE_TRANSPORT_AUTO;\n\t} else if (sipe_strequal(tmp, \"tls\")) {\n\t\tttype = SIPE_TRANSPORT_TLS;\n\t} else {\n\t\tttype = SIPE_TRANSPORT_TCP;\n\t}\n\tmir_free(tmp);\n\n\tLOCK;\n\tsipe_core_transport_sip_connect(pr->sip,\n\t\t\t\t\tttype,\n\t\t\t\t\tauthentication_type,\n\t\t\t\t\tNULL,\n\t\t\t\t\tNULL);\n\tUNLOCK;\n}\n\nvoid sipsimple_search_contact_cb( GList *columns, GList *results, GHashTable *opts, void *data )\n{\n\tSIPPROTO *pr = (SIPPROTO *)data;\n\tGList *row, *col;\n\tHANDLE hProcess = g_hash_table_lookup(opts, \"searchid\");\n\tPROTOSEARCHRESULT psr = { 0 };\n\n\tpsr.cbSize = sizeof(psr);\n\n\trow = results;\n\twhile (row)\n\t{\n\t\tgchar **name;\n\n\t\tcol = (GList*)row->data;\n\t\tpsr.id = (PROTOCHAR*)col->data;\n\n\t\tcol = g_list_next(col);\n\t\tname = g_strsplit_set(col->data, \",\", 2);\n\t\tpsr.nick = (FNAMECHAR*)col->data;\n\t\tpsr.firstName = (PROTOCHAR*)(name[0] ? name[1] : NULL);\n\t\tpsr.lastName = (PROTOCHAR*)name[0];\n\n\t\tcol = g_list_next(col);\n\t\t/* company */\n\n\t\tcol = g_list_next(col);\n\t\t/* country */\n\n\t\tcol = g_list_next(col);\n\t\tpsr.email = (PROTOCHAR*)col->data;\n\n\t\trow = g_list_next(row);\n\t\tsipe_miranda_SendBroadcast(pr, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, hProcess, (LPARAM) & psr);\n\t\tg_strfreev(name);\n\t}\n\n\tsipe_miranda_SendBroadcast(pr, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, hProcess, 0);\n\n}\n\nstatic int OnGroupChange(SIPPROTO *pr, WPARAM w, LPARAM l )\n{\n\tCLISTGROUPCHANGE *gi = (CLISTGROUPCHANGE*)l;\n\tHANDLE hContact = (HANDLE)w;\n\tDBVARIANT dbv;\n\n\t/* No contact => it's a group add/rename/remove */\n\tif (!hContact)\n\t{\n\t\tgchar *oldname, *newname;\n\n\t\t/* No old name => add */\n\t\tif (!gi->pszOldName)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\t\t/* No new name => delete */\n\t\telse if (!gi->pszNewName)\n\t\t{\n\t\t\tSIPE_DEBUG_INFO(\"Removing group <%ls>\", gi->pszOldName);\n\t\t\toldname = mir_t2a(gi->pszOldName);\n\t\t\tLOCK;\n\t\t\tsipe_core_group_remove(pr->sip, oldname);\n\t\t\tUNLOCK;\n\t\t\tmir_free(oldname);\n\t\t\treturn 0;\n\t\t}\n\n\t\tSIPE_DEBUG_INFO(\"Renaming group <%S> to <%S>\", gi->pszOldName, gi->pszNewName);\n\t\toldname = mir_t2a(gi->pszOldName);\n\t\tnewname = mir_t2a(gi->pszNewName);\n\t\tLOCK;\n\t\tsipe_core_group_rename(pr->sip, oldname, newname);\n\t\tUNLOCK;\n\t\tmir_free(oldname);\n\t\tmir_free(newname);\n\t\treturn 0;\n\t}\n\n\tif ( !DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv )) {\n\t\tgchar *oldgroup;\n\t\tgchar *who = g_strdup(dbv.pszVal);\n\t\tDBFreeVariant( &dbv );\n\n\t\tif (oldgroup = sipe_miranda_getContactString(pr, hContact, \"Group\"))\n\t\t{\n\t\t\tSIPE_DEBUG_INFO(\"Moving buddy <%s> from group <%ls> to group <%ls>\", who, oldgroup, gi->pszNewName);\n\t\t\tLOCK;\n\t\t\tsipe_core_buddy_group(pr->sip, who, oldgroup, TCHAR2CHAR(gi->pszNewName));\n\t\t\tUNLOCK;\n\t\t\tmir_free(oldgroup);\n\t\t} else {\n\t\t\tgchar *name = mir_t2a(gi->pszNewName);\n\n\t\t\tif (!g_str_has_prefix(name, \"sip:\")) {\n\t\t\t\tgchar *newname = sip_uri_from_name(name);\n\t\t\t\tmir_free(name);\n\t\t\t\tname = mir_strdup(newname);\n\t\t\t\tg_free(newname);\n\t\t\t}\n\n\t\t\tSIPE_DEBUG_INFO(\"Really adding buddy <%s> to list in group <%s>\", who, name);\n\t\t\tLOCK;\n\t\t\tsipe_core_buddy_add(pr->sip, who, name);\n\t\t\tUNLOCK;\n\t\t\tmir_free(name);\n\t\t}\n\n\t\tg_free(who);\n\t}\n\n\treturn TRUE;\n}\n\nstatic int sipe_miranda_build_chat_menu(SIPPROTO *pr, WPARAM w, LPARAM lParam )\n{\n\tGCMENUITEMS *gcmi= (GCMENUITEMS*) lParam;\n\n\tif (gcmi->Type == MENU_ON_NICKLIST)\n\t{\n\t\tstatic struct gc_item Item[] = {\n                                {\"&Make Leader\", 1, MENU_ITEM, FALSE},\n\t\t};\n\n\t\tgcmi->nItems = sizeof(Item)/sizeof(Item[0]);\n\t\tgcmi->Item = &Item[0];\n\n\t}\n\treturn 0;\n}\n\nstatic int OnChatEvent(SIPPROTO *pr, WPARAM w, LPARAM l )\n{\n\tGCHOOK *hook = (GCHOOK*)l;\n\tGCDEST *dst = hook->pDest;\n\n\tif (dst->iType == GC_USER_MESSAGE) {\n\t\tGCDEST gcd = {0};\n\t\tGCEVENT gce = {0};\n\t\tstruct sipe_chat_session *session;\n\n\t\tgcd.pszModule = pr->proto.m_szModuleName;\n\t\tgcd.pszID = dst->pszID;\n\t\tgcd.iType = GC_EVENT_GETITEMDATA;\n\n\t\tgce.cbSize = sizeof(gce);\n\t\tgce.pDest = &gcd;\n\n\n\t\tif ((session = (struct sipe_chat_session*)CallService( MS_GC_EVENT, 0, (LPARAM)&gce )) == NULL)\n\t\t{\n\t\t\tSIPE_DEBUG_WARNING_NOFORMAT(\"Failed to get chat session\");\n\t\t\treturn 0;\n\t\t}\n\n\t\tLOCK;\n\t\tsipe_core_chat_send(pr->sip, session, hook->pszText);\n\t\tUNLOCK;\n\n\t\treturn TRUE;\n\t} else if (dst->iType == GC_USER_PRIVMESS) {\n\t} else if (dst->iType == GC_USER_NICKLISTMENU) {\n\t\tif (hook->dwData == 1)\n\t\t{\n\t\t\tSIPE_DEBUG_INFO(\"make leader <%s>\", hook->pszUID);\n\t\t}\n\t}\n\n\treturn FALSE;\n}\n\nint OnPreBuildContactMenu(SIPPROTO *pr, WPARAM wParam, LPARAM lParam)\n{\n\tHANDLE hContact = (HANDLE)wParam;\n\tint chatcount = CallService(MS_GC_GETSESSIONCOUNT, 0, (LPARAM)pr->proto.m_szModuleName);\n\tint idx;\n\tCLISTMENUITEM mi = {0};\n\tGC_INFO gci = {0};\n\tgpointer tmp;\n\n\tmi.cbSize = sizeof(mi);\n\tgci.pszModule = pr->proto.m_szModuleName;\n\n\t/* Remove the old list */\n\twhile (pr->contactMenuChatItems)\n\t{\n\t\tSIPE_DEBUG_INFO(\"Removing old menuitem <%08x>\", pr->contactMenuChatItems->data);\n\t\tCallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)pr->contactMenuChatItems->data, 0);\n\t\tpr->contactMenuChatItems = g_slist_remove(pr->contactMenuChatItems, pr->contactMenuChatItems->data);\n\t}\n\n\t/* Add the main entry */\n\tmi.pszName = \"Invite to chat\";\n\tmi.flags = CMIF_NOTOFFLINE;\n\tmi.position = 20;\n\ttmp = (gpointer)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);\n\tpr->contactMenuChatItems = g_slist_append(pr->contactMenuChatItems, tmp);\n\n\tmi.pszName = \"New chat\";\n\tmi.hParentMenu = pr->contactMenuChatItems->data;\n\tmi.flags = CMIF_ROOTHANDLE;\n\tmi.popupPosition = 0;\n\tmi.position=-10;\n\tmi.pszService = g_strdup_printf(\"%s/StartChat\", pr->proto.m_szModuleName);\n\tmi.pszContactOwner = pr->proto.m_szModuleName;\n\ttmp = (gpointer)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);\n\tg_free(mi.pszService);\n\tpr->contactMenuChatItems = g_slist_append(pr->contactMenuChatItems, tmp);\n\n\tfor (idx=0 ; idx<chatcount ; idx++)\n\t{\n\t\tSIPE_DEBUG_INFO(\"Chat <%d> Menuitem <%08x>\", idx, pr->contactMenuChatItems);\n\t\tgci.iItem = idx;\n\t\tgci.Flags = BYINDEX | NAME | ID;\n\t\tif(!CallServiceSync( MS_GC_GETINFO, 0, (LPARAM)&gci )) {\n\t\t\tSIPE_DEBUG_INFO(\"Chat <%s>\", gci.pszName);\n\n\t\t\tmi.pszName = gci.pszName;\n\t\t\tmi.hParentMenu = pr->contactMenuChatItems->data;\n\t\t\tmi.flags = CMIF_ROOTHANDLE;\n\t\t\tmi.popupPosition = g_strdup(gci.pszID);\n\t\t\tmi.position = idx;\n\t\t\tmi.pszService = g_strdup_printf(\"%s/InviteToChat\", pr->proto.m_szModuleName);\n\t\t\tmi.pszContactOwner = pr->proto.m_szModuleName;\n\t\t\ttmp = (gpointer)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);\n\t\t\tg_free(mi.pszService);\n\t\t\tpr->contactMenuChatItems = g_slist_append(pr->contactMenuChatItems, tmp);\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nINT_PTR  SvcCreateAccMgrUI(const SIPPROTO *pr, WPARAM wParam, LPARAM lParam)\n{\n\treturn (INT_PTR)CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_ACCMGRUI), (HWND)lParam, DlgProcAccMgrUI, (LPARAM)pr);\n}\n\n\n/*\n * Miranda service functions\n *\n * The functions in our plugin that get called directly by core Miranda\n */\nstatic DWORD_PTR GetCaps( SIPPROTO *pr, int type, HANDLE hContact )\n{\n\tswitch (type) {\n\t\tcase PFLAGNUM_1:\n\t\t\treturn PF1_IM | PF1_CHAT | PF1_FILE | PF1_MODEMSG\n\t\t\t\t| PF1_SERVERCLIST | PF1_ADDED\n\t\t\t\t| PF1_BASICSEARCH | PF1_ADDSEARCHRES\n\t\t\t\t| PF1_SEARCHBYEMAIL | PF1_USERIDISEMAIL\n\t\t\t\t| PF1_SEARCHBYNAME | PF1_EXTSEARCH\n\t\t\t\t;\n\n\t\tcase PFLAGNUM_2:\n\t\t\treturn PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY\n\t\t\t\t| PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND\n\t\t\t\t| PF2_OUTTOLUNCH | PF2_ONTHEPHONE | PF2_IDLE;\n\n\t\tcase PFLAGNUM_3:\n\t\t\treturn PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY\n\t\t\t\t| PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND\n\t\t\t\t| PF2_OUTTOLUNCH | PF2_ONTHEPHONE | PF2_IDLE;\n\n\t\tcase PFLAGNUM_4:\n\t\t\treturn PF4_NOCUSTOMAUTH | PF4_IMSENDUTF | PF4_SUPPORTTYPING\n\t\t\t\t| PF4_SUPPORTIDLE;\n\n\t\tcase PFLAGNUM_5:\n\t\t\treturn 0;\n\n\t\tcase PFLAG_UNIQUEIDSETTING:\n\t\t\treturn (DWORD_PTR) SIP_UNIQUEID;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tSIPE_DEBUG_INFO(\"GetCaps: unknown type <%x>\", type);\n\n\t}\n\n\treturn 0;\n}\n\nstatic HICON GetIcon( SIPPROTO *pr, int iconIndex )\n{\n\tSIPE_DEBUG_INFO(\"GetIcon: unknown index <%x>\", iconIndex);\n\treturn NULL;\n}\n\nstatic int OnEvent( SIPPROTO *pr, PROTOEVENTTYPE eventType, WPARAM wParam, LPARAM lParam )\n{\n\tSIPE_DEBUG_INFO(\"OnEvent: type <%x>\", eventType);\n\n\tswitch (eventType)\n\t{\n\t\tcase EV_PROTO_ONLOAD:\n\t\t\tOnModulesLoaded(pr);\n\t\t\tbreak;\n\n\t\tcase EV_PROTO_ONREADYTOEXIT:\n\t\t\tbreak;\n\n\t\tcase EV_PROTO_ONEXIT:\n\t\t\tbreak;\n\n\t\tcase EV_PROTO_ONRENAME:\n\t\t\tbreak;\n\n\t\tcase EV_PROTO_ONOPTIONS:\n\t\t\treturn OnOptionsInit( pr, wParam, lParam );\n\t\t\tbreak;\n\n\t\tcase EV_PROTO_ONERASE:\n\t\t\tbreak;\n\n\t}\n\n\treturn 0;\n}\n\nstatic HANDLE AddToListByEvent( SIPPROTO *pr, int flags, int iContact, HANDLE hDbEvent )\n{\n\tDBEVENTINFO dbei = {0};\n\n\tdbei.cbSize = sizeof(dbei);\n\tif ((dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0)) == -1)\n\t\treturn 0;\n\n\tdbei.pBlob = (PBYTE)_alloca(dbei.cbBlob + 1);\n\tdbei.pBlob[dbei.cbBlob] = '\\0';\n\n\tif (CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei))\n\t\treturn 0; // failed to get event\n\n\tif (strcmp(dbei.szModule, pr->proto.m_szModuleName))\n\t\treturn 0; // this event is not ours\n\n\t_NIF();\n\tSIPE_DEBUG_INFO(\"AddToListByEvent: flags <%x> iContact <%x>\", flags, iContact);\n\treturn NULL;\n}\n\nstatic int Authorize( SIPPROTO *pr, HANDLE hContact )\n{\n\t_NIF();\n\tSIPE_DEBUG_INFO_NOFORMAT(\"Authorize\");\n\treturn 0;\n}\n\nstatic int AuthDeny( SIPPROTO *pr, HANDLE hContact, const PROTOCHAR* szReason )\n{\n\t_NIF();\n\tSIPE_DEBUG_INFO(\"AuthDeny: reason <%s>\", szReason);\n\treturn 0;\n}\n\nstatic int AuthRecv( SIPPROTO *pr, HANDLE hContact, PROTORECVEVENT* evt )\n{\n\t_NIF();\n\tSIPE_DEBUG_INFO_NOFORMAT(\"AuthRecv\");\n\treturn 0;\n}\n\nstatic int AuthRequest( SIPPROTO *pr, HANDLE hContact, const PROTOCHAR* szMessage )\n{\n\t_NIF();\n\tSIPE_DEBUG_INFO(\"AuthRequest: message <%s>\", szMessage);\n\treturn 0;\n}\n\nstatic HANDLE ChangeInfo( SIPPROTO *pr, int iInfoType, void* pInfoData )\n{\n\t_NIF();\n\tSIPE_DEBUG_INFO(\"ChangeInfo: infotype <%x>\", iInfoType);\n\treturn NULL;\n}\n\nstatic int FileCancel( SIPPROTO *pr, HANDLE hContact, HANDLE hTransfer )\n{\n\t_NIF();\n\tSIPE_DEBUG_INFO_NOFORMAT(\"FileCancel\");\n\treturn 0;\n}\n\nstatic int FileResume( SIPPROTO *pr, HANDLE hTransfer, int* action, const PROTOCHAR** szFilename )\n{\n\t_NIF();\n\tSIPE_DEBUG_INFO(\"FileResume: action <%x>\", action);\n\treturn 0;\n}\n\nstatic HANDLE SearchBasic( SIPPROTO *pr, const PROTOCHAR* id )\n{\n\treturn NULL;\n}\n\nstatic HWND CreateExtendedSearchUI( SIPPROTO *pr, HWND owner )\n{\n\treturn CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_SEARCHUI), (HWND)owner, NULL, (LPARAM)pr);\n}\n\nstatic HANDLE AddToList( SIPPROTO *pr, int flags, PROTOSEARCHRESULT* psr )\n{\n\tHANDLE hContact;\n\tgchar *id = g_strdup(TCHAR2CHAR(psr->id));\n\n\t/* Prepend sip: if needed */\n\tif (strncmp(\"sip:\", id, 4)) {\n\t\tgchar *tmp = id;\n\t\tid = sip_uri_from_name(tmp);\n\t\tg_free(tmp);\n\t}\n\n\thContact = sipe_miranda_buddy_find(pr, id, NULL);\n\tif (hContact) {\n\t\tg_free(id);\n\t\treturn hContact;\n\t}\n\n\thContact = ( HANDLE )CallService( MS_DB_CONTACT_ADD, 0, 0 );\n\tCallService( MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)pr->proto.m_szModuleName );\n\tsipe_miranda_setContactString( pr, hContact, SIP_UNIQUEID, id ); // name\n\tif (psr->nick)\n\t{\n\t\t/* server_alias */\n\t\tgchar *tmp = mir_t2a(psr->nick);\n\t\tsipe_miranda_setContactStringUtf( pr, hContact, \"Nick\", tmp );\n\t\tmir_free(tmp);\n\t}\n\n\tg_free(id);\n\treturn hContact;\n}\n\nint\nsipe_miranda_window_closed(SIPPROTO *pr, WPARAM wParam, LPARAM lParam)\n{\n\tMessageWindowEventData* evt = (MessageWindowEventData*)lParam;\n\n\tSIPE_DEBUG_INFO(\"contact <%08x> module <%s> type <%02x> flags <%02x>\",\n\t\t evt->hContact, evt->szModule, evt->uType, evt->uFlags);\n\n\treturn 0;\n}\n\nstatic int\nsipe_miranda_invite_to_chat(const SIPPROTO *pr, WPARAM wParam, LPARAM lParam)\n{\n\tHANDLE hContact = (HANDLE)wParam;\n\tgchar *id = (gchar*)lParam;\n\tGCDEST gcd = {0};\n\tGCEVENT gce = {0};\n\tstruct sipe_chat_session *session;\n\tgchar *uid;\n\n\tgcd.pszModule = pr->proto.m_szModuleName;\n\tgcd.pszID = id;\n\tgcd.iType = GC_EVENT_GETITEMDATA;\n\n\tgce.cbSize = sizeof(gce);\n\tgce.pDest = &gcd;\n\n\tif ((session = (struct sipe_chat_session*)CallService( MS_GC_EVENT, 0, (LPARAM)&gce )) == NULL)\n\t{\n\t\tSIPE_DEBUG_WARNING_NOFORMAT(\"Failed to get chat session\");\n\t\treturn 0;\n\t}\n\n\tuid = sipe_miranda_getContactString(pr, hContact, SIP_UNIQUEID);\n\tsipe_core_chat_invite(pr->sip, session, uid);\n\n\tmir_free(uid);\n\tg_free(id);\n\treturn 0;\n}\n\n/*\n * Main Miranda interface\n *\n * The structures and functions that allow Miranda to recovnize and load\n * our plugin.\n */\n\n/* Plugin information structure */\nPLUGININFOEX pluginInfo = {\n\tsizeof(PLUGININFOEX),\n\t\"Office Communicator Protocol\",\n\tPLUGIN_MAKE_VERSION(0,11,2,1),\n\t\"Support for Microsoft Office Communicator\",\n\t\"Miranda support by Jochen De Smet, for core sipe support see homepage\",\n\t\"jochen.libsipe@leahnim.org\",\n\t\"(C)2009-2011\",\n\t\"https://sourceforge.net/projects/sipe\",\n\tUNICODE_AWARE,\n\t0,   //doesn't replace anything built-in\n    #if defined( _UNICODE )\n\t{ 0x842395ed, 0x4e56, 0x40e5, { 0x94, 0x25, 0x28, 0x29, 0xd8, 0xab, 0xae, 0xa5 } } // {842395ED-4E56-40e5-9425-2829D8ABAEA5}\n    #else\n\t{ 0x1ef8af37, 0xdec1, 0x4757, { 0x89, 0x78, 0xe8, 0xad, 0xd0, 0xd8, 0x6e, 0x7f } } // {1EF8AF37-DEC1-4757-8978-E8ADD0D86E7F}\n    #endif\n};\n\n__declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion)\n{\n\t// Only load for 0.8.0.29 or greater\n\t// We need the core stubs for PS_GETNAME and PS_GETSTATUS\n\tif (mirandaVersion < PLUGIN_MAKE_VERSION(0, 9, 0, 0))\n\t{\n\t\tMessageBoxA(\n\t\t\tNULL,\n\t\t\t\"SIP/Simple plugin cannot be loaded. It requires Miranda IM 0.9.0.0 or later.\",\n\t\t\t\"SIP/Simple Plugin\",\n\t\t\tMB_OK | MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST\n\t\t);\n\t\treturn NULL;\n\t}\n\n\treturn &pluginInfo;\n}\n\nstatic const MUUID interfaces[] = {MIID_PROTOCOL, MIID_LAST};\n__declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)\n{\n\treturn interfaces;\n}\n\nstatic PROTO_INTERFACE* sipsimpleProtoInit( const char* pszProtoName, const TCHAR* tszUserName )\n{\n\tgchar *tmp;\n\tSIPPROTO *pr = (SIPPROTO *)mir_calloc(sizeof(SIPPROTO));\n\tpr->proto.vtbl = (PROTO_INTERFACE_VTBL*)mir_calloc(sizeof(PROTO_INTERFACE_VTBL));\n\n\tSIPE_DEBUG_INFO(\"protoname <%s> username <%ls>\", pszProtoName, tszUserName);\n\n\tif (!InitializeCriticalSectionAndSpinCount(&pr->CriticalSection, 0))\n\t{\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"Can't initialize critical section\");\n\t\treturn NULL;\n\t}\n\n\ttmp = sipe_miranda_getString(pr, \"transport\");\n\tif (!tmp)\n\t{\n\t\tsipe_miranda_setString(pr, \"transport\", \"auto\");\n\t} else {\n\t\tmir_free(tmp);\n\t}\n\n\t/* To make it easy to detect when a SIPPROTO* isn't a SIPPROTO* */\n\tstrncpy(pr->_SIGNATURE, \"AbandonAllHope..\", sizeof(pr->_SIGNATURE));\n\n\tpr->main_thread_id = GetCurrentThreadId();\n\tpr->proto.m_iVersion = 2;\n\tpr->proto.m_szModuleName = mir_strdup(pszProtoName);\n\tpr->proto.m_tszUserName = mir_tstrdup(tszUserName);\n\tpr->proto.m_szProtoName = mir_strdup(pszProtoName);\n\n//\tset_buddies_offline(pr);\n\tfix_contact_groups(pr);\n\n\t/* Fill the function table */\n#define PROTO_FUNC(name,func) ((struct sipe_backend_private)(pr->proto)).vtbl->name = func;\n\n\tpr->proto.vtbl->AddToList              = AddToList;\n\tpr->proto.vtbl->AddToListByEvent       = AddToListByEvent;\n\n\tpr->proto.vtbl->Authorize              = Authorize;\n\tpr->proto.vtbl->AuthDeny               = AuthDeny;\n\tpr->proto.vtbl->AuthRecv               = AuthRecv;\n\tpr->proto.vtbl->AuthRequest            = AuthRequest;\n\n\tpr->proto.vtbl->ChangeInfo             = ChangeInfo;\n\n\tpr->proto.vtbl->FileAllow              = sipe_miranda_FileAllow;\n\tpr->proto.vtbl->FileCancel             = FileCancel;\n\tpr->proto.vtbl->FileDeny               = sipe_miranda_FileDeny;\n\tpr->proto.vtbl->FileResume             = FileResume;\n\n\tpr->proto.vtbl->GetCaps                = GetCaps;\n\tpr->proto.vtbl->GetIcon                = GetIcon;\n\tpr->proto.vtbl->GetInfo                = sipe_miranda_GetInfo;\n\n\tpr->proto.vtbl->SearchBasic            = SearchBasic;\n\tpr->proto.vtbl->SearchByEmail          = sipe_miranda_SearchByEmail;\n\tpr->proto.vtbl->SearchByName           = sipe_miranda_SearchByName;\n\tpr->proto.vtbl->SearchAdvanced         = sipe_miranda_SearchAdvanced;\n\tpr->proto.vtbl->CreateExtendedSearchUI = CreateExtendedSearchUI;\n\n\tpr->proto.vtbl->RecvMsg                = sipe_miranda_RecvMsg;\n\n\tpr->proto.vtbl->SendMsg                = sipe_miranda_SendMsg;\n\n\tpr->proto.vtbl->SetStatus              = sipe_miranda_SetStatus;\n\n\tpr->proto.vtbl->GetAwayMsg             = sipe_miranda_GetAwayMsg;\n\tpr->proto.vtbl->SetAwayMsg             = sipe_miranda_SetAwayMsg;\n\n\tpr->proto.vtbl->UserIsTyping           = sipe_miranda_UserIsTyping;\n\n\tpr->proto.vtbl->SendFile               = sipe_miranda_SendFile;\n\tpr->proto.vtbl->RecvFile               = sipe_miranda_RecvFile;\n\n\tpr->proto.vtbl->OnEvent                = OnEvent;\n\n\t/* Setup services */\n\tCreateProtoService(pr, PS_CREATEACCMGRUI, &SvcCreateAccMgrUI );\n\tCreateProtoService(pr, \"/InviteToChat\", &sipe_miranda_invite_to_chat);\n\tCreateProtoService(pr, \"/StartChat\",&sipe_miranda_start_chat);\n\n#define HOOKEVENT(evt,func) HookEventObj(evt, func, pr)\n\tHOOKEVENT(ME_OPT_INITIALISE,            &OnOptionsInit);\n\tHOOKEVENT(ME_CLIST_GROUPCHANGE,         &OnGroupChange);\n\tHOOKEVENT(ME_GC_EVENT,                  &OnChatEvent);\n\tHOOKEVENT(ME_CLIST_PREBUILDCONTACTMENU, &OnPreBuildContactMenu);\n\tHOOKEVENT(ME_DB_CONTACT_DELETED,        &sipe_miranda_buddy_delete);\n\tHOOKEVENT(ME_MSG_WINDOWEVENT,           &sipe_miranda_window_closed);\n\tHOOKEVENT(ME_GC_BUILDMENU,              &sipe_miranda_build_chat_menu);\n\n\treturn (PROTO_INTERFACE*)pr;\n}\n\nstatic int sipsimpleProtoUninit( PROTO_INTERFACE* _pr )\n{\n\tSIPPROTO *pr = (SIPPROTO *)_pr;\n\n\tDeleteCriticalSection(&pr->CriticalSection);\n\n\tNetlib_CloseHandle(pr->m_hServerNetlibUser);\n\tmir_free(pr->proto.m_szProtoName);\n\tmir_free(pr->proto.m_szModuleName);\n\tmir_free(pr->proto.m_tszUserName);\n\tmir_free(pr->proto.vtbl);\n\tmir_free(pr);\n\n\treturn 0;\n}\n\n__declspec(dllexport) int Load(PLUGINLINK *link)\n{\n\tPROTOCOLDESCRIPTOR pd = {0};\n\tNETLIBUSER nlu = {0};\n\tchar *tmp;\n\tWORD iptype;\n\n\tpluginLink = link;\n\n\tsipe_core_init(\"\");\n\n\tmir_getMMI( &mmi );\n\n\t/* Register the module */\n\tpd.cbSize   = sizeof(pd);\n\tpd.szName   = SIPSIMPLE_PROTOCOL_NAME;\n\tpd.type     = PROTOTYPE_PROTOCOL;\n\tpd.fnInit   = sipsimpleProtoInit;\n\tpd.fnUninit = sipsimpleProtoUninit;\n\tCallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd);\n\n\t/* Protocolwide netlib user for incoming connections (also abused for logging) */\n\tnlu.cbSize = sizeof(nlu);\n\tnlu.flags = NUF_INCOMING | NUF_TCHAR | NUF_NOOPTIONS;\n\tnlu.szSettingsModule = SIPSIMPLE_PROTOCOL_NAME;\n\tnlu.minIncomingPorts = 10;\n\n\tInitializeCriticalSectionAndSpinCount(&sipe_miranda_debug_CriticalSection, 0);\n\tsipe_miranda_incoming_netlibuser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);\n\n\ttmp = sipe_miranda_getGlobalString(\"public_ip\");\n\tif (!tmp) {\n\t\tsipe_miranda_setGlobalString(\"public_ip\", \"0.0.0.0\");\n\t} else {\n\t\tmir_free(tmp);\n\t}\n\n\tif (!sipe_miranda_getGlobalWord(\"iptype\", &iptype))\n\t{\n\t\tsipe_miranda_setGlobalWord(\"iptype\", SIPE_MIRANDA_IP_LOCAL);\n\t}\n\n\treturn 0;\n}\n\n__declspec(dllexport) int Unload(void)\n{\n\tNetlib_CloseHandle(sipe_miranda_incoming_netlibuser);\n\tsipe_miranda_incoming_netlibuser = NULL;\n\tDeleteCriticalSection(&sipe_miranda_debug_CriticalSection);\n\tsipe_core_destroy();\n\treturn 0;\n}\n\nBOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)\n{\n\thInst = hinstDLL;\n\treturn TRUE;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-private.h",
    "content": "#ifdef _MSC_VER\n#define __func__ __FUNCTION__\n#endif\n\n#define SIPSIMPLE_PROTOCOL_NAME LPGEN(\"Office Communicator\")\n#define SIP_UNIQUEID \"sip_screenname\"\n\n#define SIPE_EVENTTYPE_ERROR_NOTIFY 2002\n#define SIPE_DB_GETEVENTTEXT_ERROR_NOTIFY \"SIP/SIMPLE/GetEventTextErrorNotify\"\n#define SIPE_EVENTTYPE_INFO_NOTIFY 2003\n#define SIPE_DB_GETEVENTTEXT_INFO_NOTIFY \"SIP/SIMPLE/GetEventTextInfoNotify\"\n#define SIPE_EVENTTYPE_IM_TOPIC 2010\n#define SIPE_DB_GETEVENTTEXT_IM_TOPIC \"SIP/SIMPLE/GetEventTextIMTopic\"\n\n#define SIPE_MIRANDA_IP_LOCAL 0\n#define SIPE_MIRANDA_IP_MANUAL 1\n#define SIPE_MIRANDA_IP_PROG 2\n\ntypedef enum\n{\n        SIPE_MIRANDA_DISCONNECTED = 0, /**< Disconnected. */\n        SIPE_MIRANDA_CONNECTED,        /**< Connected.    */\n        SIPE_MIRANDA_CONNECTING        /**< Connecting.   */\n\n} sipe_miranda_ConnectionState;\n\nstruct sipe_miranda_connection_info;\n\ntypedef struct sipe_backend_private\n{\n\tPROTO_INTERFACE proto;\n\tstruct sipe_core_public *sip;\n\tCRITICAL_SECTION CriticalSection; \n\tHANDLE m_hServerNetlibUser;\n\tsipe_miranda_ConnectionState state;\n\tgboolean valid;\n\tgboolean disconnecting;\n\tHANDLE disconnect_timeout;\n\tGSList *contactMenuChatItems;\n\tDWORD main_thread_id;\n\tchar _SIGNATURE[16];\n} SIPPROTO;\n\nstruct sipe_backend_chat_session {\n\tSIPPROTO *pr;\n\tgchar *conv;\n};\n\ntypedef enum\n{\n\tSIPE_MIRANDA_INPUT_READ  = 1 << 0,  /**< A read condition.  */\n\tSIPE_MIRANDA_INPUT_WRITE = 1 << 1   /**< A write condition. */\n\n} sipe_miranda_input_condition;\n\n/** The type of callbacks to handle events on file descriptors, as passed to\n *  sipe_miranda_input_add().  The callback will receive the @c user_data\n *  passed to sipe_miranda_input_add(), the file descriptor on which the event\n *  occurred, and the condition that was satisfied to cause the callback to be\n *  invoked.\n */\ntypedef void (*sipe_miranda_input_function)(gpointer, gint, sipe_miranda_input_condition);\n\ntypedef struct sipe_miranda_sel_entry;\n\n#define CONTACTS_FOREACH(list) {               \\\n\tGSList *entry = list;                  \\\n\twhile (entry) {                        \\\n\t\tHANDLE hContact = entry->data; \\\n\t\tentry = entry->next;\n#define CONTACTS_FOREACH_END }}\n\n\ntypedef INT_PTR (*SipSimpleServiceFunc)( SIPPROTO*, WPARAM, LPARAM );\ntypedef int     (*SipSimpleEventFunc)( SIPPROTO*, WPARAM, LPARAM );\ntypedef void    (*SipSimpleThreadFunc)( SIPPROTO*, void* );\n\n#define _NI(string) SIPE_DEBUG_INFO( \"%s:%s (%d) ##NOT IMPLEMENTED## %s\", __FILE__, __FUNCTION__, __LINE__, #string )\n#define _NIF() _NI(\"\")\n\n#define _LOCK(crit) do { SIPE_DEBUG_INFO(\"[L:%08x] About to lock\", crit); EnterCriticalSection(crit); SIPE_DEBUG_INFO(\"[L:%08x] Locked\", crit); } while (0)\n#define _UNLOCK(crit) do { SIPE_DEBUG_INFO(\"[L:%08x] About to unlock\", crit); LeaveCriticalSection(crit); SIPE_DEBUG_INFO(\"[L:%08x] Unlocked\", crit); } while (0)\n#define LOCK _LOCK(&pr->CriticalSection)\n#define UNLOCK _UNLOCK(&pr->CriticalSection)\n\n#define _TRACE do { SIPE_DEBUG_INFO_NOFORMAT(\"TRACE\") } while (0);\n\nvoid sipe_miranda_close( SIPPROTO *pr);\n\nTCHAR* CHAR2TCHAR( const char *chr );\nchar* TCHAR2CHAR( const TCHAR *tchr );\nHANDLE sipe_miranda_AddEvent(const SIPPROTO *pr, HANDLE hContact, WORD wType, DWORD dwTime, DWORD flags, DWORD cbBlob, PBYTE pBlob);\n\ngchar*\t\tsipe_miranda_getContactString(const SIPPROTO *pr, HANDLE hContact, const gchar* name);\ngchar*\t\tsipe_miranda_getString(const SIPPROTO *pr, const gchar* name);\nint\t\tsipe_miranda_getStaticString(const SIPPROTO *pr, HANDLE hContact, const gchar* valueName, gchar* dest, unsigned dest_len);\ngchar*\t\tsipe_miranda_getGlobalString(const gchar* name);\nWORD\t\tsipe_miranda_getGlobalWord(const gchar* name, WORD* rv);\nWORD\t\tsipe_miranda_getWord(const SIPPROTO *pr, HANDLE hContact, const gchar* name, WORD* rv);\nDWORD\t\tsipe_miranda_getDword( const SIPPROTO *pr, HANDLE hContact, const gchar* name, DWORD* rv);\ngboolean\tsipe_miranda_getBool(const SIPPROTO *pr, const gchar *name, gboolean defval);\n\nvoid sipe_miranda_setContactString(const SIPPROTO *pr, HANDLE hContact, const gchar* name, const gchar* value);\nvoid sipe_miranda_setContactStringUtf(const SIPPROTO *pr, HANDLE hContact, const gchar* valueName, const gchar* parValue );\nvoid sipe_miranda_setString(const SIPPROTO *pr, const gchar* name, const gchar* value);\nvoid sipe_miranda_setStringUtf(const SIPPROTO *pr, const gchar* name, const gchar* value);\nvoid sipe_miranda_setGlobalString(const gchar* name, const gchar* value);\nvoid sipe_miranda_setGlobalStringUtf(const gchar* valueName, const gchar* parValue );\nint sipe_miranda_setGlobalWord(const gchar* szSetting, WORD wValue);\nint sipe_miranda_setWord(const SIPPROTO *pr, HANDLE hContact, const gchar* szSetting, WORD wValue);\nint sipe_miranda_setBool(const SIPPROTO *pr, const gchar *name, gboolean value);\n\nstruct sipe_miranda_sel_entry* sipe_miranda_input_add(HANDLE fd, sipe_miranda_input_condition cond, sipe_miranda_input_function func, gpointer user_data);\ngboolean sipe_miranda_input_remove(struct sipe_miranda_sel_entry *entry);\n\nint sipe_miranda_SendBroadcast(SIPPROTO *pr, HANDLE hContact,int type,int result,HANDLE hProcess,LPARAM lParam);\nvoid sipe_miranda_SendProtoAck( SIPPROTO *pr, HANDLE hContact, DWORD dwCookie, int nAckResult, int nAckType, const char* pszMessage);\nvoid sipe_miranda_msgbox(const char *msg, const char *caption);\ngchar *sipe_miranda_uri_self(SIPPROTO *pr);\n\nvoid sipe_miranda_login(SIPPROTO *pr);\nstruct sipe_miranda_connection_info *sipe_miranda_connect(SIPPROTO *pr, const gchar *host, int port, gboolean tls, int timeout, void (*callback)(HANDLE fd, void *data, const gchar *reason), void *data);\ngboolean sipe_miranda_cmd(gchar *cmd, gchar *buf, DWORD *maxlen);\n\ngchar* sipe_miranda_eliminate_html(const gchar *string, int len);\ngchar* sipe_miranda_html2rtf(const gchar *text);\nunsigned short sipe_miranda_network_get_port_from_fd( HANDLE fd );\nconst gchar *sipe_miranda_get_local_ip(void);\nvoid sipe_miranda_connection_destroy(SIPPROTO *pr);\nvoid sipe_miranda_connection_error_reason(SIPPROTO *pr, sipe_connection_error error, const gchar *msg);\ngpointer sipe_miranda_schedule_mseconds(void (*callback)(gpointer), guint timeout, gpointer data);\n\n/* Buddy utility functions */\nsipe_backend_buddy sipe_miranda_buddy_find(SIPPROTO *pr, const gchar *name, const gchar *group);\nGSList* sipe_miranda_buddy_find_all(SIPPROTO *pr, const gchar *buddy_name, const gchar *group_name);\n\n/* Plugin interface functions */\nint sipe_miranda_SetStatus( SIPPROTO *pr, int iNewStatus );\nint sipe_miranda_SendMsg(SIPPROTO *pr, HANDLE hContact, int flags, const char* msg);\nint sipe_miranda_RecvMsg(SIPPROTO *pr, HANDLE hContact, PROTORECVEVENT* pre);\nint sipe_miranda_SetAwayMsg(SIPPROTO *pr, int m_iStatus, const PROTOCHAR* msg);\nHANDLE sipe_miranda_GetAwayMsg( SIPPROTO *pr, HANDLE hContact );\nHANDLE sipe_miranda_SendFile( SIPPROTO *pr, HANDLE hContact, const PROTOCHAR* szDescription, PROTOCHAR** ppszFiles );\nint sipe_miranda_RecvFile( SIPPROTO *pr, HANDLE hContact, PROTOFILEEVENT* evt );\nint sipe_miranda_FileDeny( SIPPROTO *pr, HANDLE hContact, HANDLE hTransfer, const PROTOCHAR* szReason );\nHANDLE sipe_miranda_FileAllow( SIPPROTO *pr, HANDLE hContact, HANDLE hTransfer, const PROTOCHAR* szPath );\nint sipe_miranda_UserIsTyping( SIPPROTO *pr, HANDLE hContact, int type );\nint sipe_miranda_GetInfo( SIPPROTO *pr, HANDLE hContact, int infoType );\nHANDLE sipe_miranda_SearchByEmail( SIPPROTO *pr, const PROTOCHAR* email );\nHANDLE sipe_miranda_SearchByName( SIPPROTO *pr, const PROTOCHAR* nick, const PROTOCHAR* firstName, const PROTOCHAR* lastName);\nHWND sipe_miranda_SearchAdvanced( SIPPROTO *pr, HWND owner );\n\n/* Plugin event functions */\nint sipe_miranda_buddy_delete(SIPPROTO *pr, WPARAM wParam, LPARAM lParam);\n\nint SipeStatusToMiranda(guint activity);\nguint MirandaStatusToSipe(int status);\n\n"
  },
  {
    "path": "src/miranda/miranda-resource.h",
    "content": "#ifndef IDC_STATIC\n#define IDC_STATIC (-1)\n#endif\n\n#define IDD_ACCMGRUI                            135\n#define IDD_OPT_SIPSIMPLE                       137\n#define IDD_OPT_SIPSIMPLE_ABOUT                 139\n#define IDD_SEARCHUI                            142\n#define IDC_USESSO                              1000\n#define IDC_CONNTYPE                            1001\n#define IDC_AUTHTYPE                            1002\n#define IDC_ABOUTSIPE                           1003\n#define IDC_IPPROGEXE                           1005\n#define IDC_IPLOCALFOUND                        1006\n#define IDC_PASSWORD                            1020\n#define IDC_LOGIN                               1021\n#define IDC_HANDLE                              1022\n#define IDC_PUBLICIP                            1024\n#define IDC_SSO                                 1030\n#define IDC_MSO                                 1031\n#define IDC_IPLOCAL                             1040\n#define IDC_IPMANUAL                            1041\n#define IDC_IPPROG                              1042\n#define IDC_SEARCH_FN                           1044\n#define IDC_SEARCH_LN                           1045\n#define IDC_SEARCH_COMPANY                      1046\n#define IDC_SEARCH_COUNTRY                      1047\n"
  },
  {
    "path": "src/miranda/miranda-schedule.c",
    "content": "/**\n * @file miranda-schedule.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-11 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <windows.h>\n#include <stdio.h>\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n\n#include \"newpluginapi.h\"\n#include \"m_system.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"miranda-private.h\"\n\nstruct time_entry {\n\tgpointer core_data;\n\tguint timeout;\n\tHANDLE sem;\n\tgboolean cancelled;\n\tSIPPROTO *pr;\n\tvoid (*callback)(gpointer);\n\n\t/* Private. For locking only */\n\tHANDLE hDoneEvent;\n};\n\nstatic void __stdcall\ntimeout_cb_async(void *data)\n{\n\tstruct time_entry *entry = (struct time_entry*)data;\n        SIPPROTO *pr = entry->pr;\n\n\tif (entry->cancelled == TRUE)\n\t{\n\t\tSIPE_DEBUG_INFO(\"Entry <%08x> already cancelled. Not calling timeout function\", entry);\n\t} else {\n\t\tSIPE_DEBUG_INFO(\"Calling timeout function for entry <%08x>\", entry);\n\t\tLOCK;\n\t\tentry->callback(entry->core_data);\n\t\tUNLOCK;\n\t}\n\tSetEvent(entry->hDoneEvent);\n}\n\nstatic unsigned __stdcall timeoutfunc(void* data)\n{\n\tstruct time_entry *entry = (struct time_entry*)data;\n\tDWORD ret;\n        SIPPROTO *pr = entry->pr;\n\n\tSIPE_DEBUG_INFO(\"timeout start; <%08x> timeout is <%d>\", entry, entry->timeout);\n\n\tentry->sem = CreateSemaphore(NULL, 0, 100, NULL);\n\n\tret = WaitForSingleObjectEx( entry->sem, entry->timeout, FALSE);\n\tif (entry->cancelled == TRUE)\n\t{\n\t\tSIPE_DEBUG_INFO(\"<%08x> Timeout cancelled by caller\", entry);\n\t}\n\telse if (ret == WAIT_TIMEOUT)\n\t{\n\t\tSIPE_DEBUG_INFO(\"<%08x> about to run\", entry);\n\t\tif (entry->cancelled == TRUE)\n\t\t{\n\t\t\tSIPE_DEBUG_INFO(\"<%08x> Timeout cancelled by caller in the nick of time\", entry);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tentry->hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\n\t\t\tCallFunctionAsync(timeout_cb_async, entry);\n\t\t\tWaitForSingleObject(entry->hDoneEvent, INFINITE);\n\t\t\tCloseHandle(entry->hDoneEvent);\n\t\t}\n\t\tSIPE_DEBUG_INFO(\"<%08x> exiting\", entry);\n\t}\n\telse\n\t{\n\t\tSIPE_DEBUG_INFO(\"<%08x> Something unexpected happened: <%d>\", entry, ret);\n\t}\n\n\tCloseHandle(entry->sem);\n\tg_free(entry);\n\treturn 0;\n\n}\n\ngpointer sipe_miranda_schedule_mseconds(void (*callback)(gpointer),\n\t\t\t\t\tguint timeout,\n\t\t\t\t\tgpointer data)\n{\n\tstruct time_entry *entry;\n\n\tentry = g_new0(struct time_entry,1);\n\tentry->timeout = timeout;\n\tentry->core_data = data;\n\tentry->cancelled = FALSE;\n\tentry->pr = data; /* FIXME: Assumes data = SIPPROTO * */\n\tentry->callback = callback;\n\n\tSIPE_DEBUG_INFO(\"Scheduling timeout in <%u>ms for entry <%08x>\", timeout, entry);\n\tCloseHandle((HANDLE) mir_forkthreadex( timeoutfunc, entry, 65536, NULL ));\n\n\treturn entry;\n}\n\ngpointer sipe_backend_schedule_mseconds(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\tguint timeout,\n\t\t\t\t\tgpointer data)\n{\n\tstruct time_entry *entry;\n\n\tentry = g_new0(struct time_entry,1);\n\tentry->timeout = timeout;\n\tentry->core_data = data;\n\tentry->cancelled = FALSE;\n\tentry->pr = sipe_public->backend_private;\n\tentry->callback = sipe_core_schedule_execute;\n\n\tCloseHandle((HANDLE) mir_forkthreadex( timeoutfunc, entry, 65536, NULL ));\n\n\treturn entry;\n}\n\ngpointer sipe_backend_schedule_seconds(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t       guint timeout,\n\t\t\t\t       gpointer data)\n{\n\treturn sipe_backend_schedule_mseconds( sipe_public, timeout*1000, data);\n}\n\nvoid sipe_backend_schedule_cancel(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t  gpointer data)\n{\n\tstruct time_entry *entry = (struct time_entry*) data;\n\n\tif (entry && entry->sem)\n\t{\n\t\tSIPE_DEBUG_INFO(\"Cancelling timeout <%08x>\", entry);\n\t\tentry->cancelled = TRUE;\n\t\tReleaseSemaphore(entry->sem, 1, NULL);\n\t}\n\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-search.c",
    "content": "/**\n * @file miranda-search.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <windows.h>\n#include <glib.h>\n#include <stdio.h>\n\n#include \"miranda-version.h\"\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"m_system.h\"\n#include \"m_utils.h\"\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n\n#include \"miranda-private.h\"\n#include \"miranda-resource.h\"\n\nstruct sipe_backend_search_results {\n\tint dummy;\n};\n\nvoid sipe_backend_search_failed(struct sipe_core_public *sipe_public,\n\t\t\t\tSIPE_UNUSED_PARAMETER struct sipe_backend_search_token *token,\n\t\t\t\tconst gchar *msg)\n{\n\tsipe_miranda_SendBroadcast(sipe_public->backend_private, NULL, ACKTYPE_SEARCH, ACKRESULT_FAILED, (HANDLE)1, 0);\n\tsipe_backend_notify_error(sipe_public, msg, NULL);\n}\n\nstruct sipe_backend_search_results *sipe_backend_search_results_start(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t\t      SIPE_UNUSED_PARAMETER struct sipe_backend_search_token *token)\n{\n\treturn g_new0(struct sipe_backend_search_results, 1);\n}\n\nvoid sipe_backend_search_results_add(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t     struct sipe_backend_search_results *results,\n\t\t\t\t     const gchar *uri,\n\t\t\t\t     const gchar *name,\n\t\t\t\t     const gchar *company,\n\t\t\t\t     const gchar *country,\n\t\t\t\t     const gchar *email)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tPROTOSEARCHRESULT psr = { 0 };\n\tHANDLE hProcess = (HANDLE)1; /* g_hash_table_lookup(opts, \"searchid\"); */\n\tgchar **nameparts;\n\n\tpsr.cbSize = sizeof(psr);\n\tpsr.id = (PROTOCHAR*)uri;\n\tnameparts = g_strsplit_set(name, \",\", 2);\n\tpsr.nick = (FNAMECHAR*)name;\n\tpsr.firstName = (PROTOCHAR*)(nameparts[1] ? nameparts[1] : NULL);\n\tpsr.lastName = (PROTOCHAR*)nameparts[0];\n\tpsr.email = (PROTOCHAR*)email;\n\n\tsipe_miranda_SendBroadcast(pr, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, hProcess, (LPARAM) & psr);\n\tg_strfreev(nameparts);\n}\n\nvoid sipe_backend_search_results_finalize(struct sipe_core_public *sipe_public,\n\t\t\t\t\t  struct sipe_backend_search_results *results,\n\t\t\t\t\t  const gchar *description,\n\t\t\t\t\t  gboolean more)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tHANDLE hProcess = (HANDLE)1; /* g_hash_table_lookup(opts, \"searchid\"); */\n\n\tsipe_miranda_SendBroadcast(pr, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, hProcess, 0);\n\n\tg_free(results);\n}\n\nHANDLE sipe_miranda_SearchByEmail( SIPPROTO *pr, const PROTOCHAR* email )\n{\n\tchar *mail;\n\n\tSIPE_DEBUG_INFO(\"SearchByEmail: email <%S>\", email);\n\tif (!pr->sip) return NULL;\n\n\tmail = mir_t2a(email);\n\n\tLOCK;\n\tsipe_core_buddy_search(pr->sip, NULL, NULL, NULL, mail, NULL, NULL, NULL);\n\tUNLOCK;\n\n\tmir_free(mail);\n\n\treturn (HANDLE)1;\n}\n\nHANDLE sipe_miranda_SearchByName( SIPPROTO *pr, const PROTOCHAR* nick, const PROTOCHAR* firstName, const PROTOCHAR* lastName)\n{\n\tchar *given_name;\n\tchar *surname;\n\tSIPE_DEBUG_INFO(\"SearchByName: nick <%S> firstname <%S> lastname <%S>\", nick, firstName, lastName);\n\tif (!pr->sip) return NULL;\n\n\tgiven_name = mir_t2a(firstName);\n\tsurname = mir_t2a(lastName);\n\n\tLOCK;\n\tsipe_core_buddy_search(pr->sip, NULL, given_name, surname, NULL, NULL, NULL, NULL);\n\tUNLOCK;\n\n\tmir_free(given_name);\n\tmir_free(surname);\n\n\treturn (HANDLE)1;\n}\n\nHWND sipe_miranda_SearchAdvanced( SIPPROTO *pr, HWND owner )\n{\n\tchar buf[512];\n\tGHashTable *query = g_hash_table_new_full(NULL,NULL,NULL,g_free);\n\tGString *msg;\n\n\tif (!pr->sip) return NULL;\n\tmsg = g_string_new(\"SearchAdvanced: \");\n\n\tGetDlgItemTextA(owner, IDC_SEARCH_FN, buf, sizeof(buf));\n\tif (strlen(buf))\n\t{\n\t\tg_string_append_printf(msg, \"firstname <%s> \", buf);\n\t\tg_hash_table_insert(query, \"givenName\", g_strdup(buf));\n\t}\n\n\tGetDlgItemTextA(owner, IDC_SEARCH_LN, buf, sizeof(buf));\n\tif (strlen(buf))\n\t{\n\t\tg_string_append_printf(msg, \"lastname <%s> \", buf);\n\t\tg_hash_table_insert(query, \"sn\", g_strdup(buf));\n\t}\n\n\tGetDlgItemTextA(owner, IDC_SEARCH_COMPANY, buf, sizeof(buf));\n\tif (strlen(buf))\n\t{\n\t\tg_string_append_printf(msg, \"company <%s> \", buf);\n\t\tg_hash_table_insert(query, \"company\", g_strdup(buf));\n\t}\n\n\tGetDlgItemTextA(owner, IDC_SEARCH_COUNTRY, buf, sizeof(buf));\n\tif (strlen(buf))\n\t{\n\t\tg_string_append_printf(msg, \"country <%s> \", buf);\n\t\tg_hash_table_insert(query, \"c\", g_strdup(buf));\n\t}\n\n\tSIPE_DEBUG_INFO_NOFORMAT(msg->str);\n\tg_string_free(msg, TRUE);\n\n\tLOCK;\n\tsipe_backend_search_failed(pr->sip, NULL, \"Not implemented\");\n\n/*\tret = (HANDLE)sipe_core_buddy_search( pr->sip, NULL, query, sipsimple_search_contact_cb, pr); */\n\tUNLOCK;\n\n\treturn (HANDLE)1;\n\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-setting.c",
    "content": "/**\n * @file miranda-setting.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <windows.h>\n\n#include <glib.h>\n\n#include \"sipe-core.h\"\n#include \"sipe-backend.h\"\n\n#include \"miranda-version.h\"\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"m_system.h\"\n#include \"m_database.h\"\n\n#include \"miranda-private.h\"\n\n/**\n * Map sipe_setting values to miranda account setting keys\n *\n * This needs to be kept in sync with\n *\n *     api/sipe-backend.h\n */\nstatic const gchar * const setting_name[SIPE_SETTING_LAST] = {\n\t\"email_url\",      /* SIPE_SETTING_EMAIL_URL      */\n\t\"login\",          /* SIPE_SETTING_EMAIL_LOGIN    */\n\t\"password\",       /* SIPE_SETTING_EMAIL_PASSWORD */\n\t\"groupchat_user\", /* SIPE_SETTING_GROUPCHAT_USER */\n\t\"NOTDEFINED\",     /* SIPE_SETTING_RDP_CLIENT     */\n\t\"useragent\"       /* SIPE_SETTING_USER_AGENT     */\n};\n\nconst gchar *sipe_backend_setting(struct sipe_core_public *sipe_public,\n\t\t\t\t  sipe_setting type)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tgchar *ret;\n\tgchar *tmp;\n\n\tif (type == SIPE_SETTING_EMAIL_PASSWORD) {\n\t\ttmp = (char*)mir_calloc(1024);\n\n\t\tif (sipe_miranda_getStaticString(pr, NULL, \"password\", tmp, 1024 )) tmp[0] = '\\0';\n\t\tCallService(MS_DB_CRYPT_DECODESTRING, sizeof(tmp),(LPARAM)tmp);\n\n        } else {\n\t\ttmp = sipe_miranda_getString(pr, setting_name[type] );\n\t}\n\n\tret = g_strdup(tmp);\n\tmir_free(tmp);\n\treturn ret;\n\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-status.c",
    "content": "/**\n * @file miranda-status.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2015 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <windows.h>\n#include <glib.h>\n\n#include \"miranda-version.h\"\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"m_system.h\"\n\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"miranda-private.h\"\n\nguint sipe_backend_status(struct sipe_core_public *sipe_public)\n{\n\tSIPPROTO* pr = sipe_public->backend_private;\n\treturn MirandaStatusToSipe(pr->proto.m_iStatus);\n}\n\nint sipe_miranda_SetStatus( SIPPROTO *pr, int iNewStatus )\n{\n\tint oldStatus;\n\tif (!pr->m_hServerNetlibUser) return 0;\n\tif (pr->proto.m_iDesiredStatus == iNewStatus) return 0;\n\n\toldStatus = pr->proto.m_iStatus;\n\tpr->proto.m_iDesiredStatus = iNewStatus;\n\n\tSIPE_DEBUG_INFO(\"SetStatus: newstatus <%x>\", iNewStatus);\n\n\tif (iNewStatus == ID_STATUS_OFFLINE) {\n\t\tpr->disconnecting = TRUE;\n\t\tsipe_miranda_connection_destroy(pr);\n\t\tpr->valid = FALSE;\n\t\tpr->disconnecting = FALSE;\n\t} else {\n\t\tif (pr->proto.m_iStatus == ID_STATUS_OFFLINE) {\n\t\t\tpr->valid = TRUE;\n\t\t\tpr->state = SIPE_MIRANDA_CONNECTING;\n\t\t\tpr->proto.m_iStatus = ID_STATUS_CONNECTING;\n\t\t\tsipe_miranda_SendBroadcast(pr, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, pr->proto.m_iStatus);\n\t\t\tsipe_miranda_login(pr);\n\t\t} else if (pr->state == SIPE_MIRANDA_CONNECTED) {\n\t\t\tpr->proto.m_iStatus = pr->proto.m_iDesiredStatus;\n\t\t\tsipe_miranda_SendBroadcast(pr, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, pr->proto.m_iStatus);\n\t\t\tLOCK;\n\t\t\tif (pr->proto.m_iStatus != ID_STATUS_OFFLINE) {\n\t\t\t\tgchar *note = sipe_miranda_getString(pr, \"note\");\n\t\t\t\tsipe_core_status_set(pr->sip, TRUE, MirandaStatusToSipe(iNewStatus), note);\n\t\t\t\tmir_free(note);\n\t\t\t}\n\t\t\tUNLOCK;\n\t\t}\n\t}\n\n\n/*\n//Will send an ack with:\n//type=ACKTYPE_STATUS, result=ACKRESULT_SUCCESS, hProcess=(HANDLE)previousMode, lParam=newMode\n//when the change completes. This ack is sent for all changes, not just ones\n//caused by calling this function.\n//Note that newMode can be ID_STATUS_CONNECTING<=newMode<ID_STATUS_CONNECTING+\n//MAX_CONNECT_RETRIES to signify that it's connecting and it's the nth retry.\n//Protocols are initially always in offline mode.\n//Non-network-level protocol modules do not have the concept of a status and\n//should leave this service unimplemented\n//If a protocol doesn't support the specific status mode, it should pick the\n*/\n\n\treturn 0;\n}\n\ngboolean sipe_backend_status_changed(struct sipe_core_public *sipe_public,\n\t\t\t\t     guint activity,\n\t\t\t\t     const gchar *message)\n{\n\tSIPPROTO *pr = sipe_public->backend_private;\n\tint iNewStatus = SipeStatusToMiranda(activity);\n\tif (!pr->m_hServerNetlibUser) return FALSE;\n\tif (pr->proto.m_iDesiredStatus == iNewStatus) return FALSE;\n\treturn(TRUE);\n}\n\nvoid sipe_backend_status_and_note(struct sipe_core_public *sipe_public,\n\t\t\t\t  guint activity,\n\t\t\t\t  const gchar *message)\n{\n\tsipe_miranda_SetStatus(sipe_public->backend_private, SipeStatusToMiranda(activity));\n}\n"
  },
  {
    "path": "src/miranda/miranda-transport.c",
    "content": "/**\n * @file miranda-transport.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <windows.h>\n#include <stdio.h>\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n#include \"sipe-backend.h\"\n\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"m_netlib.h\"\n#include \"miranda-private.h\"\n\n#define MIRANDA_TRANSPORT ((struct sipe_transport_miranda *) conn)\n#define SIPE_TRANSPORT_CONNECTION ((struct sipe_transport_connection *) transport)\n\n#define BUFFER_SIZE_INCREMENT 4096\n\nstruct sipe_transport_miranda {\n\t/* public part shared with core */\n\tstruct sipe_transport_connection public;\n\n\t/* miranda private part */\n\ttransport_connected_cb *connected;\n\ttransport_input_cb *input;\n\ttransport_error_cb *error;\n\tHANDLE fd;\n\tstruct sipe_miranda_sel_entry *inputhandler;\n\n\tSIPPROTO *pr;\n\n\t/* Private. For locking only */\n\tHANDLE hDoneEvent;\n};\n\nstatic void __stdcall\ntransport_input_cb_async(void *data)\n{\n\tstruct sipe_transport_miranda *transport = (struct sipe_transport_miranda *)data;\n\tstruct sipe_transport_connection *conn = SIPE_TRANSPORT_CONNECTION;\n\tSIPPROTO *pr = transport->pr;\n\tLOCK;\n        transport->input(conn);\n\tUNLOCK;\n\tSetEvent(transport->hDoneEvent);\n}\n\nstatic void\nmiranda_sipe_input_cb(gpointer data,\n\t\t      SIPE_UNUSED_PARAMETER gint source,\n\t\t      SIPE_UNUSED_PARAMETER sipe_miranda_input_condition cond)\n{\n\tstruct sipe_transport_miranda *transport = (struct sipe_transport_miranda *)data;\n\tstruct sipe_transport_connection *conn = SIPE_TRANSPORT_CONNECTION;\n\tSIPPROTO *pr = transport->pr;\n\tint len;\n\tint readlen;\n\tgboolean firstread = TRUE;\n\n\tLOCK;\n\n\tif (!pr->valid)\n\t{\n\t\tUNLOCK;\n\t\treturn;\n\t}\n\n\tif (!transport->fd)\n\t{\n\t\tUNLOCK;\n\t\treturn;\n\t}\n\n\tdo {\n\t\t/* Increase input buffer size as needed */\n\t\tif (conn->buffer_length < conn->buffer_used + BUFFER_SIZE_INCREMENT) {\n\t\t\tconn->buffer_length += BUFFER_SIZE_INCREMENT;\n\t\t\tconn->buffer = g_realloc(conn->buffer, conn->buffer_length);\n\t\t\tSIPE_DEBUG_INFO(\"miranda_sipe_input_cb: new buffer length %\" G_GSIZE_FORMAT,\n\t\t\t\t\tconn->buffer_length);\n\t\t}\n\n\t\t/* Try to read as much as there is space left in the buffer */\n\t\t/* minus 1 for the string terminator */\n\t\treadlen = conn->buffer_length - conn->buffer_used - 1;\n\n\t\tlen = Netlib_Recv(transport->fd, conn->buffer + conn->buffer_used, readlen, MSG_NODUMP);\n\n\t\tif (len == SOCKET_ERROR) {\n\t\t\tSIPE_DEBUG_INFO(\"miranda_sipe_input_cb: read error\");\n\t\t\tif (transport)\n\t\t\t\ttransport->error(SIPE_TRANSPORT_CONNECTION, \"Read error\");\n\n\t\t\tUNLOCK;\n\t\t\treturn;\n\t\t} else if (firstread && (len == 0)) {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"miranda_sipe_input_cb: server has disconnected\");\n\t\t\ttransport->error(SIPE_TRANSPORT_CONNECTION, \"Server has disconnected\");\n\t\t\tUNLOCK;\n\t\t\treturn;\n\t\t}\n\n\t\tconn->buffer_used += len;\n\t\tfirstread = FALSE;\n\n\t/* Equivalence indicates that there is possibly more data to read */\n\t} while (len == readlen);\n\n\tconn->buffer[conn->buffer_used] = '\\0';\n\tUNLOCK;\n\n\ttransport->hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\n\tCallFunctionAsync(transport_input_cb_async, transport);\n\tWaitForSingleObject(transport->hDoneEvent, INFINITE);\n\tCloseHandle(transport->hDoneEvent);\n}\n\nstatic void\nconnected_callback(HANDLE fd, void* data, const gchar *reason)\n{\n\tstruct sipe_transport_miranda *transport = (struct sipe_transport_miranda*)data;\n\tSIPPROTO *pr = transport->pr;\n\n\tif (!pr) return;\n\n\tLOCK;\n\tif (!fd)\n\t{\n\t\ttransport->error(SIPE_TRANSPORT_CONNECTION, reason);\n\t} else {\n\t\ttransport->fd = fd;\n\t\ttransport->public.client_port = sipe_miranda_network_get_port_from_fd( transport->fd );\n\t\ttransport->inputhandler = sipe_miranda_input_add(transport->fd, SIPE_MIRANDA_INPUT_READ, miranda_sipe_input_cb, transport );\n\t\ttransport->connected(SIPE_TRANSPORT_CONNECTION);\n\t}\n\tUNLOCK;\n}\n\nstruct sipe_transport_connection *\nsipe_backend_transport_connect(struct sipe_core_public *sipe_public,\n\t\t\t       const sipe_connect_setup *setup)\n{\n\tstruct sipe_transport_miranda *transport = g_new0(struct sipe_transport_miranda, 1);\n\tSIPPROTO *pr = sipe_public->backend_private;\n\n\tNETLIBOPENCONNECTION ncon = {0};\n\n\ttransport->public.type      = setup->type;\n\ttransport->public.user_data = setup->user_data;\n\ttransport->connected        = setup->connected;\n\ttransport->input            = setup->input;\n\ttransport->error            = setup->error;\n\ttransport->pr               = pr;\n\n\tsipe_miranda_connect(pr, setup->server_name, setup->server_port, (setup->type == SIPE_TRANSPORT_TLS), 5, connected_callback, transport);\n\n\treturn(SIPE_TRANSPORT_CONNECTION);\n}\n\nvoid sipe_backend_transport_disconnect(struct sipe_transport_connection *conn)\n{\n\tstruct sipe_transport_miranda *transport = MIRANDA_TRANSPORT;\n\n\tSIPE_DEBUG_INFO(\"Disconnecting transport <%08x>\", transport);\n\n\tif (!transport) return;\n\n\tNetlib_CloseHandle(transport->fd);\n\ttransport->fd = NULL;\n\n\tif (transport->inputhandler)\n\t\tsipe_miranda_input_remove(transport->inputhandler);\n\n\tg_free(transport->public.buffer);\n\tg_free(transport);\n}\n\ngchar *sipe_backend_transport_ip_address(struct sipe_transport_connection *conn)\n{\n\t// @TODO: provide correct implementation for Miranda\n\treturn(\"0.0.0.0\");\n}\n\nvoid sipe_backend_transport_message(struct sipe_transport_connection *conn,\n\t\t\t\t    const gchar *buffer)\n{\n\tstruct sipe_transport_miranda *transport = MIRANDA_TRANSPORT;\n\tguint written = 0;\n\n\tdo {\n\t\tint len = Netlib_Send(transport->fd, buffer + written, strlen(buffer + written), MSG_NODUMP);\n\n\t\tif (len == SOCKET_ERROR) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_backend_transport_message: error, exiting\");\n\t\t\ttransport->error(SIPE_TRANSPORT_CONNECTION,\n\t\t\t\t\t \"Write error\");\n\t\t\treturn;\n\t\t}\n\n\t\twritten += len;\n\t} while (written < strlen(buffer));\n}\n\nvoid sipe_backend_transport_flush(struct sipe_transport_connection *conn)\n{\n\t/* N/A */\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-user.c",
    "content": "/**\n * @file miranda-user.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <windows.h>\n#include <stdio.h>\n#include <glib.h>\n\n#include \"miranda-version.h\"\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"m_database.h\"\n\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"miranda-private.h\"\n\nvoid sipe_backend_user_feedback_typing(struct sipe_core_public *sipe_public,\n\t\t\t\t       const gchar *from)\n{\n\tHANDLE hContact = sipe_backend_buddy_find( sipe_public, from, NULL );\n\n\tif (!hContact)\n\t\treturn;\n\n\tCallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hContact, (LPARAM)6);\n}\n\nvoid sipe_backend_user_feedback_typing_stop(struct sipe_core_public *sipe_public,\n\t\t\t\t\t    const gchar *from)\n{\n\tHANDLE hContact = sipe_backend_buddy_find( sipe_public, from, NULL );\n\n\tif (!hContact)\n\t\treturn;\n\n\tCallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hContact, (LPARAM)0);\n}\n\nvoid sipe_backend_user_ask(struct sipe_core_public *sipe_public,\n\t\t\t   const gchar *message,\n\t\t\t   const gchar *accept_label,\n\t\t\t   const gchar *decline_label,\n\t\t\t   gpointer key)\n{\n\t_NIF();\n}\n\nvoid sipe_backend_user_ask_choice(struct sipe_core_public *sipe_public,\n\t\t\t\t  const gchar *message,\n\t\t\t\t  GSList *choices,\n\t\t\t\t  gpointer key)\n{\n\t_NIF();\n}\n\nvoid sipe_backend_user_close_ask(gpointer key)\n{\n\t_NIF();\n}\n\nint sipe_miranda_SetAwayMsg(SIPPROTO *pr,\n\t       int m_iStatus,\n\t       const PROTOCHAR* msg)\n{\n\tconst gchar *note = TCHAR2CHAR(msg);\n\n\tSIPE_DEBUG_INFO(\"SetAwayMsg: status <%x> msg <%ls>\", m_iStatus, msg);\n\tsipe_miranda_setString(pr, \"note\", note);\n\tLOCK;\n\tif (pr->state == SIPE_MIRANDA_CONNECTED)\n\t\tsipe_core_status_set(pr->sip, FALSE, MirandaStatusToSipe(pr->proto.m_iStatus), note);\n\tUNLOCK;\n\treturn 0;\n}\n\nint sipe_miranda_UserIsTyping( SIPPROTO *pr, HANDLE hContact, int type )\n{\n\tSIPE_DEBUG_INFO(\"type <%x>\", type);\n\tif (hContact)\n\t{\n\t\tDBVARIANT dbv;\n\t\tchar *name;\n\n\t\tif ( !DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv )) {\n\t\t\tname = g_strdup(dbv.pszVal);\n\t\t\tDBFreeVariant(&dbv);\n\t\t} else {\n\t\t\treturn 1;\n\t\t}\n\n\t\tswitch (type) {\n\t\t\tcase PROTOTYPE_SELFTYPING_ON:\n\t\t\t\tLOCK;\n\t\t\t\tsipe_core_user_feedback_typing(pr->sip, name, TRUE);\n\t\t\t\tUNLOCK;\n\t\t\t\tg_free(name);\n\t\t\t\treturn 0;\n\n\t\t\tcase PROTOTYPE_SELFTYPING_OFF:\n\t\t\t\t/* Not supported anymore? */\n\t\t\t\tLOCK;\n\t\t\t\tsipe_core_user_feedback_typing(pr->sip, name, FALSE);\n\t\t\t\tUNLOCK;\n\t\t\t\tg_free(name);\n\t\t\t\treturn 0;\n\t\t}\n\n\t\tg_free(name);\n\t}\n\n\treturn 1;\n}\n\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-utils.c",
    "content": "/**\n * @file miranda-utils.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-11 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <windows.h>\n\n#include \"miranda-version.h\"\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"m_database.h\"\n#include \"m_netlib.h\"\n#include \"m_langpack.h\"\n#include \"m_protomod.h\"\n\n#include \"glib.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"miranda-private.h\"\n\n/*\n * Table to hold HTML entities we want to convert\n */\nstatic GHashTable *entities = NULL;\n\n\n/**\n * Various shortcut functions to get database values\n */\ngchar*\nsipe_miranda_getGlobalString(const gchar* name)\n{\n\treturn DBGetString( NULL, SIPSIMPLE_PROTOCOL_NAME, name );\n}\n\ngchar*\nsipe_miranda_getContactString(const SIPPROTO *pr, HANDLE hContact, const gchar* name)\n{\n\treturn DBGetString( hContact, pr->proto.m_szModuleName, name );\n}\n\ngchar*\nsipe_miranda_getString(const SIPPROTO *pr, const gchar* name)\n{\n\treturn sipe_miranda_getContactString( pr, NULL, name );\n}\n\nDWORD\nsipe_miranda_getDword(const SIPPROTO *pr, HANDLE hContact, const gchar* name, DWORD* rv)\n{\n\tDBVARIANT dbv;\n\tDBCONTACTGETSETTING cgs;\n\n\tcgs.szModule = pr->proto.m_szModuleName;\n\tcgs.szSetting = name;\n\tcgs.pValue=&dbv;\n\tif(CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&cgs))\n\t\treturn 0;\n\n\tif (rv) {\n\t\t*rv = dbv.dVal;\n\t\treturn 1;\n\t} else {\n\t\treturn dbv.dVal;\n\t}\n\n}\n\nWORD\nsipe_miranda_getGlobalWord(const gchar* name, WORD* rv)\n{\n\tDBVARIANT dbv;\n\tDBCONTACTGETSETTING cgs;\n\n\tcgs.szModule = SIPSIMPLE_PROTOCOL_NAME;\n\tcgs.szSetting = name;\n\tcgs.pValue=&dbv;\n\tif(CallService(MS_DB_CONTACT_GETSETTING, (WPARAM)NULL,(LPARAM)&cgs))\n\t\treturn 0;\n\n\tif (rv) {\n\t\t*rv = dbv.wVal;\n\t\treturn 1;\n\t} else {\n\t\treturn dbv.wVal;\n\t}\n\n}\n\nWORD\nsipe_miranda_getWord(const SIPPROTO *pr, HANDLE hContact, const gchar* name, WORD* rv)\n{\n\tDBVARIANT dbv;\n\tDBCONTACTGETSETTING cgs;\n\n\tcgs.szModule = pr->proto.m_szModuleName;\n\tcgs.szSetting = name;\n\tcgs.pValue=&dbv;\n\tif(CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&cgs))\n\t\treturn 0;\n\n\tif (rv) {\n\t\t*rv = dbv.wVal;\n\t\treturn 1;\n\t} else {\n\t\treturn dbv.wVal;\n\t}\n\n}\n\ngboolean\nsipe_miranda_getBool(const SIPPROTO *pr, const gchar *name, gboolean defval)\n{\n\tWORD ret;\n\n\tif (sipe_miranda_getWord( pr, NULL, name, &ret ))\n\t\treturn ret?TRUE:FALSE;\n\n\treturn defval;\n}\n\nint\nsipe_miranda_getStaticString(const SIPPROTO *pr, HANDLE hContact, const gchar* valueName, gchar* dest, unsigned dest_len)\n{\n\tDBVARIANT dbv;\n\tDBCONTACTGETSETTING sVal;\n\n\tdbv.pszVal = dest;\n\tdbv.cchVal = (WORD)dest_len;\n\tdbv.type = DBVT_ASCIIZ;\n\n\tsVal.pValue = &dbv;\n\tsVal.szModule = pr->proto.m_szModuleName;\n\tsVal.szSetting = valueName;\n\tif (CallService(MS_DB_CONTACT_GETSETTINGSTATIC, (WPARAM)hContact, (LPARAM)&sVal) != 0)\n\t\treturn 1;\n\n\treturn (dbv.type != DBVT_ASCIIZ);\n}\n\n/**\n * Various shortcut functions to set database values\n */\nvoid\nsipe_miranda_setGlobalString(const gchar* name, const gchar* value)\n{\n\tDBWriteContactSettingString(NULL, SIPSIMPLE_PROTOCOL_NAME, name, value);\n}\n\nvoid\nsipe_miranda_setGlobalStringUtf(const gchar* valueName, const gchar* parValue )\n{\n\tDBWriteContactSettingStringUtf( NULL, SIPSIMPLE_PROTOCOL_NAME, valueName, parValue );\n}\n\nvoid\nsipe_miranda_setContactString(const SIPPROTO *pr, HANDLE hContact, const gchar* name, const gchar* value)\n{\n\tDBWriteContactSettingString(hContact, pr->proto.m_szModuleName, name, value);\n}\n\nvoid\nsipe_miranda_setContactStringUtf(const SIPPROTO *pr, HANDLE hContact, const gchar* valueName, const gchar* parValue )\n{\n\tDBWriteContactSettingStringUtf( hContact, pr->proto.m_szModuleName, valueName, parValue );\n}\n\nvoid\nsipe_miranda_setString(const SIPPROTO *pr, const gchar* name, const gchar* value)\n{\n\tsipe_miranda_setContactString( pr, NULL, name, value );\n}\n\nvoid\nsipe_miranda_setStringUtf(const SIPPROTO *pr, const gchar* name, const gchar* value)\n{\n\tsipe_miranda_setContactStringUtf( pr, NULL, name, value );\n}\n\nint\nsipe_miranda_setGlobalWord(const gchar* szSetting, WORD wValue)\n{\n\treturn DBWriteContactSettingWord(NULL, SIPSIMPLE_PROTOCOL_NAME, szSetting, wValue);\n}\n\nint\nsipe_miranda_setWord(const SIPPROTO *pr, HANDLE hContact, const gchar* szSetting, WORD wValue)\n{\n\treturn DBWriteContactSettingWord(hContact, pr->proto.m_szModuleName, szSetting, wValue);\n}\n\nint\nsipe_miranda_setBool(const SIPPROTO *pr, const gchar *name, gboolean value)\n{\n\treturn DBWriteContactSettingWord(NULL, pr->proto.m_szModuleName, name, value?1:0);\n}\n\n/*\n * Initialize our table of HTML entities\n */\n#define ADDENT(a,b) g_hash_table_insert(entities, a, b)\nstatic void\ninitEntities(void)\n{\n\tentities = g_hash_table_new(g_str_hash, g_str_equal);\n\n\tADDENT(\"nbsp\",\" \");\n\tADDENT(\"quot\",\"\\\"\");\n\tADDENT(\"lt\",\"<\");\n\tADDENT(\"gt\",\">\");\n\tADDENT(\"apos\",\"'\");\n}\n\n/*\n * WARNING: Returns miranda-allocated string, not glib one\n */\ngchar*\nsipe_miranda_eliminate_html(const gchar *string, int len)\n{\n\tgchar *tmp = (char*)mir_alloc(len + 1);\n\tint i,j;\n\tBOOL tag = FALSE;\n\tgchar *res;\n\n\tif (!entities)\n\t\tinitEntities();\n\n\tfor (i=0,j=0;i<len;i++)\n\t{\n\t\tif (!tag && string[i] == '<')\n\t\t{\n\t\t\tif ((i + 4 <= len) && (!_strnicmp(string + i, \"<br>\", 4) || !_strnicmp(string + i, \"<br/>\", 5)))\n\t\t\t{ // insert newline\n\t\t\t\ttmp[j] = '\\r';\n\t\t\t\tj++;\n\t\t\t\ttmp[j] = '\\n';\n\t\t\t\tj++;\n\t\t\t}\n\t\t\ttag = TRUE;\n\t\t}\n\t\telse if (tag && string[i] == '>')\n\t\t{\n\t\t\ttag = FALSE;\n\t\t}\n\t\telse if (!tag)\n\t\t{\n\t\t\tchar *tkend;\n\n\t\t\tif ((string[i] == '&') && (tkend = strstr((char*)&string[i], \";\")))\n\t\t\t{\n\t\t\t\tgchar *rep;\n\t\t\t\tgchar c = *tkend;\n\t\t\t\t*tkend = '\\0';\n\n\t\t\t\trep = (char*)g_hash_table_lookup(entities, &string[i+1]);\n\n\t\t\t\tif (rep)\n\t\t\t\t{\n\t\t\t\t\tstrcpy(&tmp[j], rep);\n\t\t\t\t\tj += strlen(rep);\n\t\t\t\t\ti += strlen(&string[i]);\n\t\t\t\t\t*tkend = c;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t*tkend = c;\n\t\t\t\t\ttmp[j] = string[i];\n\t\t\t\t\tj++;\n\t\t\t\t}\n\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttmp[j] = string[i];\n\t\t\t\tj++;\n\t\t\t}\n\t\t}\n\t\ttmp[j] = '\\0';\n\t}\n\tres = tmp;\n\n\treturn res;\n}\n\nunsigned short\nsipe_miranda_network_get_port_from_fd( HANDLE fd )\n{\n\tSOCKET sock = CallService(MS_NETLIB_GETSOCKET, (WPARAM)fd, (LPARAM)0);\n\n\tstruct sockaddr_in sockbuf;\n\tint namelen = sizeof(sockbuf);\n\tgetsockname(sock, (struct sockaddr *)&sockbuf, &namelen);\n\tSIPE_DEBUG_INFO(\"<%x> <%x><%x><%s>\", namelen, sockbuf.sin_family, sockbuf.sin_port, inet_ntoa(sockbuf.sin_addr) );\n\n\treturn sockbuf.sin_port;\n}\n\n/* Misc functions */\nTCHAR _tcharbuf[32768];\nTCHAR* CHAR2TCHAR( const char *chr ) {\n#ifdef UNICODE\n\tif (!chr) return NULL;\n\tmbstowcs( _tcharbuf, chr, strlen(chr)+1 );\n\treturn _tcharbuf;\n#else\n\treturn chr;\n#endif\n}\n\nchar _charbuf[32768];\nchar* TCHAR2CHAR( const TCHAR *tchr ) {\n#ifdef UNICODE\n\tif (!tchr) return NULL;\n\twcstombs( _charbuf, tchr, wcslen(tchr)+1 );\n\treturn _charbuf;\n#else\n\treturn tchr;\n#endif\n}\n\nHANDLE\nsipe_miranda_AddEvent(const SIPPROTO *pr, HANDLE hContact, WORD wType, DWORD dwTime, DWORD flags, DWORD cbBlob, PBYTE pBlob)\n{\n\tDBEVENTINFO dbei = {0};\n\n\tdbei.cbSize = sizeof(dbei);\n\tdbei.szModule = pr->proto.m_szModuleName;\n\tdbei.timestamp = dwTime;\n\tdbei.flags = flags;\n\tdbei.eventType = wType;\n\tdbei.cbBlob = cbBlob;\n\tdbei.pBlob = pBlob;\n\n\treturn (HANDLE)CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei);\n}\n\nstruct msgboxinfo {\n\tTCHAR *msg;\n\tTCHAR *caption;\n};\n\nstatic unsigned __stdcall\nmsgboxThread(void* arg)\n{\n\tstruct msgboxinfo *err = (struct msgboxinfo*)arg;\n\tif (!err)\n\t\treturn 0;\n\n\tMessageBox(NULL, err->msg, err->caption, MB_OK);\n\tmir_free(err->msg);\n\tmir_free(err->caption);\n\tg_free(err);\n\treturn 0;\n}\n\nvoid\nsipe_miranda_msgbox(const char *msg, const char *caption)\n{\n\tstruct msgboxinfo *info = g_new(struct msgboxinfo,1);\n\n\tinfo->msg = mir_a2t(msg);\n\tinfo->caption = mir_a2t(caption);\n\n\tCloseHandle((HANDLE) mir_forkthreadex( msgboxThread, info, 8192, NULL ));\n}\n\nchar* sipe_miranda_acktype_strings[] = {\n\t\"ACKTYPE_MESSAGE\",\t\"ACKTYPE_URL\",\t\t\"ACKTYPE_FILE\",\n\t\"ACKTYPE_CHAT\",\t\t\"ACKTYPE_AWAYMSG\",\t\"ACKTYPE_AUTHREQ\",\n\t\"ACKTYPE_ADDED\",\t\"ACKTYPE_GETINFO\",\t\"ACKTYPE_SETINFO\",\n\t\"ACKTYPE_LOGIN\",\t\"ACKTYPE_SEARCH\",\t\"ACKTYPE_NEWUSER\",\n\t\"ACKTYPE_STATUS\",\t\"ACKTYPE_CONTACTS\",\t\"ACKTYPE_AVATAR\",\n\t\"ACKTYPE_EMAIL\" };\n\nchar* sipe_miranda_ackresult_strings[] = {\n\t\"ACKRESULT_SUCCESS\",\t\"ACKRESULT_FAILED\",\t\"ACKRESULT_CONNECTING\",\n\t\"ACKRESULT_CONNECTED\",\t\"ACKRESULT_INITIALISING\",\t\"ACKRESULT_SENTREQUEST\",\n\t\"ACKRESULT_DATA\",\t\"ACKRESULT_NEXTFILE\",\t\"ACKRESULT_FILERESUME\",\n\t\"ACKRESULT_DENIED\",\t\"ACKRESULT_STATUS\",\t\"ACKRESULT_LISTENING\",\n\t\"ACKRESULT_CONNECTPROXY\",\t\"ACKRESULT_SEARCHRESULT\" };\n\nint\nsipe_miranda_SendBroadcast(SIPPROTO *pr, HANDLE hContact,int type,int result,HANDLE hProcess,LPARAM lParam)\n{\n\tACKDATA ack = {0};\n\n\tack.cbSize = sizeof(ACKDATA);\n\tack.szModule = pr->proto.m_szModuleName;\n\tack.hContact = hContact;\n\tack.type = type;\n\tack.result = result;\n\tack.hProcess = hProcess;\n\tack.lParam = lParam;\n\n\tSIPE_DEBUG_INFO(\"broadcasting contact <%08x> type <%d:%s> result <%d:%s> par1 <%08x> par2 <%08x>\",\n\t\thContact,\n\t\ttype, sipe_miranda_acktype_strings[type],\n\t\tresult, sipe_miranda_ackresult_strings[result>99 ? result-98 : result],\n\t\thProcess, lParam);\n\n\treturn CallServiceSync(MS_PROTO_BROADCASTACK,0,(LPARAM)&ack);\n}\n\nstruct sipe_miranda_connection_info {\n\tSIPPROTO *pr;\n\tgchar *server_name;\n\tint server_port;\n\tint timeout;\n\tgboolean tls;\n\tvoid (*callback)(HANDLE fd, void *data, const gchar *reason);\n\tvoid *data;\n\n\t/* Private. For locking only */\n\tHANDLE hDoneEvent;\n\tHANDLE fd;\n\tconst gchar *reason;\n};\n\nstatic void __stdcall\nconnection_cb_async(void *data)\n{\n\tstruct sipe_miranda_connection_info *entry = (struct sipe_miranda_connection_info*)data;\n\tSIPE_DEBUG_INFO(\"[C:%08x] Calling real connected function\", entry);\n\tentry->callback(entry->fd, entry->data, entry->reason);\n\tSetEvent(entry->hDoneEvent);\n}\n\nstatic unsigned __stdcall\nsipe_miranda_connected_callback(void* data)\n{\n\tstruct sipe_miranda_connection_info *info = (struct sipe_miranda_connection_info*)data;\n\tSIPPROTO *pr = info->pr;\n\tNETLIBOPENCONNECTION ncon = {0};\n\n\tncon.cbSize = sizeof(ncon);\n\tncon.flags = NLOCF_V2;\n\tncon.szHost = info->server_name;\n\tncon.wPort = info->server_port;\n\tncon.timeout = info->timeout;\n\n\tinfo->fd = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)pr->m_hServerNetlibUser, (LPARAM)&ncon);\n\tif (info->fd == NULL)  {\n\t\tSIPE_DEBUG_INFO(\"[C:%08x] Connection to <%s:%d> failed\", info, info->server_name, info->server_port);\n\t\tinfo->reason = \"Connection failed\";\n\n\t} else {\n\t\tSIPE_DEBUG_INFO(\"[C:%08x] connected <%d>\", info, (int)info->fd);\n\n\t\tif (info->tls)\n\t\t{\n\t\t\tif (!CallService(MS_NETLIB_STARTSSL, (WPARAM)info->fd, 0))\n\t\t\t{\n\t\t\t\tNetlib_CloseHandle(info->fd);\n\t\t\t\tinfo->fd = NULL;\n\t\t\t\tinfo->reason = \"Failed to enabled SSL\";\n\t\t\t} else {\n\t\t\t\tSIPE_DEBUG_INFO(\"[C:%08x] SSL enabled\", info);\n\t\t\t}\n\t\t} else {\n\t\t\tinfo->reason = NULL;\n\t\t}\n\t}\n\n\tinfo->hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\n\tCallFunctionAsync(connection_cb_async, info);\n\tWaitForSingleObject(info->hDoneEvent, INFINITE);\n\tCloseHandle(info->hDoneEvent);\n\n\tg_free(info->server_name);\n\tg_free(info);\n\treturn 0;\n}\n\nstruct sipe_miranda_connection_info *\nsipe_miranda_connect(SIPPROTO *pr,\n\t\t     const gchar *host,\n\t\t     int port,\n\t\t     gboolean tls,\n\t\t     int timeout,\n\t\t     void (*callback)(HANDLE fd, void *data, const gchar *reason),\n\t\t     void *data)\n{\n\tstruct sipe_miranda_connection_info *info = g_new0(struct sipe_miranda_connection_info, 1);\n\tSIPE_DEBUG_INFO(\"[C:%08x] Connecting to <%s:%d> tls <%d> timeout <%d>\", info, host, port, tls, timeout);\n\n\tinfo->pr = pr;\n\tinfo->server_name = g_strdup(host);\n\tinfo->server_port = port;\n\tinfo->timeout = timeout;\n\tinfo->tls = tls;\n\tinfo->callback = callback;\n\tinfo->data = data;\n\n\tCloseHandle((HANDLE) mir_forkthreadex( sipe_miranda_connected_callback, info, 65536, NULL ));\n\n\treturn info;\n}\n\nstruct sipe_miranda_ack_args\n{\n        HANDLE hContact;\n        int    nAckType;\n        int    nAckResult;\n        HANDLE hSequence;\n        gchar *pszMessage;\n\tconst gchar *modname;\n};\n\nstatic unsigned __stdcall\nProtocolAckThread(struct sipe_miranda_ack_args* args)\n{\n\tProtoBroadcastAck(args->modname, args->hContact, args->nAckType, args->nAckResult, args->hSequence, (LPARAM)args->pszMessage);\n\n\tif (args->nAckResult == ACKRESULT_SUCCESS)\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"ProtocolAckThread: Sent ACK\");\n\telse if (args->nAckResult == ACKRESULT_FAILED)\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"ProtocolAckThread: Sent NACK\");\n\n\tg_free(args->pszMessage);\n\tg_free(args);\n\treturn 0;\n}\n\nvoid\nsipe_miranda_SendProtoAck( SIPPROTO *pr, HANDLE hContact, DWORD dwCookie, int nAckResult, int nAckType, const char* pszMessage)\n{\n\tstruct sipe_miranda_ack_args* pArgs = g_new0(struct sipe_miranda_ack_args, 1);\n\n\tpArgs->hContact = hContact;\n\tpArgs->hSequence = (HANDLE)dwCookie;\n\tpArgs->nAckResult = nAckResult;\n\tpArgs->nAckType = nAckType;\n\tpArgs->pszMessage = g_strdup(pszMessage);\n\tpArgs->modname = pr->proto.m_szModuleName;\n\n\tCloseHandle((HANDLE) mir_forkthreadex(ProtocolAckThread, pArgs, 65536, NULL));\n}\n\ngboolean\nsipe_miranda_cmd(gchar *cmd, gchar *buf, DWORD *maxlen)\n{\n\tSTARTUPINFOA si = {0};\n\tPROCESS_INFORMATION pi = {0};\n\tSECURITY_ATTRIBUTES sa = {0};\n\tHANDLE rd,wr;\n\n\tsa.nLength = sizeof(sa);\n\tsa.bInheritHandle = TRUE;\n\n\tif (!CreatePipe(&rd, &wr, &sa, 0))\n\t{\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"Could not create pipe\");\n\t\treturn FALSE;\n\t}\n\n\tSetHandleInformation(rd, HANDLE_FLAG_INHERIT, 0);\n\n\tsi.cb = sizeof(si);\n\tsi.dwFlags = STARTF_USESTDHANDLES;\n\tsi.hStdOutput = wr;\n\tsi.hStdError = wr;\n\tsi.hStdInput = GetStdHandle(STD_INPUT_HANDLE);\n\n\tif (!CreateProcessA(NULL, cmd, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))\n\t{\n\t\tSIPE_DEBUG_INFO(\"Could not run child program <%s> (%d)\", cmd, GetLastError());\n\t\treturn FALSE;\n\t}\n\n\tCloseHandle(pi.hThread);\n\tCloseHandle(pi.hProcess);\n\n\tif (!ReadFile(rd, buf, *maxlen, maxlen, NULL))\n\t{\n\t\tSIPE_DEBUG_INFO(\"Could not read from child program <%s>\", cmd);\n\t\treturn FALSE;\n\t}\n\n\treturn TRUE;\n}\n\ngchar*\nsipe_miranda_html2rtf(const gchar *text)\n{\n\tconst gchar *intro = \"{\\\\rtf1\\\\ansi\";\n\tconst gchar *link1 = \"{\\\\field{\\\\*\\\\fldinst{HYPERLINK \\\"\";\n\tconst gchar *link2 = \"}}{\\\\fldrslt {\\\\ul\\\\cf2 \";\n\tgchar *tmp = g_malloc(strlen(text)+1);\n\tint maxlen = strlen(text);\n\tconst gchar *i = text;\n\tint j = 0;\n\tgboolean skiptag = FALSE;\n\tgboolean escape = FALSE;\n\tgboolean copystring = FALSE;\n\tgboolean link_stage2 = FALSE;\n\n\tstrncpy(tmp+j, intro, maxlen-j);\n\tj += strlen(intro);\n\n\twhile (*i)\n\t{\n\t\tif (j+100>=maxlen) /* 100 is max substitution size */\n\t\t{\n\t\t\tmaxlen += 128;\n\t\t\ttmp = g_realloc(tmp, maxlen);\n\t\t}\n\t\tif (skiptag && !escape && *i != '>') {\n\t\t\ti++;\n\t\t} else if (skiptag && !escape) {\n\t\t\ti++;\n\t\t\tskiptag = FALSE;\n\t\t} else if (copystring) {\n\t\t\tif (!escape && *i == '\"') copystring = FALSE;\n\t\t\tif (escape) escape = FALSE;\n\t\t\telse if (*i == '\\\\') escape = TRUE;\n\t\t\t*(tmp+j) = *i;\n\t\t\tj++;\n\t\t\ti++;\n\t\t} else if (link_stage2) {\n\t\t\tstrcpy(tmp+j, link2);\n\t\t\tj += strlen(link2);\n\t\t\tlink_stage2 = FALSE;\n\t\t\tskiptag = TRUE;\n\t\t} else if (g_str_has_prefix(i,\"<br/>\"))\t{\n\t\t\tstrcpy(tmp+j, \"\\\\par\\n\");\n\t\t\tj += 5;\n\t\t\ti += 5;\n\t\t} else if (g_str_has_prefix(i,\"<b>\")) {\n\t\t\tstrcpy(tmp+j, \"\\\\b\");\n\t\t\tj += 2;\n\t\t\ti += 3;\n\t\t} else if (g_str_has_prefix(i,\"</b>\")) {\n\t\t\tstrcpy(tmp+j, \"\\\\b0\");\n\t\t\tj += 3;\n\t\t\ti += 4;\n\t\t} else if (g_str_has_prefix(i,\"<font size=\\\"\")) {\n\t\t\tstrcpy(tmp+j, \"\\\\fs36\");\n\t\t\tj += 5;\n\t\t\ti += 12;\n\t\t\tskiptag = TRUE;\n\t\t} else if (g_str_has_prefix(i,\"</font>\")) {\n\t\t\tstrcpy(tmp+j, \"\\\\fs20\");\n\t\t\tj += 5;\n\t\t\ti += 7;\n\t\t} else if (g_str_has_prefix(i,\"<a href=\\\"\")) {\n\t\t\tstrcpy(tmp+j, link1);\n\t\t\tj += strlen(link1);\n\t\t\tlink_stage2 = TRUE;\n\t\t\tcopystring = TRUE;\n\t\t\ti += 9;\n\t\t} else if (g_str_has_prefix(i,\"</a>\")) {\n\t\t\tstrcpy(tmp+j, \"}}}\\\\cf0 \");\n\t\t\tj += 7;\n\t\t\ti += 4;\n\t\t} else if (*i == '<') {\n\t\t\tskiptag = TRUE;\n\t\t} else {\n\t\t\tif (escape) {\n\t\t\t\tescape = FALSE;\n\t\t\t} else if (*i == '\\\\') {\n\t\t\t\tescape = TRUE;\n\t\t\t}\n\t\t\tif (!skiptag)\n\t\t\t{\n\t\t\t\t*(tmp+j) = *i;\n\t\t\t\tj++;\n\t\t\t}\n\t\t\ti++;\n\t\t}\n\t}\n\t*(tmp+j++) = '}';\n\t*(tmp+j++) = '\\0';\n\ttmp = g_realloc(tmp, j);\n\treturn tmp;\n}\n\nint SipeStatusToMiranda(guint activity) {\n\n\tswitch (activity)\n\t{\n\tcase SIPE_ACTIVITY_OFFLINE:\n\t\treturn ID_STATUS_OFFLINE;\n\tcase SIPE_ACTIVITY_AVAILABLE:\n\t\treturn ID_STATUS_ONLINE;\n\tcase SIPE_ACTIVITY_ON_PHONE:\n\t\treturn ID_STATUS_ONTHEPHONE;\n\tcase SIPE_ACTIVITY_DND:\n\tcase SIPE_ACTIVITY_URGENT_ONLY:\n\t\treturn ID_STATUS_DND;\n\tcase SIPE_ACTIVITY_AWAY:\n\tcase SIPE_ACTIVITY_OOF:\n\t\treturn ID_STATUS_NA;\n\tcase SIPE_ACTIVITY_LUNCH:\n\t\treturn ID_STATUS_OUTTOLUNCH;\n\tcase SIPE_ACTIVITY_BUSY:\n\tcase SIPE_ACTIVITY_IN_MEETING:\n\tcase SIPE_ACTIVITY_IN_CONF:\n\t\treturn ID_STATUS_OCCUPIED;\n\tcase SIPE_ACTIVITY_INVISIBLE:\n\t\treturn ID_STATUS_INVISIBLE;\n\tcase SIPE_ACTIVITY_BRB:\n\t\treturn ID_STATUS_AWAY;\n\tcase SIPE_ACTIVITY_UNSET:\n\t\treturn ID_STATUS_OFFLINE;\n\tcase SIPE_ACTIVITY_INACTIVE:\n\tcase SIPE_ACTIVITY_ONLINE:\n\tcase SIPE_ACTIVITY_BUSYIDLE:\n\t\treturn ID_STATUS_ONLINE;\n\tdefault:\n\t\t/* None of those? We'll have to guess. Online seems ok. */\n\t\treturn ID_STATUS_ONLINE;\n\t}\n\n\t/* Don't have SIPE equivalent of these:\n\t\t- ID_STATUS_FREECHAT\n\t*/\n\n}\n\nguint MirandaStatusToSipe(int status) {\n\n\tswitch (status)\n\t{\n\tcase ID_STATUS_OFFLINE:\n\t\treturn SIPE_ACTIVITY_OFFLINE;\n\n\tcase ID_STATUS_ONLINE:\n\tcase ID_STATUS_FREECHAT:\n\t\treturn SIPE_ACTIVITY_AVAILABLE;\n\n\tcase ID_STATUS_ONTHEPHONE:\n\t\treturn SIPE_ACTIVITY_ON_PHONE;\n\n\tcase ID_STATUS_DND:\n\t\treturn SIPE_ACTIVITY_DND;\n\n\tcase ID_STATUS_NA:\n\t\treturn SIPE_ACTIVITY_AWAY;\n\n\tcase ID_STATUS_AWAY:\n\t\treturn SIPE_ACTIVITY_BRB;\n\n\tcase ID_STATUS_OUTTOLUNCH:\n\t\treturn SIPE_ACTIVITY_LUNCH;\n\n\tcase ID_STATUS_OCCUPIED:\n\t\treturn SIPE_ACTIVITY_BUSY;\n\n\tcase ID_STATUS_INVISIBLE:\n\t\treturn SIPE_ACTIVITY_INVISIBLE;\n\n\tdefault:\n\t\treturn SIPE_ACTIVITY_UNSET;\n\t}\n\n}\n\ngchar *sipe_miranda_uri_self(SIPPROTO *pr) {\n\tgchar *username = sipe_miranda_getString(pr, \"username\");\n\tgchar *uri = g_strdup_printf(\"sip:%s\", username);\n\tmir_free(username);\n\treturn uri;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/miranda/miranda-version.h",
    "content": "/**\n * @file miranda-version.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#define MIRANDA_VER 0x900\n\n"
  },
  {
    "path": "src/miranda/miranda.rc",
    "content": "// Generated by ResEdit 1.5.4\n// Copyright (C) 2006-2010\n// http://www.resedit.net\n\n#include <windows.h>\n#include <commctrl.h>\n#include <richedit.h>\n#include \"miranda-resource.h\"\n\n\n\n\n//\n// Dialog resources\n//\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\nIDD_ACCMGRUI DIALOGEX 0, 0, 186, 134\nSTYLE DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW\nEXSTYLE WS_EX_CONTROLPARENT\nFONT 8, \"MS Shell Dlg\", 400, 0, 1\n{\n    LTEXT           \"Username:\", IDC_STATIC, 5, 5, 45, 12, SS_LEFT\n    EDITTEXT        IDC_HANDLE, 50, 5, 116, 12, ES_AUTOHSCROLL\n    AUTORADIOBUTTON \"Use windows credentials\", IDC_SSO, 5, 20, 94, 8\n    AUTORADIOBUTTON \"Manually specify parameters\", IDC_MSO, 5, 35, 105, 8\n    LTEXT           \"Login:\", IDC_STATIC, 20, 50, 45, 12, SS_LEFT\n    EDITTEXT        IDC_LOGIN, 65, 50, 116, 12, ES_AUTOHSCROLL\n    LTEXT           \"Password:\", IDC_STATIC, 20, 65, 45, 12, SS_LEFT\n    EDITTEXT        IDC_PASSWORD, 65, 65, 116, 12, ES_AUTOHSCROLL | ES_PASSWORD\n}\n\n\n\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\nIDD_SEARCHUI DIALOGEX 0, 0, 109, 148\nSTYLE DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW\nEXSTYLE WS_EX_CONTROLPARENT\nFONT 8, \"Ms Shell Dlg\"\n{\n    LTEXT           \"First Name\", IDC_STATIC, 3, 5, 44, 12, SS_LEFT\n    EDITTEXT        IDC_SEARCH_FN, 3, 15, 104, 12, ES_AUTOHSCROLL\n    LTEXT           \"Last Name\", IDC_STATIC, 3, 30, 44, 12, SS_LEFT\n    EDITTEXT        IDC_SEARCH_LN, 3, 40, 104, 12, ES_AUTOHSCROLL\n    LTEXT           \"Company\", IDC_STATIC, 3, 55, 44, 12, SS_LEFT\n    EDITTEXT        IDC_SEARCH_COMPANY, 3, 65, 104, 12, ES_AUTOHSCROLL\n    LTEXT           \"Country\", IDC_STATIC, 3, 80, 44, 12, SS_LEFT\n    EDITTEXT        IDC_SEARCH_COUNTRY, 3, 90, 104, 12, ES_AUTOHSCROLL\n}\n\n\n\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\nIDD_OPT_SIPSIMPLE DIALOG 0, 0, 255, 230\nSTYLE DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW\nEXSTYLE WS_EX_CONTROLPARENT\nFONT 8, \"Ms Shell Dlg\"\n{\n    GROUPBOX        \"Account options\", IDC_STATIC, 5, 5, 245, 70\n    AUTOCHECKBOX    \"Use windows credentials for authentication\", IDC_USESSO, 15, 20, 155, 12\n    LTEXT           \"Authentication scheme\", IDC_STATIC, 20, 35, 75, 12, SS_LEFT\n    COMBOBOX        IDC_AUTHTYPE, 100, 35, 75, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS\n    LTEXT           \"Connection type\", IDC_STATIC, 20, 55, 75, 12, SS_LEFT\n    COMBOBOX        IDC_CONNTYPE, 100, 55, 75, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS\n    GROUPBOX        \"User information\", IDC_STATIC, 5, 80, 245, 65\n    LTEXT           \"Username:\", IDC_STATIC, 15, 95, 55, 12, SS_LEFT\n    EDITTEXT        IDC_HANDLE, 75, 95, 135, 12, ES_AUTOHSCROLL\n    LTEXT           \"Login:\", IDC_STATIC, 15, 110, 55, 12, SS_LEFT\n    EDITTEXT        IDC_LOGIN, 75, 110, 135, 12, ES_AUTOHSCROLL\n    LTEXT           \"Password:\", IDC_STATIC, 15, 125, 55, 12, SS_LEFT\n    EDITTEXT        IDC_PASSWORD, 75, 125, 135, 12, ES_AUTOHSCROLL | ES_PASSWORD\n    GROUPBOX        \"Public IP (Protocol global)\", IDC_STATIC, 5, 150, 245, 75\n    AUTORADIOBUTTON \"Fetch local IP\", IDC_IPLOCAL, 15, 165, 55, 12\n    LTEXT           \"\", IDC_IPLOCALFOUND, 90, 165, 55, 12, SS_LEFT\n    AUTORADIOBUTTON \"Set manually\", IDC_IPMANUAL, 15, 180, 55, 12\n    EDITTEXT        IDC_PUBLICIP, 90, 180, 135, 12, ES_AUTOHSCROLL\n    AUTORADIOBUTTON \"Run program\", IDC_IPPROG, 15, 195, 55, 12\n    EDITTEXT        IDC_IPPROGEXE, 90, 195, 135, 12, ES_AUTOHSCROLL\n}\n\n\n\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\nIDD_OPT_SIPSIMPLE_ABOUT DIALOG 0, 0, 255, 230\nSTYLE DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW\nEXSTYLE WS_EX_CONTROLPARENT\nFONT 8, \"Ms Shell Dlg\"\n{\n    CONTROL         \"Rich Edit\", IDC_ABOUTSIPE, RICHEDIT_CLASS, WS_TABSTOP | WS_BORDER | ES_NUMBER | ES_MULTILINE | ES_READONLY | ES_AUTOVSCROLL | WS_VSCROLL, 5, 8, 240, 216\n}\n"
  },
  {
    "path": "src/miranda/sipe-miranda.c",
    "content": "#include <windows.h>\n#include <win2k.h>\n#include <Richedit.h>\n#include <process.h>\n\n#include <glib.h>\n\n#include \"miranda-version.h\"\n#include \"newpluginapi.h\"\n#include \"m_protosvc.h\"\n#include \"m_protoint.h\"\n#include \"m_system.h\"\n#include \"m_database.h\"\n#include \"m_langpack.h\"\n#include \"m_options.h\"\n#include \"m_clist.h\"\n#include \"m_chat.h\"\n#include \"m_netlib.h\"\n#include \"m_protomod.h\"\n\n#include \"sipe-core.h\"\n#include \"sipe-backend.h\"\n#include \"miranda-private.h\"\n#include \"miranda-resource.h\"\n\n/* Miranda interface globals */\n\nvoid CreateProtoService(SIPPROTO *pr, const char* szService, SipSimpleServiceFunc serviceProc)\n{\n\tchar str[ MAXMODULELABELLENGTH ];\n\n\tmir_snprintf(str, sizeof(str), \"%s%s\", pr->proto.m_szModuleName, szService);\n\tCreateServiceFunctionObj(str, (MIRANDASERVICEOBJ)*(void**)&serviceProc, pr);\n}\n\n/****************************************************************************\n * Struct that defines our interface with libsipe\n ****************************************************************************/\n/* Protocol interface functions */\nint RecvContacts( SIPPROTO *pr, HANDLE hContact, PROTORECVEVENT* evt )\n{\n\t_NIF();\n\treturn 0;\n}\n\nint RecvUrl( SIPPROTO *pr, HANDLE hContact, PROTORECVEVENT* evt )\n{\n\t_NIF();\n\treturn 0;\n}\n\nint SendContacts( SIPPROTO *pr, HANDLE hContact, int flags, int nContacts, HANDLE* hContactsList )\n{\n\t_NIF();\n\tSIPE_DEBUG_INFO(\"SendContacts: flags <%x> ncontacts <%x>\", flags, nContacts);\n\treturn 0;\n}\n\nint SendUrl( SIPPROTO *pr, HANDLE hContact, int flags, const char* url )\n{\n\t_NIF();\n\tSIPE_DEBUG_INFO(\"SendUrl: iflags <%x> url <%s>\", flags, url);\n\treturn 0;\n}\n\nint SetApparentMode( SIPPROTO *pr, HANDLE hContact, int mode )\n{\n\t_NIF();\n\tSIPE_DEBUG_INFO(\"SetApparentMode: mode <%x>\", mode);\n\treturn 0;\n}\n\nint RecvAwayMsg( SIPPROTO *pr, HANDLE hContact, int mode, PROTORECVEVENT* evt )\n{\n\t_NIF();\n\tSIPE_DEBUG_INFO(\"RecvAwayMsg: mode <%x>\", mode);\n\treturn 0;\n}\n\nint SendAwayMsg( SIPPROTO *pr, HANDLE hContact, HANDLE hProcess, const char* msg )\n{\n\t_NIF();\n\tSIPE_DEBUG_INFO(\"SendAwayMsg: msg <%s>\", msg);\n\treturn 0;\n}\n"
  },
  {
    "path": "src/miranda/vlc.c",
    "content": "#include <windows.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <vlc/vlc.h>\n\nextern HINSTANCE hInst;\n\nLRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)\n{\n    switch(msg)\n    {\n        case WM_CLOSE:\n            DestroyWindow(hwnd);\n        break;\n        case WM_DESTROY:\n            PostQuitMessage(0);\n        break;\n        default:\n            return DefWindowProc(hwnd, msg, wParam, lParam);\n    }\n    return 0;\n}\n\nint __stdcall show_vlc(void *data)\n{\n     libvlc_instance_t * inst;\n     libvlc_media_player_t *mp;\n     libvlc_media_t *m;\n\tint rc;\n\tHANDLE w;\n\tWNDCLASSEX wc;\n     \n     /* Load the VLC engine */\n     inst = libvlc_new (0, NULL);\n  \n     /* Create a new item */\n     m = libvlc_media_new_path (inst, \"C:\\\\Temp\\\\[001_1-01] Broken Bow (Part 1).mpg\");\n        \n     /* Create a media player playing environement */\n     mp = libvlc_media_player_new_from_media (m);\n     \n     /* No need to keep the media now */\n     libvlc_media_release (m);\n \n\n\t//Step 1: Registering the Window Class\n\twc.cbSize        = sizeof(WNDCLASSEX);\n\twc.style         = 0;\n\twc.lpfnWndProc   = WndProc;\n\twc.cbClsExtra    = 0;\n\twc.cbWndExtra    = 0;\n\twc.hInstance     = hInst;\n\twc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);\n\twc.hCursor       = LoadCursor(NULL, IDC_ARROW);\n\twc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);\n\twc.lpszMenuName  = NULL;\n\twc.lpszClassName = L\"myclassstuff\";\n\twc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);\n\n\tif(!RegisterClassEx(&wc))\n\t{\n\t\tMessageBox(NULL, L\"Window Registration Failed!\", L\"Error!\", MB_ICONEXCLAMATION | MB_OK);\n\t\treturn 0;\n\t}\n  \n\tw = CreateWindow(L\"myclassstuff\", L\"VLC Window\", WS_OVERLAPPEDWINDOW, 50, 50, 400, 400, NULL, NULL, hInst, NULL);\n\n\tif (!w)\n\t{\n\t\tDWORD d = GetLastError();\n\t\tprintf (\"===================== %08x ==============\\n\", d);\n\n\t}\n\n//\tlibvlc_media_player_set_hwnd (mp, w);\n\n//\tShowWindow(w, SW_SHOW); \n//\tUpdateWindow(w); \n\n#if 0\n     /* This is a non working code that show how to hooks into a window,\n      * if we have a window around */\n      libvlc_media_player_set_xdrawable (mp, xdrawable);\n     /* or on windows */\n     /* or on mac os */\n      libvlc_media_player_set_nsobject (mp, view);\n#endif\n \n     /* play the media_player */\n     rc = libvlc_media_player_play (mp);\n    \n     Sleep (60000); /* Let it play a bit */\n    \n     /* Stop playing */\n     libvlc_media_player_stop (mp);\n \n     /* Free the media_player */\n     libvlc_media_player_release (mp);\n \n     libvlc_release (inst);\n \n     return 0;\n}\n"
  },
  {
    "path": "src/purple/Makefile.am",
    "content": "pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)\n\nnoinst_LTLIBRARIES = libsipe_backend.la\n\npkg_LTLIBRARIES = libsipe.la\n\nEXTRA_DIST = \\\n\tpidgin-sipe.metainfo.xml\n\nMAINTAINERCLEANFILES = \\\n\tMakefile.in\n\nlibsipe_backend_la_SOURCES = \\\n\tpurple-private.h \\\n\tpurple-buddy.c \\\n\tpurple-chat.c \\\n\tpurple-connection.c \\\n\tpurple-debug.c \\\n\tpurple-dnsquery.c \\\n\tpurple-ft.c \\\n\tpurple-groupchat.c \\\n\tpurple-im.c \\\n\tpurple-markup.c \\\n\tpurple-network.c \\\n\tpurple-notify.c \\\n\tpurple-schedule.c \\\n\tpurple-search.c \\\n\tpurple-setting.c \\\n\tpurple-status.c \\\n\tpurple-transport.c \\\n\tpurple-user.c\n\nlibsipe_la_SOURCES = \\\n\tpurple-plugin-common.c\n\nif SIPE_PURPLE3\nlibsipe_la_SOURCES += purple-plugin3.c\nelse\nlibsipe_la_SOURCES += purple-plugin.c\nendif\n\nAM_CFLAGS = $(st)\n\nlibsipe_backend_la_CFLAGS = \\\n\t$(DEBUG_CFLAGS) \\\n\t$(QUALITY_CFLAGS) \\\n\t$(GLIB_CFLAGS) \\\n\t$(DBUS_CFLAGS) \\\n\t$(PURPLE_CFLAGS) \\\n\t-I$(srcdir)/../api\n\nif !SIPE_OS_WIN32\nlibsipe_backend_la_CFLAGS += \\\n        $(LOCALE_CPPFLAGS)\nendif\n\nlibsipe_la_CFLAGS = $(libsipe_backend_la_CFLAGS)\n\nlibsipe_la_LDFLAGS = \\\n\t-module -avoid-version -no-undefined \\\n\t$(ADDITIONAL_LDFLAGS)\n\nlibsipe_la_LIBADD = \\\n\t../core/libsipe_core.la \\\n\t../core/libsipe_core_crypto.la \\\n\t../core/libsipe_core_libxml2.la \\\n\tlibsipe_backend.la \\\n\t$(DBUS_LIBS) \\\n\t$(LIBXML2_LIBS) \\\n\t$(NSS_LIBS) \\\n\t$(OPENSSL_LIBS) \\\n\t$(GLIB_LIBS) \\\n\t$(PURPLE_LIBS)\n\nif SIPE_OS_WIN32\nlibsipe_la_CFLAGS += -DHAVE_SSPI=1\nlibsipe_la_LIBADD += -lws2_32 -lsecur32\nendif\n\nif SIP_SEC_GSSAPI\nlibsipe_la_LIBADD += $(KRB5_LDFLAGS)\nendif\n\ncheck_PROGRAMS = tests_load\ntests_load_SOURCES = tests-load.c\ntests_load_CFLAGS  = $(GMODULE_CFLAGS)\ntests_load_LDADD   = $(GMODULE_LIBS)\n\nif !SIPE_OS_WIN32\nif !SIP_SEC_GSSAPI_ONLY\ncheck_PROGRAMS += tests\ntests_SOURCES   = tests.c\ntests_CFLAGS    = $(libsipe_la_CFLAGS)\ntests_LDADD     = \\\n\t../core/libsipe_core_tests.la \\\n\t../core/libsipe_core_crypto.la \\\n\tlibsipe_backend.la \\\n\t$(NSS_LIBS) \\\n\t$(OPENSSL_LIBS) \\\n\t$(PURPLE_LIBS)\nendif\nendif\n\n# D-Bus functionality no longer available in 3.x.x API\nif !SIPE_PURPLE3\nif SIPE_DBUS\nlibsipe_backend_la_SOURCES += \\\n\tpurple-dbus.c \\\n\tpurple-dbus.h \\\n\tpurple-dbus-bindings.c\nendif\nendif\n\nif SIPE_MIME_GMIME\nlibsipe_la_LIBADD += \\\n\t../core/libsipe_core_mime.la \\\n\t$(GMIME_LIBS)\nif !SIPE_OS_WIN32\nif !SIP_SEC_GSSAPI_ONLY\ntests_LDADD       += \\\n\t../core/libsipe_core_mime.la \\\n\t$(GMIME_LIBS)\nendif\nendif\nelse\nlibsipe_backend_la_SOURCES += purple-mime.c\nendif\n\nif SIPE_WITH_VV\nnoinst_LTLIBRARIES            += libsipe_backend_vv.la\nlibsipe_backend_vv_la_SOURCES  = purple-media.c\nlibsipe_backend_vv_la_CFLAGS   = \\\n\t$(libsipe_backend_la_CFLAGS) \\\n\t$(NICE_CFLAGS) \\\n\t$(GSTREAMER_CFLAGS) \\\n\t$(FARSTREAM_CFLAGS)\nlibsipe_la_LIBADD             += \\\n\tlibsipe_backend_vv.la \\\n\t$(NICE_LIBS) \\\n\t$(GSTREAMER_LIBS) \\\n\t$(FARSTREAM_LIBS)\n\nif SIPE_HAVE_APPSHARE_SERVER\nlibsipe_la_LIBADD             += \\\n\t$(FREERDP_SHADOW_LIBS)\nendif\nendif\n\nTESTS = $(check_PROGRAMS)\n\n# Remove any libsipe.so from the old incorrect installation location\ninstall-exec-local:\n\trm -f $(DESTDIR)$(libdir)/pidgin/libsipe.so\n\nif SIPE_WITH_APPSTREAM\npidginmetainfofiledir   = $(datadir)/metainfo\npidginmetainfofile_DATA = pidgin-sipe.metainfo.xml\n\ncheck: validate-metainfo\n\n.PHONY: validate-metainfo\nvalidate-metainfo: $(pidginmetainfofile_DATA)\n\tappstreamcli validate --pedantic --nonet $< || \\\n\tappstreamcli validate --pedantic         $< || \\\n\tappstream-validate                       $<\nendif\n"
  },
  {
    "path": "src/purple/pidgin-sipe.metainfo.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<component type=\"addon\">\n  <id>net.sourceforge.sipe.purple</id>\n  <extends>pidgin.desktop</extends>\n  <name>SIPE</name>\n  <summary>Pidgin protocol plugin to connect to MS Office Communicator</summary>\n  <description>\n    <p>\n      SIPE is a third-party plugin for the Pidgin/Adium/Miranda/Telepathy\n      multi-protocol instant messaging clients/frameworks. It implements the\n      extended version of SIP/SIMPLE used by various products:\n    </p>\n    <ul>\n      <li>Skype for Business</li>\n      <li>Microsoft Office 365</li>\n      <li>Microsoft Business Productivity Online Suite (BPOS)</li>\n      <li>Microsoft Lync Server</li>\n      <li>Microsoft Office Communications Server (OCS 2007/2007 R2)</li>\n      <li>Microsoft Live Communications Server (LCS 2003/2005)</li>\n    </ul>\n    <p>\n      With this plugin you should be able to replace your Microsoft Office\n      Communicator client with Pidgin/Adium/Miranda/Telepathy.\n    </p>\n  </description>\n  <url type=\"homepage\">http://sipe.sourceforge.net/</url>\n  <url type=\"bugtracker\">https://sourceforge.net/p/sipe/bugs/</url>\n  <metadata_license>GFDL-1.3</metadata_license>\n  <!-- NOTE: appstream does not recognize SPDX 2.x+ \"GPL-2.0-or-later\" -->\n  <project_license>GPL-2.0+</project_license>\n</component>\n"
  },
  {
    "path": "src/purple/purple-buddy.c",
    "content": "/**\n * @file purple-buddy.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n\n#include \"notify.h\"\n#include \"request.h\"\n\n#include \"version.h\"\n#if PURPLE_VERSION_CHECK(3,0,0)\n#include \"action.h\"\n#include \"account.h\"\n#include \"buddylist.h\"\n#else\n#include \"blist.h\"\n#include \"privacy.h\"\n#define purple_account_privacy_check(a, n)             purple_privacy_check(a, n)\n#define purple_account_privacy_deny_add(a, n, l)       purple_privacy_deny_add(a, n, l)\n#define purple_account_privacy_deny_remove(a, n, l)    purple_privacy_deny_remove(a, n, l)\n#define purple_action_menu_new(l, c, d, ch)            purple_menu_action_new(l, c, d, ch)\n#define purple_blist_find_buddies(a, n)                purple_find_buddies(a, n)\n#define purple_blist_find_buddy(a, n)                  purple_find_buddy(a, n)\n#define purple_blist_find_buddy_in_group(a, n, g)      purple_find_buddy_in_group(a, n, g)\n#define purple_blist_find_group(n)                     purple_find_group(n)\n#define purple_blist_get_default_root()                purple_blist_get_root()\n#define purple_buddy_set_local_alias(b, n)             purple_blist_alias_buddy(b, n)\n#define purple_buddy_set_server_alias(b, n)            purple_blist_server_alias_buddy(b, n)\n#define purple_buddy_set_name(b, n)                    purple_blist_rename_buddy(b, n)\n#define purple_group_set_name(g, n)                    purple_blist_rename_group(g, n)\n#define purple_notify_user_info_add_pair_html(i, k, v) purple_notify_user_info_add_pair(i, k, v)\n#define purple_protocol_got_user_status                purple_prpl_got_user_status\n#define PurpleActionMenu                               PurpleMenuAction\n#define PURPLE_IS_BUDDY(b)                             PURPLE_BLIST_NODE_IS_BUDDY(b)\n#define PURPLE_IS_GROUP(b)                             PURPLE_BLIST_NODE_IS_GROUP(b)\n#endif\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-nls.h\"\n\n#include \"purple-private.h\"\n\nstatic const struct {\n\tconst gchar *property;    /* property name to store in blist.xml */\n\tconst gchar *description; /* label for \"Get Info\" dialog */\n} buddy_info_map[] = {\n/* SIPE_BUDDY_INFO_DISPLAY_NAME          */ { \"alias\",                 N_(\"Display name\")   },\n/* SIPE_BUDDY_INFO_JOB_TITLE             */ { \"title\",                 N_(\"Job title\")      },\n/* SIPE_BUDDY_INFO_CITY                  */ { \"address-city\",          N_(\"City\")           },\n/* SIPE_BUDDY_INFO_STATE                 */ { \"address-state\",         N_(\"State\")          },\n/* SIPE_BUDDY_INFO_OFFICE                */ { \"office\",                N_(\"Office\")         },\n/* SIPE_BUDDY_INFO_DEPARTMENT            */ { \"department\",            NULL                 },\n/* SIPE_BUDDY_INFO_COUNTRY               */ { \"address-country-code\",  N_(\"Country\")        },\n/* SIPE_BUDDY_INFO_WORK_PHONE            */ { \"phone\",                 N_(\"Business phone\") },\n/* SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY    */ { \"phone-display\",         NULL                 },\n/* SIPE_BUDDY_INFO_COMPANY               */ { \"company\",               N_(\"Company\")        },\n/* SIPE_BUDDY_INFO_EMAIL                 */ { \"email\",                 N_(\"Email address\")  },\n/* SIPE_BUDDY_INFO_SITE                  */ { \"site\",                  N_(\"Site\")           },\n/* SIPE_BUDDY_INFO_ZIPCODE               */ { \"address-zipcode\",       NULL                 },\n/* SIPE_BUDDY_INFO_STREET                */ { \"address-street\",        NULL                 },\n/* SIPE_BUDDY_INFO_MOBILE_PHONE          */ { \"phone-mobile\",          NULL                 },\n/* SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY  */ { \"phone-mobile-display\",  NULL                 },\n/* SIPE_BUDDY_INFO_HOME_PHONE            */ { \"phone-home\",            NULL                 },\n/* SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY    */ { \"phone-home-display\",    NULL                 },\n/* SIPE_BUDDY_INFO_OTHER_PHONE           */ { \"phone-other\",           NULL                 },\n/* SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY   */ { \"phone-other-display\",   NULL                 },\n/* SIPE_BUDDY_INFO_CUSTOM1_PHONE         */ { \"phone-custom1\",         NULL                 },\n/* SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY */ { \"phone-custom1-display\", NULL                 },\n/* SIPE_BUDDY_INFO_ALIAS                 */ { NULL,                    N_(\"Alias\")          },\n/* SIPE_BUDDY_INFO_DEVICE                */ { NULL,                    N_(\"Device\")         },\n};\n\n#define buddy_info_property(i)    buddy_info_map[i].property\n#define buddy_info_description(i) gettext(buddy_info_map[i].description)\n\nsipe_backend_buddy sipe_backend_buddy_find(struct sipe_core_public *sipe_public,\n\t\t\t\t\t   const gchar *buddy_name,\n\t\t\t\t\t   const gchar *group_name)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tPurpleGroup *purple_group;\n\n\tif (group_name)\n\t{\n\t\tpurple_group = purple_blist_find_group(group_name);\n\t\tif (!purple_group)\n\t\t\treturn NULL;\n\n\t\treturn purple_blist_find_buddy_in_group(purple_private->account,\n\t\t\t\t\t\t\tbuddy_name,\n\t\t\t\t\t\t\tpurple_group);\n\t} else {\n\t\treturn purple_blist_find_buddy(purple_private->account,\n\t\t\t\t\t       buddy_name);\n\t}\n}\n\nGSList* sipe_backend_buddy_find_all(struct sipe_core_public *sipe_public,\n\t\t\t\t    const gchar *buddy_name,\n\t\t\t\t    const gchar *group_name)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\n\tif (group_name)\n\t{\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"Finding all buddies in a group not supported on purple\");\n\t\treturn NULL;\n\t}\n\n\treturn purple_blist_find_buddies(purple_private->account, buddy_name);\n}\n\ngchar* sipe_backend_buddy_get_name(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t   const sipe_backend_buddy who)\n{\n\treturn g_strdup(purple_buddy_get_name((PurpleBuddy *) who));\n}\n\ngchar* sipe_backend_buddy_get_alias(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t    const sipe_backend_buddy who)\n{\n\treturn g_strdup(purple_buddy_get_alias(who));\n}\n\ngchar* sipe_backend_buddy_get_server_alias(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t   const sipe_backend_buddy who)\n{\n\treturn g_strdup(purple_buddy_get_server_alias(who));\n}\n\ngchar *sipe_backend_buddy_get_local_alias(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t  const sipe_backend_buddy who)\n{\n\treturn g_strdup(\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\tpurple_buddy_get_local_alias(who)\n#else\n\t\tpurple_buddy_get_local_buddy_alias(who)\n#endif\n\t\t);\n}\n\ngchar* sipe_backend_buddy_get_group_name(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t const sipe_backend_buddy who)\n{\n\treturn g_strdup(purple_group_get_name(purple_buddy_get_group((PurpleBuddy*)who)));\n}\n\nguint sipe_backend_buddy_get_status(struct sipe_core_public *sipe_public,\n\t\t\t\t    const gchar *uri)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tPurpleBuddy *pbuddy = purple_blist_find_buddy(purple_private->account, uri);\n\tPurplePresence *presence = purple_buddy_get_presence(pbuddy);\n\tPurpleStatus *pstatus = purple_presence_get_active_status(presence);\n\treturn(sipe_purple_token_to_activity(purple_status_get_id(pstatus)));\n}\n\nvoid sipe_backend_buddy_set_alias(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t  const sipe_backend_buddy who,\n\t\t\t\t  const gchar *alias)\n{\n\tpurple_buddy_set_local_alias(who, alias);\n}\n\nvoid sipe_backend_buddy_set_server_alias(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t const sipe_backend_buddy who,\n\t\t\t\t\t const gchar *alias)\n{\n\tpurple_buddy_set_server_alias(who, alias);\n}\n\ngchar* sipe_backend_buddy_get_string(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t     sipe_backend_buddy buddy,\n\t\t\t\t     const sipe_buddy_info_fields key)\n{\n\tPurpleBuddy *b = (PurpleBuddy*) buddy;\n\treturn g_strdup(purple_blist_node_get_string(&b->node, buddy_info_property(key)));\n}\n\nvoid sipe_backend_buddy_set_string(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t   sipe_backend_buddy buddy,\n\t\t\t\t   const sipe_buddy_info_fields key,\n\t\t\t\t   const gchar *val)\n{\n\tPurpleBuddy *b = (PurpleBuddy*) buddy;\n\tpurple_blist_node_set_string(&b->node, buddy_info_property(key), val);\n}\n\nvoid sipe_backend_buddy_refresh_properties(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t   SIPE_UNUSED_PARAMETER const gchar *uri)\n{\n\t/* nothing to do here: already taken care of by libpurple */\n}\n\nvoid sipe_backend_buddy_list_processing_start(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public)\n{\n}\n\nvoid sipe_backend_buddy_list_processing_finish(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public)\n{\n}\n\nsipe_backend_buddy sipe_backend_buddy_add(struct sipe_core_public *sipe_public,\n\t\t\t\t\t  const gchar *name,\n\t\t\t\t\t  const gchar *alias,\n\t\t\t\t\t  const gchar *groupname)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tPurpleBuddy *b;\n\tPurpleGroup *purple_group = purple_blist_find_group(groupname);\n\n\tif (!purple_group)\n\t\treturn NULL;\n\n\tb = purple_buddy_new(purple_private->account, name, alias);\n\tpurple_blist_add_buddy(b, NULL, purple_group, NULL);\n\treturn b;\n}\n\nvoid sipe_backend_buddy_remove(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t       const sipe_backend_buddy who)\n{\n\tpurple_blist_remove_buddy(who);\n}\n\nstruct authorization_cb_data {\n\tsipe_backend_buddy_request_authorization_cb auth_cb;\n\tsipe_backend_buddy_request_authorization_cb deny_cb;\n\tgpointer data;\n};\n\nstatic void authorization_auth_cb(\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tSIPE_UNUSED_PARAMETER const char *response,\n#endif\n\tvoid *user_data)\n{\n\tstruct authorization_cb_data *cb_data = user_data;\n\tsipe_backend_buddy_request_authorization_cb callback = cb_data->auth_cb;\n\tvoid *data = cb_data->data;\n\tg_free(user_data);\n\t(*callback)(data);\n}\n\nstatic void authorization_deny_cb(\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tSIPE_UNUSED_PARAMETER const char *response,\n#endif\n\tvoid *user_data)\n{\n\tstruct authorization_cb_data *cb_data = user_data;\n\tsipe_backend_buddy_request_authorization_cb callback = cb_data->deny_cb;\n\tvoid *data = cb_data->data;\n\tg_free(user_data);\n\t(*callback)(data);\n}\n\nvoid sipe_backend_buddy_request_authorization(struct sipe_core_public *sipe_public,\n\t\t\t\t\t      const gchar *who,\n\t\t\t\t\t      const gchar *alias,\n\t\t\t\t\t      gboolean on_list,\n\t\t\t\t\t      sipe_backend_buddy_request_authorization_cb auth_cb,\n\t\t\t\t\t      sipe_backend_buddy_request_authorization_cb deny_cb,\n\t\t\t\t\t      gpointer data)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tstruct authorization_cb_data *cb_data = g_new(struct authorization_cb_data, 1);\n\n\tcb_data->auth_cb = auth_cb;\n\tcb_data->deny_cb = deny_cb;\n\tcb_data->data    = data;\n\n\tpurple_account_request_authorization(\n\t\tpurple_private->account,\n\t\twho,\n\t\t_(\"you\"), /* id */\n\t\talias,\n\t\tNULL, /* message */\n\t\ton_list,\n\t\tauthorization_auth_cb,\n\t\tauthorization_deny_cb,\n\t\tcb_data);\n}\n\nvoid sipe_backend_buddy_request_add(struct sipe_core_public *sipe_public,\n\t\t\t\t    const gchar *who,\n\t\t\t\t    const gchar *alias)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\n\tpurple_account_request_add(purple_private->account,\n\t\t\t\t   who,\n\t\t\t\t   _(\"you\"),\n\t\t\t\t   alias,\n\t\t\t\t   NULL);\n\n}\n\ngboolean sipe_backend_buddy_is_blocked(struct sipe_core_public *sipe_public,\n\t\t\t\t       const gchar *who)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\n\treturn(!purple_account_privacy_check(purple_private->account, who));\n}\n\nvoid sipe_backend_buddy_set_blocked_status(struct sipe_core_public *sipe_public,\n\t\t\t\t      const gchar *who,\n\t\t\t\t      gboolean blocked)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\n\tif (blocked) {\n\t\tpurple_account_privacy_deny_add(purple_private->account, who, TRUE);\n\t} else {\n\t\tpurple_account_privacy_deny_remove(purple_private->account, who, TRUE);\n\t}\n\n\t/* stupid workaround to make pidgin re-render screen to reflect our changes */\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_backend_buddy_set_blocked_status: forcefully refreshing screen.\");\n\tsipe_core_buddy_got_status(sipe_public,\n\t\t\t\t   who,\n\t\t\t\t   sipe_backend_buddy_get_status(sipe_public,\n\t\t\t\t\t\t\t\t who),\n\t\t\t\t   0);\n}\n\nvoid sipe_backend_buddy_set_status(struct sipe_core_public *sipe_public,\n\t\t\t\t   const gchar *who,\n\t\t\t\t   guint activity,\n\t                           time_t last_active)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tPurpleBuddy *buddy = NULL;\n\tgchar *tmp = NULL;\n\n\tbuddy = purple_blist_find_buddy(purple_private->account, who);\n\n\tif (buddy) {\n\t\tconst PurpleStatusType *status_type =\n\t\t\tpurple_status_type_find_with_id(\n\t\t\t\tpurple_account_get_status_types(purple_private->account),\n\t\t\t\tsipe_purple_activity_to_token(activity));\n\t\ttmp = sipe_core_buddy_status(PURPLE_BUDDY_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t\t     purple_buddy_get_name(buddy),\n\t\t\t\t\t     activity,\n\t\t\t\t\t     purple_status_type_get_name(status_type));\n\t}\n\n\t/* make sure to clear status message when there is none */\n\tif (!tmp)\n\t\ttmp = g_strdup(\"\");\n\n\tpurple_protocol_got_user_status(purple_private->account, who,\n\t\t\t\t\tsipe_purple_activity_to_token(activity),\n\t\t\t\t\tSIPE_PURPLE_STATUS_ATTR_ID_MESSAGE, tmp,\n\t\t\t\t\tNULL);\n\tg_free(tmp);\n\n\t/*\n\t * One of the idiosyncrasies in the libpurple API: it is not\n\t * enough to set the buddy status to one of the idle ones.\n\t * You also must make another call to set an idle flag!\n\t */\n\tif (buddy) {\n\t\tPurplePresence *presence = purple_buddy_get_presence(buddy);\n\t\tgboolean is_idle =\n\t\t\t(activity == SIPE_ACTIVITY_INACTIVE) ||\n\t\t\t(activity == SIPE_ACTIVITY_AWAY)     ||\n\t\t\t(activity == SIPE_ACTIVITY_BRB)      ||\n\t\t\t(activity == SIPE_ACTIVITY_LUNCH);\n\n\t\tpurple_presence_set_idle(presence, is_idle,\n\t\t\t\t\t is_idle ? last_active : 0);\n\t}\n}\n\ngboolean sipe_backend_uses_photo(void)\n{\n\treturn TRUE;\n}\n\nvoid sipe_backend_buddy_set_photo(struct sipe_core_public *sipe_public,\n\t\t\t\t  const gchar *who,\n\t\t\t\t  gpointer photo_data,\n\t\t\t\t  gsize data_len,\n\t\t\t\t  const gchar *photo_hash)\n{\n\tPurpleAccount *account = sipe_public->backend_private->account;\n\n\tpurple_buddy_icons_set_for_user(account, who, photo_data,\n\t\t\t\t\tdata_len, photo_hash);\n}\n\nconst gchar *sipe_backend_buddy_get_photo_hash(struct sipe_core_public *sipe_public,\n\t\t\t\t\t       const gchar *who)\n{\n\tPurpleAccount *account = sipe_public->backend_private->account;\n\tconst gchar *result = NULL;\n\n\tPurpleBuddyIcon *icon = purple_buddy_icons_find(account, who);\n\tif (icon) {\n\t\tresult = purple_buddy_icon_get_checksum(icon);\n\t\tpurple_buddy_icon_unref(icon);\n\t}\n\n\treturn result;\n}\n\ngboolean sipe_backend_buddy_group_add(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t      const gchar *group_name)\n{\n\tPurpleGroup * purple_group = purple_blist_find_group(group_name);\n\tif (!purple_group) {\n\t\tpurple_group = purple_group_new(group_name);\n\t\tpurple_blist_add_group(purple_group, NULL);\n\t}\n\n\treturn (purple_group != NULL);\n}\n\ngboolean sipe_backend_buddy_group_rename(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t const gchar *old_name,\n\t\t\t\t\t const gchar *new_name)\n{\n\tPurpleGroup *purple_group = purple_blist_find_group(old_name);\n\tif (purple_group)\n\t\tpurple_group_set_name(purple_group, new_name);\n\treturn(purple_group != NULL);\n}\n\nvoid sipe_backend_buddy_group_remove(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t     const gchar *group_name)\n{\n\tPurpleGroup *purple_group = purple_blist_find_group(group_name);\n\tif (purple_group)\n\t\tpurple_blist_remove_group(purple_group);\n}\n\nstruct sipe_backend_buddy_info *sipe_backend_buddy_info_start(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public)\n{\n\treturn((struct sipe_backend_buddy_info *)purple_notify_user_info_new());\n}\n\nvoid sipe_backend_buddy_info_add(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t struct sipe_backend_buddy_info *info,\n\t\t\t\t sipe_buddy_info_fields key,\n\t\t\t\t const gchar *value)\n{\n\tif (info) {\n\t\tpurple_notify_user_info_add_pair_html((PurpleNotifyUserInfo *) info,\n\t\t\t\t\t\t      buddy_info_description(key),\n\t\t\t\t\t\t      value);\n\t}\n}\n\nvoid sipe_backend_buddy_info_break(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t   struct sipe_backend_buddy_info *info)\n{\n\tpurple_notify_user_info_add_section_break((PurpleNotifyUserInfo *) info);\n}\n\nvoid sipe_backend_buddy_info_finalize(struct sipe_core_public *sipe_public,\n\t\t\t\t      struct sipe_backend_buddy_info *info,\n\t\t\t\t      const gchar *uri)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\n\t/* show a buddy's user info in a nice dialog box */\n\tpurple_notify_userinfo(purple_private->gc,\n\t\t\t       uri,       /* buddy's URI */\n\t\t\t       (PurpleNotifyUserInfo *) info,\n\t\t\t       NULL,      /* callback called when dialog closed */\n\t\t\t       NULL);     /* userdata for callback */\n}\n\nvoid sipe_backend_buddy_tooltip_add(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t    struct sipe_backend_buddy_tooltip *tooltip,\n\t\t\t\t    const gchar *description,\n\t\t\t\t    const gchar *value)\n{\n\tpurple_notify_user_info_add_pair_html((PurpleNotifyUserInfo *) tooltip,\n\t\t\t\t\t      description,\n\t\t\t\t\t      value);\n}\n\nvoid sipe_purple_add_buddy(PurpleConnection *gc,\n\t\t\t   PurpleBuddy *buddy,\n\t\t\t   PurpleGroup *group\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t   , SIPE_UNUSED_PARAMETER const gchar *message\n#endif\n\t)\n{\n\tSIPE_DEBUG_INFO(\"sipe_purple_add_buddy[CB]: buddy:%s group:%s\",\n\t\t\tbuddy ? purple_buddy_get_name(buddy) : \"\",\n\t\t\tgroup ? purple_group_get_name(group) : \"\");\n\n\t/* libpurple can call us with undefined buddy or group */\n\tif (buddy && group) {\n\t\t/*\n\t\t * Buddy name must be lower case as we use\n\t\t * purple_normalize_nocase() to compare\n\t\t */\n\t\tgchar *buddy_name = g_ascii_strdown(purple_buddy_get_name(buddy), -1);\n\t\tgchar *uri        = sip_uri_if_valid(buddy_name);\n\t\tg_free(buddy_name);\n\n\t\tif (uri) {\n\t\t\tpurple_buddy_set_name(buddy, uri);\n\t\t\tg_free(uri);\n\n\t\t\tsipe_core_buddy_add(PURPLE_GC_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t\t    purple_buddy_get_name(buddy),\n\t\t\t\t\t    purple_group_get_name(group));\n\t\t} else {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"sipe_purple_add_buddy[CB]: buddy name is invalid for URI\");\n\t\t\tpurple_blist_remove_buddy(buddy);\n\t\t\tpurple_notify_error(gc, NULL,\n\t\t\t\t\t    _(\"User name should be a valid SIP URI\\nExample: user@company.com\"),\n\t\t\t\t\t    NULL\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t\t\t    , NULL\n#endif\n\t\t\t\t\t    );\n\t\t}\n\t}\n}\n\nvoid sipe_purple_remove_buddy(PurpleConnection *gc,\n\t\t\t      PurpleBuddy *buddy,\n\t\t\t      PurpleGroup *group)\n{\n\tSIPE_DEBUG_INFO(\"sipe_purple_remove_buddy[CB]: buddy: '%s' group: '%s'\",\n\t\t\tbuddy ? purple_buddy_get_name(buddy) : \"\",\n\t\t\tgroup ? purple_group_get_name(group) : \"\");\n\tif (!buddy) return;\n\n\tsipe_core_buddy_remove(PURPLE_GC_TO_SIPE_CORE_PUBLIC,\n\t\t\t       purple_buddy_get_name(buddy),\n\t\t\t       group ? purple_group_get_name(group) : NULL);\n}\n\nvoid sipe_purple_group_buddy(PurpleConnection *gc,\n\t\t\t     const char *who,\n\t\t\t     const char *old_group_name,\n\t\t\t     const char *new_group_name)\n{\n\tsipe_core_buddy_group(PURPLE_GC_TO_SIPE_CORE_PUBLIC, who, old_group_name, new_group_name);\n}\n\n/* Buddy Menu Handling */\n\nstatic void sipe_purple_buddy_make_chat_leader_cb(PurpleBuddy *buddy,\n\t\t\t\t\t\t  gpointer parameter)\n{\n\tSIPE_DEBUG_INFO(\"sipe_purple_buddy_make_chat_leader_cb: name '%s'\",\n\t\t\tpurple_buddy_get_name(buddy));\n\tsipe_core_conf_make_leader(PURPLE_BUDDY_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t   parameter,\n\t\t\t\t   purple_buddy_get_name(buddy));\n}\n\nstatic void sipe_purple_buddy_remove_from_chat_cb(PurpleBuddy *buddy,\n\t\t\t\t\t\t  gpointer parameter)\n{\n\tSIPE_DEBUG_INFO(\"sipe_purple_buddy_remove_from_chat_cb: name '%s'\",\n\t\t\tpurple_buddy_get_name(buddy));\n\tsipe_core_conf_remove_from(PURPLE_BUDDY_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t   parameter,\n\t\t\t\t   purple_buddy_get_name(buddy));\n}\n\nstatic void sipe_purple_buddy_invite_to_chat_cb(PurpleBuddy *buddy,\n\t\t\t\t\t\tgpointer parameter)\n{\n\tSIPE_DEBUG_INFO(\"sipe_purple_buddy_invite_to_chat_cb: name '%s'\",\n\t\t\tpurple_buddy_get_name(buddy));\n\tsipe_core_chat_invite(PURPLE_BUDDY_TO_SIPE_CORE_PUBLIC,\n\t\t\t      parameter,\n\t\t\t      purple_buddy_get_name(buddy));\n}\n\nstatic void sipe_purple_buddy_new_chat_cb(PurpleBuddy *buddy,\n\t\t\t\t\t  SIPE_UNUSED_PARAMETER gpointer parameter)\n{\n\tSIPE_DEBUG_INFO(\"sipe_purple_buddy_new_chat_cb: name '%s'\",\n\t\t\tpurple_buddy_get_name(buddy));\n\tsipe_core_buddy_new_chat(PURPLE_BUDDY_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t purple_buddy_get_name(buddy));\n}\n\nstatic void sipe_purple_buddy_make_call_cb(PurpleBuddy *buddy,\n\t\t\t\t\t   gpointer parameter)\n{\n\tSIPE_DEBUG_INFO(\"sipe_purple_buddy_make_call_cb: name '%s'\",\n\t\t\tpurple_buddy_get_name(buddy));\n\tsipe_core_buddy_make_call(PURPLE_BUDDY_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t  parameter);\n}\n\nstatic void sipe_purple_buddy_send_email_cb(PurpleBuddy *buddy,\n\t\t\t\t\t    SIPE_UNUSED_PARAMETER gpointer parameter)\n{\n\tSIPE_DEBUG_INFO(\"sipe_purple_buddy_send_email_cb: name '%s'\",\n\t\t\tpurple_buddy_get_name(buddy));\n\tsipe_core_buddy_send_email(PURPLE_BUDDY_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t   purple_buddy_get_name(buddy));\n}\n\nstatic void sipe_purple_buddy_access_level_help_cb(PurpleBuddy *buddy,\n\t\t\t\t\t\t   SIPE_UNUSED_PARAMETER gpointer parameter)\n{\n\t/**\n\t * Translators: replace with URL to localized page\n\t * If it doesn't exist copy the original URL\n\t */\n\tpurple_notify_uri(purple_account_get_connection(purple_buddy_get_account(buddy)),\n\t\t\t  _(\"https://sourceforge.net/apps/mediawiki/sipe/index.php?title=Access_Levels\"));\n}\n\nstatic void sipe_purple_buddy_change_access_level_cb(PurpleBuddy *buddy,\n\t\t\t\t\t\t     gpointer parameter)\n{\n\tsipe_core_change_access_level_from_container(PURPLE_BUDDY_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t     parameter);\n}\n\nstatic void sipe_purple_ask_access_domain_cb(PurpleConnection *gc,\n\t\t\t\t\t     PurpleRequestFields *fields)\n{\n\tconst gchar *domain = purple_request_fields_get_string(fields, \"access_domain\");\n\tguint index         =\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\tGPOINTER_TO_UINT(\n#endif\n\t\t\tpurple_request_fields_get_choice(fields, \"container_id\")\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t\t)\n#endif\n\t\t;\n\n\tsipe_core_change_access_level_for_domain(PURPLE_GC_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t domain,\n\t\t\t\t\t\t index);\n}\n\nstatic void sipe_purple_buddy_add_new_domain_cb(PurpleBuddy *buddy,\n\t\t\t\t\t\tSIPE_UNUSED_PARAMETER gpointer parameter)\n{\n\tPurpleAccount *account = purple_buddy_get_account(buddy);\n\tPurpleConnection *gc = purple_account_get_connection(account);\n\tPurpleRequestFields *fields;\n\tPurpleRequestFieldGroup *g;\n\tPurpleRequestField *f;\n\n\tfields = purple_request_fields_new();\n\n\tg = purple_request_field_group_new(NULL);\n\tf = purple_request_field_string_new(\"access_domain\",\n\t\t\t\t\t    _(\"Domain\"),\n\t\t\t\t\t    \"partner-company.com\",\n\t\t\t\t\t    FALSE);\n\tpurple_request_field_set_required(f, TRUE);\n\tpurple_request_field_group_add_field(g, f);\n\n\tf = purple_request_field_choice_new(\"container_id\",\n\t\t\t\t\t    _(\"Access level\"),\n\t\t\t\t\t    0);\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tpurple_request_field_choice_add(f, _(\"Personal\"), GUINT_TO_POINTER(0));\n\tpurple_request_field_choice_add(f, _(\"Team\"),     GUINT_TO_POINTER(1));\n\tpurple_request_field_choice_add(f, _(\"Company\"),  GUINT_TO_POINTER(2));\n\tpurple_request_field_choice_add(f, _(\"Public\"),   GUINT_TO_POINTER(3));\n\tpurple_request_field_choice_add(f, _(\"Blocked\"),  GUINT_TO_POINTER(4));\n\tpurple_request_field_choice_set_default_value(f,  GUINT_TO_POINTER(3));\n#else\n\tpurple_request_field_choice_add(f, _(\"Personal\")); /* index 0 */\n\tpurple_request_field_choice_add(f, _(\"Team\"));\n\tpurple_request_field_choice_add(f, _(\"Company\"));\n\tpurple_request_field_choice_add(f, _(\"Public\"));\n\tpurple_request_field_choice_add(f, _(\"Blocked\")); /* index 4 */\n\tpurple_request_field_choice_set_default_value(f, 3); /* index */\n#endif\n\tpurple_request_field_set_required(f, TRUE);\n\tpurple_request_field_group_add_field(g, f);\n\n\tpurple_request_fields_add_group(fields, g);\n\n\tpurple_request_fields(gc, _(\"Add new domain\"),\n\t\t\t      _(\"Add new domain\"), NULL, fields,\n\t\t\t      _(\"Add\"), G_CALLBACK(sipe_purple_ask_access_domain_cb),\n\t\t\t      _(\"Cancel\"), NULL,\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t      purple_request_cpar_from_account(account),\n#else\n\t\t\t      account, NULL, NULL,\n#endif\n\t\t\t      gc);\n}\n\nstatic void sipe_purple_buddy_share_desktop_cb(SIPE_UNUSED_PARAMETER PurpleBuddy *buddy,\n\t\t\t\t\t       SIPE_UNUSED_PARAMETER gpointer parameter)\n{\n#ifdef HAVE_APPSHARE_SERVER\n\tsipe_core_appshare_share_desktop(PURPLE_BUDDY_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t\t purple_buddy_get_name(buddy));\n#endif\n}\n\nstatic void sipe_purple_buddy_give_desktop_control_cb(SIPE_UNUSED_PARAMETER PurpleBuddy *buddy,\n\t\t\t\t\t\t      SIPE_UNUSED_PARAMETER gpointer parameter)\n{\n#ifdef HAVE_APPSHARE_SERVER\n\tsipe_core_appshare_set_remote_control(parameter, TRUE);\n#endif\n}\n\nstatic void sipe_purple_buddy_take_desktop_control_cb(SIPE_UNUSED_PARAMETER PurpleBuddy *buddy,\n\t\t\t\t\t\t      SIPE_UNUSED_PARAMETER gpointer parameter)\n{\n#ifdef HAVE_APPSHARE_SERVER\n\tsipe_core_appshare_set_remote_control(parameter, FALSE);\n#endif\n}\n\ntypedef void (*buddy_menu_callback)(PurpleBuddy *buddy,\n\t\t\t\t    gpointer parameter);\nstatic const buddy_menu_callback callback_map[SIPE_BUDDY_MENU_TYPES] = {\n/* SIPE_BUDDY_MENU_MAKE_CHAT_LEADER    */ sipe_purple_buddy_make_chat_leader_cb,\n/* SIPE_BUDDY_MENU_REMOVE_FROM_CHAT    */ sipe_purple_buddy_remove_from_chat_cb,\n/* SIPE_BUDDY_MENU_INVITE_TO_CHAT      */ sipe_purple_buddy_invite_to_chat_cb,\n/* SIPE_BUDDY_MENU_NEW_CHAT            */ sipe_purple_buddy_new_chat_cb,\n/* SIPE_BUDDY_MENU_MAKE_CALL           */ sipe_purple_buddy_make_call_cb,\n/* SIPE_BUDDY_MENU_SEND_EMAIL          */ sipe_purple_buddy_send_email_cb,\n/* SIPE_BUDDY_MENU_ACCESS_LEVEL_HELP   */ sipe_purple_buddy_access_level_help_cb,\n/* SIPE_BUDDY_MENU_CHANGE_ACCESS_LEVEL */ sipe_purple_buddy_change_access_level_cb,\n/* SIPE_BUDDY_MENU_ADD_NEW_DOMAIN      */ sipe_purple_buddy_add_new_domain_cb,\n/* SIPE_BUDDY_MENU_SHARE_DESKTOP       */ sipe_purple_buddy_share_desktop_cb,\n/* SIPE_BUDDY_MENU_GIVE_DESKTOP_CONTROL*/ sipe_purple_buddy_give_desktop_control_cb,\n/* SIPE_BUDDY_MENU_TAKE_DESKTOP_CONTROL*/ sipe_purple_buddy_take_desktop_control_cb,\n};\n\nstruct sipe_backend_buddy_menu *sipe_backend_buddy_menu_start(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public)\n{\n\treturn(NULL);\n}\n\nstruct sipe_backend_buddy_menu *sipe_backend_buddy_menu_add(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t    struct sipe_backend_buddy_menu *menu,\n\t\t\t\t\t\t\t    const gchar *label,\n\t\t\t\t\t\t\t    enum sipe_buddy_menu_type type,\n\t\t\t\t\t\t\t    gpointer parameter)\n{\n\treturn((struct sipe_backend_buddy_menu *)\n\t       g_list_prepend((GList *) menu,\n\t\t\t      purple_action_menu_new(label,\n\t\t\t\t\t\t     PURPLE_CALLBACK(callback_map[type]),\n\t\t\t\t\t\t     parameter, NULL)));\n}\n\nstruct sipe_backend_buddy_menu *sipe_backend_buddy_menu_separator(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t\t  struct sipe_backend_buddy_menu *menu,\n\t\t\t\t\t\t\t\t  const gchar *label)\n{\n\treturn((struct sipe_backend_buddy_menu *)\n\t       g_list_prepend((GList *) menu,\n\t\t\t      purple_action_menu_new(label, NULL, NULL, NULL)));\n}\n\nstruct sipe_backend_buddy_menu *sipe_backend_buddy_sub_menu_add(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t\tstruct sipe_backend_buddy_menu *menu,\n\t\t\t\t\t\t\t\tconst gchar *label,\n\t\t\t\t\t\t\t\tstruct sipe_backend_buddy_menu *sub)\n{\n\treturn((struct sipe_backend_buddy_menu *)\n\t       g_list_prepend((GList *) menu,\n\t\t\t      purple_action_menu_new(label,\n\t\t\t\t\t\t     NULL,\n\t\t\t\t\t\t     NULL,\n\t\t\t\t\t\t     g_list_reverse((GList *) sub))));\n}\n\nstatic void sipe_purple_buddy_copy_to_cb(PurpleBlistNode *node,\n\t\t\t\t\t const gchar *group_name)\n{\n\tstruct sipe_core_public *sipe_public;\n\tPurpleBuddy *buddy = (PurpleBuddy *)node;\n\tPurpleGroup *group;\n\tPurpleBuddy *clone;\n\n\tg_return_if_fail(PURPLE_IS_BUDDY(node));\n\n\tsipe_public = PURPLE_BUDDY_TO_SIPE_CORE_PUBLIC;\n\tgroup       = purple_blist_find_group(group_name);\n\n\tSIPE_DEBUG_INFO(\"sipe_purple_buddy_copy_to_cb: copying %s to %s\",\n\t\t\tpurple_buddy_get_name(buddy), group_name);\n\n\tclone = purple_blist_find_buddy_in_group(purple_buddy_get_account(buddy),\n\t\t\t\t\t\t purple_buddy_get_name(buddy),\n\t\t\t\t\t\t group);\n\tif (!clone) {\n\t\tclone = sipe_backend_buddy_add(sipe_public,\n\t\t\t\t\t       purple_buddy_get_name(buddy),\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t\t\t       purple_buddy_get_local_alias(buddy),\n#else\n\t\t\t\t\t       buddy->alias,\n#endif\n\t\t\t\t\t       purple_group_get_name(group));\n\t\tif (clone) {\n\t\t\tconst gchar *tmp;\n\t\t\tconst gchar *key;\n\t\t\tPurpleStatus *status = purple_presence_get_active_status(purple_buddy_get_presence(buddy));\n\n\t\t\ttmp = purple_buddy_get_server_alias(buddy);\n\t\t\tif (tmp) purple_buddy_set_server_alias(clone, tmp);\n\n\t\t\tkey = buddy_info_property(SIPE_BUDDY_INFO_EMAIL);\n\t\t\ttmp = purple_blist_node_get_string(&buddy->node, key);\n\t\t\tif (tmp) purple_blist_node_set_string(&clone->node,\n\t\t\t\t\t\t\t      key,\n\t\t\t\t\t\t\t      tmp);\n\n\t\t\ttmp = purple_status_get_id(status);\n\t\t\tpurple_presence_set_status_active(purple_buddy_get_presence(clone),\n\t\t\t\t\t\t\t  tmp,\n\t\t\t\t\t\t\t  TRUE);\n\n\t\t\t/* update UI */\n\t\t\tpurple_protocol_got_user_status(purple_buddy_get_account(clone),\n\t\t\t\t\t\t\tpurple_buddy_get_name(clone),\n\t\t\t\t\t\t\ttmp,\n\t\t\t\t\t\t\tSIPE_PURPLE_STATUS_ATTR_ID_MESSAGE, tmp,\n\t\t\t\t\t\t\tNULL);\n\t\t}\n\t}\n\n\tif (clone && group)\n\t\tsipe_core_buddy_add(sipe_public,\n\t\t\t\t    purple_buddy_get_name(clone),\n\t\t\t\t    purple_group_get_name(group));\n}\n\nstatic GList *sipe_purple_copy_to_menu(GList *menu,\n\t\t\t\t       PurpleBuddy *buddy)\n{\n\tGList *menu_groups = NULL;\n\tPurpleGroup *gr_parent = purple_buddy_get_group(buddy);\n\tPurpleBlistNode *g_node;\n\n\tfor (g_node = purple_blist_get_default_root(); g_node; g_node = g_node->next) {\n\t\tPurpleGroup *group = (PurpleGroup *)g_node;\n\t\tPurpleActionMenu *act;\n\n\t\tif ((!PURPLE_IS_GROUP(g_node)) ||\n\t\t    (group == gr_parent)       ||\n\t\t    purple_blist_find_buddy_in_group(purple_buddy_get_account(buddy),\n\t\t\t\t\t\t     purple_buddy_get_name(buddy),\n\t\t\t\t\t\t     group))\n\t\t\tcontinue;\n\n\t\tact = purple_action_menu_new(purple_group_get_name(group),\n\t\t\t\t\t     PURPLE_CALLBACK(sipe_purple_buddy_copy_to_cb),\n\t\t\t\t\t     (gpointer) purple_group_get_name(group),\n\t\t\t\t\t     NULL);\n\t\tmenu_groups = g_list_prepend(menu_groups, act);\n\t}\n\n\tif (menu_groups)\n\t\tmenu = g_list_prepend(menu,\n\t\t\t\t      purple_action_menu_new(_(\"Copy to\"),\n\t\t\t\t\t\t\t     NULL,\n\t\t\t\t\t\t\t     NULL,\n\t\t\t\t\t\t\t     g_list_reverse(menu_groups)));\n\n\treturn(menu);\n}\n\nGList *sipe_purple_buddy_menu(PurpleBuddy *buddy)\n{\n\tstruct sipe_core_public *sipe_public = PURPLE_BUDDY_TO_SIPE_CORE_PUBLIC;\n\tGList *menu = (GList *) sipe_core_buddy_create_menu(sipe_public,\n\t\t\t\t\t\t\t    purple_buddy_get_name(buddy),\n\t\t\t\t\t\t\t    NULL);\n\tmenu = sipe_purple_copy_to_menu(menu, buddy);\n\treturn(g_list_reverse(menu));\n}\n\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-chat.c",
    "content": "/**\n * @file purple-chat.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2009 pier11 <pier11@operamail.com>\n *\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <time.h>\n\n#include <glib.h>\n\n#include \"conversation.h\"\n#include \"server.h\"\n/* for ENOTCONN */\n#ifdef _WIN32\n#include \"win32/win32dep.h\"\n#else\n#include <errno.h>\n#endif\n\n#include \"version.h\"\n#if PURPLE_VERSION_CHECK(3,0,0)\n#include \"action.h\"\n#include \"buddylist.h\"\n#include \"conversations.h\"\n#define BACKEND_SESSION_TO_PURPLE_CONV_CHAT(s)           ((PurpleChatConversation *) s)\n#define PURPLE_CONV_CHAT(c)                              c\n#define PURPLE_CONV_TO_SIPE_CORE_PUBLIC                  ((struct sipe_core_public *) purple_connection_get_protocol_data(purple_conversation_get_connection(conv)))\n#else\n#include \"blist.h\"\n#define purple_action_menu_new(l, c, d, ch)              purple_menu_action_new(l, c, d, ch)\n#define purple_chat_conversation_add_user(c, n, m, f, b) purple_conv_chat_add_user(c, n, m, f, b)\n#define purple_chat_conversation_clear_users(c)          purple_conv_chat_clear_users(c)\n#define purple_chat_conversation_get_id(c)               purple_conv_chat_get_id(c)\n#define purple_chat_conversation_remove_user(c, n, s)    purple_conv_chat_remove_user(c, n, s)\n#define purple_chat_conversation_set_nick(c, n)          purple_conv_chat_set_nick(c, n)\n#define purple_chat_conversation_set_topic(c, n, s)      purple_conv_chat_set_topic(c, n, s)\n#define purple_chat_get_components(chat)                 chat->components\n#define purple_conversations_find_chat(g, n)             purple_find_chat(g, n)\n#define purple_conversations_get_chats                   purple_get_chats\n#define purple_conversation_get_connection(c)            purple_conversation_get_gc(c)\n#define purple_serv_got_chat_in(c, i, w, f, m, t)        serv_got_chat_in(c, i, w, f, m, t)\n#define purple_serv_got_joined_chat(c, i, n)             serv_got_joined_chat(c, i, n)\n#define PurpleActionMenu                                 PurpleMenuAction\n#define BACKEND_SESSION_TO_PURPLE_CONV_CHAT(s)           (PURPLE_CONV_CHAT(((PurpleConversation *)s)))\n#define PURPLE_CHAT_USER_NONE                            PURPLE_CBFLAGS_NONE\n#define PURPLE_CONV_TO_SIPE_CORE_PUBLIC                  ((struct sipe_core_public *) conv->account->gc->proto_data)\n#define PURPLE_CONVERSATION_UPDATE_TOPIC                 PURPLE_CONV_UPDATE_TOPIC\n#endif\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-nls.h\"\n\n#define _PurpleMessageFlags PurpleMessageFlags\n#include \"purple-private.h\"\n\n/**\n * Mapping between chat sessions in SIPE core and libpurple backend\n *\n * PurpleAccount\n *    This data structure is created when the user creates the account or at\n *    startup. It lives as long as the account exists, i.e. until the user\n *    deletes it or shutdown.\n *\n *    Value does not change when connection is dropped & re-created.\n *    HAS: gc (PurpleConnection *)\n *\n * PurpleConversation / PurpleConvChat (sub-type)\n *    This data structure is created by serv_got_join_chat(). It lives as long\n *    as the user doesn't leave the chat or until shutdown.\n *\n *    Value does not change when connection is dropped & re-created.\n *    HAS: account (PurpleAccount *)\n *    HAS: chat ID (int), must be unique\n *    HAS: name (char *), must be unique\n *    HAS: data (GHashTable *)\n *\n * PurpleConnection\n *    This data structure is created when the connection to the service is\n *    set up. It lives as long as the connection stays open, the user disables\n *    the account or until shutdown.\n *\n *    Value *DOES NOT* survive a connection drop & re-creation.\n *    ASSOCIATED TO: account\n *\n * SIPE -> libpurple API\n *    add user:    purple_conv_chat_add_user(conv, ...)\n *    create:      serv_got_joined_chat(gc, chat ID, name)\n *    find user:   purple_conv_chat_find_user(conv, ...)\n *    message:     serv_got_chat_in(gc, chat ID, ...)\n *    remove user: purple_conv_chat_remove_user(conv, ...)\n *    topic:       purple_conv_chat_set_topic(conv, ...)\n *\n * libpurple -> SIPE API\n *    join_chat(gc, params (GHashTable *))\n *      request to join a channel (again)                 [only Group Chat]\n *      SIPE must call serv_got_joined_chat() on join response\n *\n *    reject_chat(gc, params (GHashTable *))                NOT IMPLEMENTED\n *    get_chat_name(params (GHashTable *))                  NOT IMPLEMENTED\n *\n *    chat_invite(gc, chat ID,...)\n *      invite a user to a join a chat\n *\n *    chat_leave(gc, chat ID)\n *      request to leave a channel, also called on conversation destroy\n *      SIPE must call serv_got_chat_left() immediately!\n *\n *    chat_whisper(gc, chat ID, ...)                        NOT IMPLEMENTED\n *\n *    chat_send(gc, chat ID, ...)\n *      send a message to the channel\n *\n *    set_chat_topic(gc, chat ID, ...)                      NOT IMPLEMENTED\n *      set channel topic                           [@TODO: for Group Chat]\n *\n *\n * struct sipe_chat_session\n *    Same life span as PurpleConversation\n *    Pointer stored under key \"sipe\" in PurpleConversation->data\n *    Contains information private to core to identify chat session on server\n *\n *    If connection is closed and THEN the conversation, then libpurple will\n *    not call chat_leave() and this will be a dangling data structure! Core\n *    must take care to release them at unload.\n *\n *    HAS: backend_session (gpointer) -> PurpleConversation\n *\n * struct sipe_backend_private\n *\n *    HAS: rejoin_chats (GList *)\n *         created on login() for existing chats\n *         initiate re-join calls to core (sipe_backend_chat_rejoin_all)\n */\n\n#define SIPE_PURPLE_KEY_CHAT_SESSION \"sipe\"\n\nstruct sipe_chat_session *sipe_purple_chat_get_session(PurpleConversation *conv)\n{\n\treturn(\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\tg_object_get_data(G_OBJECT(conv),\n#else\n\t\tpurple_conversation_get_data(conv,\n#endif\n\t\t\t\t  SIPE_PURPLE_KEY_CHAT_SESSION));\n}\n\nstatic struct sipe_chat_session *sipe_purple_chat_find(PurpleConnection *gc,\n\t\t\t\t\t\t       int id)\n{\n\tPurpleConversation *conv = (PurpleConversation *) purple_conversations_find_chat(gc, id);\n\n\tif (!conv) {\n\t\tSIPE_DEBUG_ERROR(\"sipe_purple_chat_find: can't find chat with ID %d?!?\",\n\t\t\t\t id);\n\t\treturn NULL;\n\t}\n\n\treturn sipe_purple_chat_get_session(conv);\n}\n\nvoid sipe_purple_chat_setup_rejoin(struct sipe_backend_private *purple_private)\n{\n\tGList *entry = purple_conversations_get_chats();\n\n\twhile (entry) {\n\t\tPurpleConversation *conv = entry->data;\n\t\tif (purple_conversation_get_connection(conv) == purple_private->gc)\n\t\t\tpurple_private->rejoin_chats = g_list_prepend(purple_private->rejoin_chats,\n\t\t\t\t\t\t\t\t      sipe_purple_chat_get_session(conv));\n\t\tentry = entry->next;\n\t}\n}\n\nvoid sipe_purple_chat_destroy_rejoin(struct sipe_backend_private *purple_private)\n{\n\tg_list_free(purple_private->rejoin_chats);\n\tpurple_private->rejoin_chats = NULL;\n}\n\nvoid sipe_purple_chat_invite(PurpleConnection *gc, int id,\n\t\t\t     SIPE_UNUSED_PARAMETER const char *message,\n\t\t\t     const char *name)\n{\n\tstruct sipe_chat_session *session = sipe_purple_chat_find(gc, id);\n\tif (!session) return;\n\n\tsipe_core_chat_invite(PURPLE_GC_TO_SIPE_CORE_PUBLIC, session, name);\n}\n\nvoid sipe_purple_chat_leave(PurpleConnection *gc, int id)\n{\n\tstruct sipe_chat_session *session = sipe_purple_chat_find(gc, id);\n\tif (!session) return;\n\n\tsipe_core_chat_leave(PURPLE_GC_TO_SIPE_CORE_PUBLIC, session);\n}\n\nint sipe_purple_chat_send(PurpleConnection *gc,\n\t\t\t  int id,\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t  PurpleMessage *msg)\n#else\n\t\t\t  const char *what,\n\t\t\t  SIPE_UNUSED_PARAMETER PurpleMessageFlags flags)\n#endif\n{\n\tstruct sipe_chat_session *session = sipe_purple_chat_find(gc, id);\n\tif (!session) return -ENOTCONN;\n\tsipe_core_chat_send(PURPLE_GC_TO_SIPE_CORE_PUBLIC, session,\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\tpurple_message_get_contents(msg));\n#else\n\t\t\twhat);\n#endif\n\treturn 1;\n}\n\nstatic void sipe_purple_chat_menu_unlock_cb(SIPE_UNUSED_PARAMETER PurpleChat *chat,\n\t\t\t\t\t    PurpleConversation *conv)\n{\n\tstruct sipe_core_public *sipe_public = PURPLE_CONV_TO_SIPE_CORE_PUBLIC;\n\tstruct sipe_chat_session *chat_session = sipe_purple_chat_get_session(conv);\n\tSIPE_DEBUG_INFO(\"sipe_purple_chat_menu_lock_cb: %p %p\", conv, chat_session);\n\tsipe_core_chat_modify_lock(sipe_public, chat_session, FALSE);\n}\n\nstatic void sipe_purple_chat_menu_lock_cb(SIPE_UNUSED_PARAMETER PurpleChat *chat,\n\t\t\t\t\t  PurpleConversation *conv)\n{\n\tstruct sipe_core_public *sipe_public = PURPLE_CONV_TO_SIPE_CORE_PUBLIC;\n\tstruct sipe_chat_session *chat_session = sipe_purple_chat_get_session(conv);\n\tSIPE_DEBUG_INFO(\"sipe_purple_chat_menu_lock_cb: %p %p\", conv, chat_session);\n\tsipe_core_chat_modify_lock(sipe_public, chat_session, TRUE);\n}\n\n#ifdef HAVE_VV\n\nstatic void\njoin_conference_call(PurpleConversation *conv, gboolean with_video)\n{\n\tstruct sipe_core_public *sipe_public = PURPLE_CONV_TO_SIPE_CORE_PUBLIC;\n\tstruct sipe_chat_session *chat_session = sipe_purple_chat_get_session(conv);\n\tsipe_core_media_connect_conference(sipe_public, chat_session, with_video);\n}\n\nstatic void sipe_purple_chat_menu_join_call_cb(SIPE_UNUSED_PARAMETER PurpleChat *chat,\n\t\t\t\t\t       PurpleConversation *conv)\n{\n\tSIPE_DEBUG_INFO(\"sipe_purple_chat_join_call_cb: %p\", conv);\n\tjoin_conference_call(conv, FALSE);\n}\n\nstatic void sipe_purple_chat_menu_join_video_call_cb(SIPE_UNUSED_PARAMETER PurpleChat *chat,\n\t\t\t\t\t\t     PurpleConversation *conv)\n{\n\tSIPE_DEBUG_INFO(\"sipe_purple_chat_join_video_call_cb: %p\", conv);\n\tjoin_conference_call(conv, TRUE);\n}\n\n#ifdef HAVE_APPSHARE\nstatic void\nsipe_purple_chat_menu_show_presentation_cb(SIPE_UNUSED_PARAMETER PurpleChat *chat,\n\t\t\t\t\t   PurpleConversation *conv)\n{\n\tsipe_appshare_role role;\n\n\trole = sipe_core_conf_get_appshare_role(PURPLE_CONV_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t\t\tsipe_purple_chat_get_session(conv));\n\n\tif (role == SIPE_APPSHARE_ROLE_VIEWER) {\n\t\treturn;\n\t}\n\n\tsipe_core_appshare_connect_conference(PURPLE_CONV_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t\t      sipe_purple_chat_get_session(conv),\n\t\t\t\t\t      FALSE);\n}\n\n#ifdef HAVE_APPSHARE_SERVER\nstatic void\nsipe_purple_chat_menu_share_desktop_cb(SIPE_UNUSED_PARAMETER PurpleChat *chat,\n\t\t\t\t       PurpleConversation *conv)\n{\n\tsipe_core_conf_share_desktop(PURPLE_CONV_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t     sipe_purple_chat_get_session(conv));\n}\n#endif\n#endif\n#endif // HAVE_VV\n\nstatic void sipe_purple_chat_menu_entry_info_cb(SIPE_UNUSED_PARAMETER PurpleChat *chat,\n\t\t\t\t\t\tPurpleConversation *conv)\n{\n\tgchar *tmp = sipe_core_conf_entry_info(PURPLE_CONV_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t\t       sipe_purple_chat_get_session(conv));\n\tpurple_notify_formatted(NULL, NULL, \"\", NULL, tmp, NULL, NULL);\n\tg_free(tmp);\n}\n\nGList *\nsipe_purple_chat_menu(PurpleChat *chat)\n{\n\tPurpleConversation *conv = g_hash_table_lookup(purple_chat_get_components(chat),\n\t\t\t\t\t\t       SIPE_PURPLE_COMPONENT_KEY_CONVERSATION);\n\tGList *menu = NULL;\n\n\tif (conv) {\n\t\tPurpleActionMenu *act = NULL;\n\t\tstruct sipe_chat_session *chat_session;\n#ifdef HAVE_APPSHARE\n\t\tsipe_appshare_role role;\n#endif\n\n\t\tSIPE_DEBUG_INFO(\"sipe_purple_chat_menu: %p\", conv);\n\n\t\tchat_session = sipe_purple_chat_get_session(conv);\n\n\t\tswitch (sipe_core_chat_lock_status(PURPLE_CONV_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t   chat_session)) {\n\t\tcase SIPE_CHAT_LOCK_STATUS_UNLOCKED:\n\t\t\tact = purple_action_menu_new(_(\"Lock\"),\n\t\t\t\t\t\t     PURPLE_CALLBACK(sipe_purple_chat_menu_lock_cb),\n\t\t\t\t\t\t     conv, NULL);\n\t\t\tbreak;\n\t\tcase SIPE_CHAT_LOCK_STATUS_LOCKED:\n\t\t\tact = purple_action_menu_new(_(\"Unlock\"),\n\t\t\t\t\t\t     PURPLE_CALLBACK(sipe_purple_chat_menu_unlock_cb),\n\t\t\t\t\t\t     conv, NULL);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t/* Not allowed */\n\t\t\tbreak;\n\t\t}\n\n\t\tif (act)\n\t\t\tmenu = g_list_prepend(menu, act);\n\n\t\tswitch (sipe_core_chat_type(chat_session)) {\n\t\tcase SIPE_CHAT_TYPE_CONFERENCE:\n\t\tcase SIPE_CHAT_TYPE_MULTIPARTY:\n#ifdef HAVE_VV\n\t\t\tif (!sipe_core_media_get_call(PURPLE_CONV_TO_SIPE_CORE_PUBLIC)) {\n\t\t\t\tact = purple_action_menu_new(_(\"Join conference video call\"),\n\t\t\t\t\t\t\t     PURPLE_CALLBACK(sipe_purple_chat_menu_join_video_call_cb),\n\t\t\t\t\t\t\t     conv, NULL);\n\t\t\t\tmenu = g_list_prepend(menu, act);\n\n\t\t\t\tact = purple_action_menu_new(_(\"Join conference call\"),\n\t\t\t\t\t\t\t     PURPLE_CALLBACK(sipe_purple_chat_menu_join_call_cb),\n\t\t\t\t\t\t\t     conv, NULL);\n\t\t\t\tmenu = g_list_prepend(menu, act);\n\t\t\t}\n#ifdef HAVE_APPSHARE\n\t\t\trole = sipe_core_conf_get_appshare_role(PURPLE_CONV_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t\t\t\t\tchat_session);\n\t\t\tif (role == SIPE_APPSHARE_ROLE_NONE) {\n\t\t\t\tact = purple_action_menu_new(_(\"Show presentation\"),\n\t\t\t\t\t\t\t     PURPLE_CALLBACK(sipe_purple_chat_menu_show_presentation_cb),\n\t\t\t\t\t\t\t     conv, NULL);\n\t\t\t\tmenu = g_list_prepend(menu, act);\n\t\t\t}\n#ifdef HAVE_APPSHARE_SERVER\n\t\t\tif (role != SIPE_APPSHARE_ROLE_PRESENTER) {\n\t\t\t\tact = purple_action_menu_new(_(\"Share my desktop\"),\n\t\t\t\t\t\t\t     PURPLE_CALLBACK(sipe_purple_chat_menu_share_desktop_cb),\n\t\t\t\t\t\t\t     conv, NULL);\n\t\t\t\tmenu = g_list_prepend(menu, act);\n\t\t\t}\n#endif\n#endif\n#endif // HAVE_VV\n\t\t\tact = purple_action_menu_new(_(\"Meeting entry info\"),\n\t\t\t\t\t\t     PURPLE_CALLBACK(sipe_purple_chat_menu_entry_info_cb),\n\t\t\t\t\t\t     conv, NULL);\n\t\t\tmenu = g_list_append(menu, act);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn menu;\n}\n\nvoid sipe_backend_chat_session_destroy(SIPE_UNUSED_PARAMETER struct sipe_backend_chat_session *session)\n{\n\t/* Nothing to do here */\n}\n\nvoid sipe_backend_chat_add(struct sipe_backend_chat_session *backend_session,\n\t\t\t   const gchar *uri,\n\t\t\t   gboolean is_new)\n{\n\tpurple_chat_conversation_add_user(BACKEND_SESSION_TO_PURPLE_CONV_CHAT(backend_session),\n\t\t\t\t\t  uri,\n\t\t\t\t\t  NULL,\n\t\t\t\t\t  PURPLE_CHAT_USER_NONE,\n\t\t\t\t\t  is_new);\n}\n\nvoid sipe_backend_chat_close(struct sipe_backend_chat_session *backend_session)\n{\n\tpurple_chat_conversation_clear_users(BACKEND_SESSION_TO_PURPLE_CONV_CHAT(backend_session));\n}\n\nstatic int sipe_purple_chat_id(PurpleConnection *gc)\n{\n\t/**\n\t * A non-volatile ID counter.\n\t * Should survive connection drop & reconnect.\n\t */\n\tstatic int chat_id = 0;\n\n\t/* Find next free ID */\n\tdo {\n\t\tif (++chat_id < 0) chat_id = 0;\n\t} while (purple_conversations_find_chat(gc, chat_id) != NULL)\n;\n\treturn chat_id;\n}\n\nstruct sipe_backend_chat_session *sipe_backend_chat_create(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t   struct sipe_chat_session *session,\n\t\t\t\t\t\t\t   const gchar *title,\n\t\t\t\t\t\t\t   const gchar *nick)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tPurpleChatConversation *conv;\n#else\n\tPurpleConversation *conv;\n#endif\n\n\t/*\n\t * Adium calls back into SIPE code during execution of the following\n\t * libpurple API. That code needs access to \"session\". As \"conv\" is\n\t * still being initialized we can't use sipe_purple_chat_get_session().\n\t */\n\tpurple_private->adium_chat_session = session;\n\tconv = purple_serv_got_joined_chat(purple_private->gc,\n\t\t\t\t\t   sipe_purple_chat_id(purple_private->gc),\n\t\t\t\t\t   title);\n\tpurple_private->adium_chat_session = NULL;\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tg_object_set_data(G_OBJECT(conv),\n#else\n\tpurple_conversation_set_data(conv,\n#endif\n\t\t\t\t     SIPE_PURPLE_KEY_CHAT_SESSION,\n\t\t\t\t     session);\n\tpurple_chat_conversation_set_nick(PURPLE_CONV_CHAT(conv), nick);\n\treturn((struct sipe_backend_chat_session *) conv);\n}\n\ngboolean sipe_backend_chat_find(struct sipe_backend_chat_session *backend_session,\n\t\t\t    const gchar *uri)\n{\n#if PURPLE_VERSION_CHECK(3,0,0)\n\treturn(purple_chat_conversation_find_user(BACKEND_SESSION_TO_PURPLE_CONV_CHAT(backend_session),\n\t\t\t\t\t\t  uri) != NULL);\n#else\n\treturn purple_conv_chat_find_user(BACKEND_SESSION_TO_PURPLE_CONV_CHAT(backend_session),\n\t\t\t\t\t  uri);\n#endif\n}\n\ngboolean sipe_backend_chat_is_operator(struct sipe_backend_chat_session *backend_session,\n\t\t\t\t       const gchar *uri)\n{\n#if PURPLE_VERSION_CHECK(3,0,0)\n\treturn((purple_chat_user_get_flags(\n\t\t\tpurple_chat_conversation_find_user(BACKEND_SESSION_TO_PURPLE_CONV_CHAT(backend_session),\n\t\t\t\t\t\t\t   uri))\n\t\t& PURPLE_CHAT_USER_OP)\n\t\t== PURPLE_CHAT_USER_OP);\n#else\n\treturn (purple_conv_chat_user_get_flags(BACKEND_SESSION_TO_PURPLE_CONV_CHAT(backend_session),\n\t\t\t\t\t\turi) & PURPLE_CBFLAGS_OP)\n\t\t== PURPLE_CBFLAGS_OP;\n#endif\n}\n\nvoid sipe_backend_chat_message(struct sipe_core_public *sipe_public,\n\t\t\t       struct sipe_backend_chat_session *backend_session,\n\t\t\t       const gchar *from,\n\t\t\t       time_t when,\n\t\t\t       const gchar *html)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tpurple_serv_got_chat_in(purple_private->gc,\n\t\t\t\tpurple_chat_conversation_get_id(BACKEND_SESSION_TO_PURPLE_CONV_CHAT(backend_session)),\n\t\t\t\tfrom,\n\t\t\t\tPURPLE_MESSAGE_RECV,\n\t\t\t\thtml,\n\t\t\t\twhen ? when : time(NULL));\n}\n\nvoid sipe_backend_chat_operator(struct sipe_backend_chat_session *backend_session,\n\t\t\t\tconst gchar *uri)\n{\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tpurple_chat_user_set_flags(\n\t\tpurple_chat_conversation_find_user(BACKEND_SESSION_TO_PURPLE_CONV_CHAT(backend_session),\n\t\t\t\t\t\t   uri),\n\t\tPURPLE_CHAT_USER_NONE | PURPLE_CHAT_USER_OP);\n#else\n\tpurple_conv_chat_user_set_flags(BACKEND_SESSION_TO_PURPLE_CONV_CHAT(backend_session),\n\t\t\t\t\turi,\n\t\t\t\t\tPURPLE_CBFLAGS_NONE | PURPLE_CBFLAGS_OP);\n#endif\n}\n\nvoid sipe_backend_chat_rejoin(struct sipe_core_public *sipe_public,\n\t\t\t      struct sipe_backend_chat_session *backend_session,\n\t\t\t      const gchar *nick,\n\t\t\t      const gchar *title)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tPurpleChatConversation *chat = BACKEND_SESSION_TO_PURPLE_CONV_CHAT(backend_session);\n\tPurpleChatConversation *new;\n#else\n\tPurpleConvChat *chat =         BACKEND_SESSION_TO_PURPLE_CONV_CHAT(backend_session);\n\tPurpleConversation *new;\n#endif\n\n\t/**\n\t * As the chat is marked as \"left\", serv_got_joined_chat() will\n\t * do a \"rejoin cleanup\" and return the same conversation.\n\t */\n\tnew = purple_serv_got_joined_chat(purple_private->gc,\n\t\t\t\t\t  purple_chat_conversation_get_id(chat),\n\t\t\t\t\t  title);\n\tSIPE_DEBUG_INFO(\"sipe_backend_chat_rejoin: old %p (%p) == new %p (%p)\",\n\t\t\tbackend_session, chat,\n\t\t\tnew, PURPLE_CONV_CHAT(new));\n\tpurple_chat_conversation_set_nick(chat, nick);\n}\n\n/**\n * Connection re-established: tell core what chats need to be rejoined\n */\nvoid sipe_backend_chat_rejoin_all(struct sipe_core_public *sipe_public)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tGList *entry = purple_private->rejoin_chats;\n\n\twhile (entry) {\n\t\tsipe_core_chat_rejoin(sipe_public, entry->data);\n\t\tentry = entry->next;\n\t}\n\tsipe_purple_chat_destroy_rejoin(purple_private);\n}\n\nvoid sipe_backend_chat_remove(struct sipe_backend_chat_session *backend_session,\n\t\t\t      const gchar *uri)\n{\n\tpurple_chat_conversation_remove_user(BACKEND_SESSION_TO_PURPLE_CONV_CHAT(backend_session),\n\t\t\t\t\t\t     uri,\n\t\t\t\t\t\t     NULL /* reason */);\n}\n\nvoid sipe_backend_chat_show(struct sipe_backend_chat_session *backend_session)\n{\n\t/* Bring existing purple chat to the front */\n\t/* @TODO: This seems to the trick, but is it the correct way? */\n\tpurple_conversation_update((PurpleConversation *) backend_session,\n\t\t\t\t   PURPLE_CONVERSATION_UPDATE_TOPIC);\n}\n\nvoid sipe_backend_chat_topic(struct sipe_backend_chat_session *backend_session,\n\t\t\t      const gchar *topic)\n{\n\tpurple_chat_conversation_set_topic(BACKEND_SESSION_TO_PURPLE_CONV_CHAT(backend_session),\n\t\t\t\t\t   NULL,\n\t\t\t\t\t   topic);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-connection.c",
    "content": "/**\n * @file purple-connection.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include \"glib.h\"\n\n#include \"connection.h\"\n\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n\n#include \"purple-private.h\"\n\n#if PURPLE_VERSION_CHECK(3,0,0)\n#else\n#define PURPLE_CONNECTION_CONNECTED        PURPLE_CONNECTED\n#define purple_account_is_disconnecting(a) a->disconnecting\n#define purple_connection_error(g, e, m)   purple_connection_error_reason(g, e, m)\n#endif\n\nvoid sipe_backend_connection_completed(struct sipe_core_public *sipe_public)\n{\n\tpurple_connection_set_state(sipe_public->backend_private->gc,\n\t\t\t\t    PURPLE_CONNECTION_CONNECTED);\n}\n\nstatic const guint map[SIPE_CONNECTION_ERROR_LAST] = {\n\tPURPLE_CONNECTION_ERROR_NETWORK_ERROR,\n\tPURPLE_CONNECTION_ERROR_INVALID_USERNAME,\n\tPURPLE_CONNECTION_ERROR_INVALID_SETTINGS,\n\tPURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,\n\tPURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,\n};\n\nvoid sipe_backend_connection_error(struct sipe_core_public *sipe_public,\n\t\t\t\t   sipe_connection_error error,\n\t\t\t\t   const gchar *msg)\n{\n\tpurple_connection_error(sipe_public->backend_private->gc,\n\t\t\t\tmap[error],\n\t\t\t\tmsg);\n}\n\ngboolean sipe_backend_connection_is_disconnecting(struct sipe_core_public *sipe_public)\n{\n\treturn(purple_account_is_disconnecting(sipe_public->backend_private->account));\n}\n\ngboolean sipe_backend_connection_is_valid(struct sipe_core_public *sipe_public)\n{\n\treturn PURPLE_CONNECTION_IS_CONNECTED(sipe_public->backend_private->gc);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-dbus-bindings.c",
    "content": "/**\n * @file purple-dbus-bindings.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2017 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n\n#include \"purple-dbus.h\"\n\n/*\n * The contents of this file need to be updated when any line which starts\n * with DBUS_EXPORT in purple-dbus.h gets added/removed/changed.\n *\n * You'll need access to the Pidgin source code to update this file:\n *\n *    $ python <path to pidgin>/libpurple/dbus-analyze-functions.py \\\n *             --export-only                                        \\\n *             src/purple/purple-dbus.h                             \\\n *             >> src/purple/purple-dbus-bindings.c\n *\n * You'll have to edit the contents manually after running the above command.\n */\n\n/*\n * The generated xxx_DBUS() functions need to be copied here\n */\n#ifdef HAVE_VV\nstatic DBusMessage*\nsipe_call_phone_number_DBUS(DBusMessage *message_DBUS, DBusError *error_DBUS) {\n\tDBusMessage *reply_DBUS;\n\tdbus_int32_t account_ID;\n\tPurpleAccount *account;\n\tconst char *phone_number;\n\tdbus_message_get_args(message_DBUS, error_DBUS, DBUS_TYPE_INT32, &account_ID, DBUS_TYPE_STRING, &phone_number, DBUS_TYPE_INVALID);\n\tCHECK_ERROR(error_DBUS);\n\tPURPLE_DBUS_ID_TO_POINTER(account, account_ID, PurpleAccount, error_DBUS);\n\tphone_number = (phone_number && phone_number[0]) ? phone_number : NULL;\n\tsipe_call_phone_number(account, phone_number);\n\treply_DBUS = dbus_message_new_method_return (message_DBUS);\n\tdbus_message_append_args(reply_DBUS, DBUS_TYPE_INVALID);\n\treturn reply_DBUS;\n}\n#endif\n\nstatic DBusMessage*\nsipe_join_conference_with_organizer_and_id_DBUS(DBusMessage *message_DBUS, DBusError *error_DBUS) {\n\tDBusMessage *reply_DBUS;\n\tdbus_int32_t account_ID;\n\tPurpleAccount *account;\n\tconst char *organizer;\n\tconst char *meeting_id;\n\tdbus_message_get_args(message_DBUS, error_DBUS, DBUS_TYPE_INT32, &account_ID, DBUS_TYPE_STRING, &organizer, DBUS_TYPE_STRING, &meeting_id, DBUS_TYPE_INVALID);\n\tCHECK_ERROR(error_DBUS);\n\tPURPLE_DBUS_ID_TO_POINTER(account, account_ID, PurpleAccount, error_DBUS);\n\torganizer = (organizer && organizer[0]) ? organizer : NULL;\n\tmeeting_id = (meeting_id && meeting_id[0]) ? meeting_id : NULL;\n\tsipe_join_conference_with_organizer_and_id(account, organizer, meeting_id);\n\treply_DBUS = dbus_message_new_method_return (message_DBUS);\n\tdbus_message_append_args(reply_DBUS, DBUS_TYPE_INVALID);\n\treturn reply_DBUS;\n}\n\nstatic DBusMessage*\nsipe_join_conference_with_uri_DBUS(DBusMessage *message_DBUS, DBusError *error_DBUS) {\n\tDBusMessage *reply_DBUS;\n\tdbus_int32_t account_ID;\n\tPurpleAccount *account;\n\tconst char *uri;\n\tdbus_message_get_args(message_DBUS, error_DBUS, DBUS_TYPE_INT32, &account_ID, DBUS_TYPE_STRING, &uri, DBUS_TYPE_INVALID);\n\tCHECK_ERROR(error_DBUS);\n\tPURPLE_DBUS_ID_TO_POINTER(account, account_ID, PurpleAccount, error_DBUS);\n\turi = (uri && uri[0]) ? uri : NULL;\n\tsipe_join_conference_with_uri(account, uri);\n\treply_DBUS = dbus_message_new_method_return (message_DBUS);\n\tdbus_message_append_args(reply_DBUS, DBUS_TYPE_INVALID);\n\treturn reply_DBUS;\n}\n\nstatic DBusMessage*\nsipe_republish_calendar_DBUS(DBusMessage *message_DBUS, DBusError *error_DBUS) {\n\tDBusMessage *reply_DBUS;\n\tdbus_int32_t account_ID;\n\tPurpleAccount *account;\n\tdbus_message_get_args(message_DBUS, error_DBUS, DBUS_TYPE_INT32, &account_ID, DBUS_TYPE_INVALID);\n\tCHECK_ERROR(error_DBUS);\n\tPURPLE_DBUS_ID_TO_POINTER(account, account_ID, PurpleAccount, error_DBUS);\n\tsipe_republish_calendar(account);\n\treply_DBUS = dbus_message_new_method_return (message_DBUS);\n\tdbus_message_append_args(reply_DBUS, DBUS_TYPE_INVALID);\n\treturn reply_DBUS;\n}\n\nstatic DBusMessage*\nsipe_reset_status_DBUS(DBusMessage *message_DBUS, DBusError *error_DBUS) {\n\tDBusMessage *reply_DBUS;\n\tdbus_int32_t account_ID;\n\tPurpleAccount *account;\n\tdbus_message_get_args(message_DBUS, error_DBUS, DBUS_TYPE_INT32, &account_ID, DBUS_TYPE_INVALID);\n\tCHECK_ERROR(error_DBUS);\n\tPURPLE_DBUS_ID_TO_POINTER(account, account_ID, PurpleAccount, error_DBUS);\n\tsipe_reset_status(account);\n\treply_DBUS = dbus_message_new_method_return (message_DBUS);\n\tdbus_message_append_args(reply_DBUS, DBUS_TYPE_INVALID);\n\treturn reply_DBUS;\n}\n\n/*\n * The contents of bindings_DBUS[] need to be copied here\n */\nPurpleDBusBinding sipe_purple_dbus_bindings[] = {\n#ifdef HAVE_VV\n\t{\"SipeCallPhoneNumber\", \"in\\0i\\0account\\0in\\0s\\0phone_number\\0\", sipe_call_phone_number_DBUS},\n#endif\n\t{\"SipeJoinConferenceWithOrganizerAndId\", \"in\\0i\\0account\\0in\\0s\\0organizer\\0in\\0s\\0meeting_id\\0\", sipe_join_conference_with_organizer_and_id_DBUS},\n\t{\"SipeJoinConferenceWithUri\", \"in\\0i\\0account\\0in\\0s\\0uri\\0\", sipe_join_conference_with_uri_DBUS},\n\t{\"SipeRepublishCalendar\", \"in\\0i\\0account\\0\", sipe_republish_calendar_DBUS},\n\t{\"SipeResetStatus\", \"in\\0i\\0account\\0\", sipe_reset_status_DBUS},\n\t{NULL, NULL, NULL}\n};\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-dbus.c",
    "content": "/**\n * @file purple-dbus.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2017 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n\n#include \"account.h\"\n#include \"connection.h\"\n\n#include \"sipe-core.h\"\n\n#include \"purple-dbus.h\"\n#include \"purple-private.h\"\n\n#if PURPLE_VERSION_CHECK(3,0,0)\n#else\n#define purple_account_is_disconnecting(a) a->disconnecting\n#endif\n\n/**\n * A call to our D-Bus interface is independent from the actual libpurple\n * state. Therefore we can't trust any of the incoming data.\n *\n * @param account (in) libpurple account (may be @c NULL)\n *\n * @return @c TRUE if it is safe to use PURPLE_ACCOUNT_TO_SIPE_CORE_PUBLIC\n */\nstatic gboolean account_is_valid(PurpleAccount *account)\n{\n\tgboolean valid = FALSE;\n\n\tif (account &&\n\t    !purple_account_is_disconnecting(account) &&\n\t    (sipe_strequal(purple_account_get_protocol_id(account), SIPE_PURPLE_PLUGIN_ID))) {\n\t\tPurpleConnection *gc = purple_account_get_connection(account);\n\n\t\tif (gc && PURPLE_CONNECTION_IS_CONNECTED(gc))\n\t\t\tvalid = TRUE;\n\t}\n\n\treturn(valid);\n}\n\n#ifdef HAVE_VV\nvoid sipe_call_phone_number(PurpleAccount *account,\n\t\t\t    const gchar *phone_number)\n{\n\t/* Make sure phone number is valid before calling to core */\n\tif (account_is_valid(account) && phone_number)\n\t\tsipe_core_media_phone_call(PURPLE_ACCOUNT_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t\t   phone_number);\n}\n#endif\n\nvoid sipe_join_conference_with_organizer_and_id(PurpleAccount *account,\n\t\t\t\t\t\tconst gchar *organizer,\n\t\t\t\t\t\tconst gchar *meeting_id)\n{\n\t/* Make sure organizer & ID are valid before calling to core */\n\tif (account_is_valid(account) && organizer && meeting_id)\n\t\tsipe_core_conf_create(PURPLE_ACCOUNT_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t      NULL,\n\t\t\t\t      organizer,\n\t\t\t\t      meeting_id);\n}\n\nvoid sipe_join_conference_with_uri(PurpleAccount *account,\n\t\t\t\t   const gchar *uri)\n{\n\t/* Make sure URI is valid before calling to core */\n\tif (account_is_valid(account) && uri)\n\t\tsipe_core_conf_create(PURPLE_ACCOUNT_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t      uri,\n\t\t\t\t      NULL,\n\t\t\t\t      NULL);\n}\n\nvoid sipe_republish_calendar(PurpleAccount *account)\n{\n\tif (account_is_valid(account))\n\t\tsipe_purple_republish_calendar(account);\n}\n\nvoid sipe_reset_status(PurpleAccount *account)\n{\n\tif (account_is_valid(account))\n\t\tsipe_purple_reset_status(account);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-dbus.h",
    "content": "/**\n * @file purple-dbus.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2017 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/*\n * Work around some versions of dbus-server.h that redefine DBUS_EXPORT\n * without checking that it is already defined. Include dbus/dbus.h first\n * to suppress the implicit inclusion through dbus-server.h. Then undefine\n * the macro to avoid the potential build failure.\n */\n#include <dbus/dbus.h>\n#ifdef DBUS_EXPORT\n#undef DBUS_EXPORT\n#endif\n#include \"dbus-server.h\"\n#include \"account.h\"\n\nextern PurpleDBusBinding sipe_purple_dbus_bindings[];\n\n/**\n * SipeCallPhoneNumber - call phone number\n *\n * @param account (in) libpurple account\n * @param number  (in) phone number string\n */\nDBUS_EXPORT void sipe_call_phone_number(PurpleAccount *account,\n\t\t\t\t\tconst gchar *phone_number);\n\n/**\n * SipeJoinConferenceWithOrganizerAndId - join conference using\n * organizer account name and meeting ID\n *\n * @param account   (in) libpurple account\n * @param organizer (in) organizer account name\n * @param id        (in) meeting ID string\n */\nDBUS_EXPORT void sipe_join_conference_with_organizer_and_id(PurpleAccount *account,\n\t\t\t\t\t\t\t    const gchar *organizer,\n\t\t\t\t\t\t\t    const gchar *meeting_id);\n\n/**\n * SipeJoinConferenceWithUri - join conference using URI\n *\n * @param account (in) libpurple account\n * @param uri     (in) URI string\n */\nDBUS_EXPORT void sipe_join_conference_with_uri(PurpleAccount *account,\n\t\t\t\t\t       const gchar *uri);\n\n/**\n * SipeRepublishCalendar\n */\nDBUS_EXPORT void sipe_republish_calendar(PurpleAccount *account);\n\n/**\n * SipeResetStatus\n */\nDBUS_EXPORT void sipe_reset_status(PurpleAccount *account);\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-debug.c",
    "content": "/**\n * @file purple-debug.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2017 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <stdarg.h>\n\n#include \"glib.h\"\n#include \"debug.h\"\n#include \"version.h\"\n\n#include \"sipe-backend.h\"\n\n#ifdef ADIUM\n/*\n * libpurple uses g_print() and PurpleDebugUiOps->debug() when\n * purple_debug_is_enabled() returns TRUE. Both are redirected\n * by Adium to AILog(). To avoid duplicated log lines Adium\n * therefore never calls purple_debug_set_enabled(TRUE).\n */\ngboolean AIDebugLoggingIsEnabled(void);\n#define SIPE_PURPLE_DEBUG_IS_ENABLED AIDebugLoggingIsEnabled()\n#define SIPE_PURPLE_DEBUG_IS_UNSAFE  AIDebugLoggingIsEnabled()\n#else\n/*\n * The same problem happens when a client uses PurpleDebugUiOps->debug()\n * to redirect it to stderr, e.g. bitlbee. Such a client will not call\n * purple_debug_set_enabled(TRUE). Check also the other flags that were\n * introduced in the 2.6.x API.\n */\n#define SIPE_PURPLE_DEBUG_IS_ENABLED (purple_debug_is_enabled() || \\\n\t\t\t\t      purple_debug_is_verbose() || \\\n\t\t\t\t      purple_debug_is_unsafe())\n#define SIPE_PURPLE_DEBUG_IS_UNSAFE  purple_debug_is_unsafe()\n#endif\n\nvoid sipe_backend_debug_literal(sipe_debug_level level,\n\t\t\t\tconst gchar *msg)\n{\n\tif ((level < SIPE_DEBUG_LEVEL_LOWEST) || SIPE_PURPLE_DEBUG_IS_ENABLED) {\n\n\t\t/* purple_debug doesn't have a vprintf-like API call :-( */\n\t\tswitch (level) {\n\t\tcase SIPE_LOG_LEVEL_INFO:\n\t\tcase SIPE_DEBUG_LEVEL_INFO:\n\t\t\tpurple_debug_info(\"sipe\", \"%s\\n\", msg);\n\t\t\tbreak;\n\t\tcase SIPE_LOG_LEVEL_WARNING:\n\t\tcase SIPE_DEBUG_LEVEL_WARNING:\n\t\t\tpurple_debug_warning(\"sipe\", \"%s\\n\", msg);\n\t\t\tbreak;\n\t\tcase SIPE_LOG_LEVEL_ERROR:\n\t\tcase SIPE_DEBUG_LEVEL_ERROR:\n\t\t\tpurple_debug_error(\"sipe\", \"%s\\n\", msg);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid sipe_backend_debug(sipe_debug_level level,\n\t\t\tconst gchar *format,\n\t\t\t...)\n{\n\tva_list ap;\n\n\tva_start(ap, format);\n\n\tif ((level < SIPE_DEBUG_LEVEL_LOWEST) || SIPE_PURPLE_DEBUG_IS_ENABLED) {\n\n\t\t/* purple_debug doesn't have a vprintf-like API call :-( */\n\t\tgchar *msg = g_strdup_vprintf(format, ap);\n\t\tsipe_backend_debug_literal(level, msg);\n\t\tg_free(msg);\n\t}\n\n\tva_end(ap);\n}\n\ngboolean sipe_backend_debug_enabled(void)\n{\n\treturn SIPE_PURPLE_DEBUG_IS_UNSAFE;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-dnsquery.c",
    "content": "/**\n * @file purple-dnsquery.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n\n#include \"version.h\"\n\n#if PURPLE_VERSION_CHECK(2,8,0)\n#include \"account.h\"\n#endif\n#if PURPLE_VERSION_CHECK(3,0,0)\n#include \"protocols.h\"\n#include <gio/gio.h>\n#else\n\n#ifdef _WIN32\n/* wrappers for write() & friends for socket handling */\n#include \"win32/win32dep.h\"\n#include <ws2tcpip.h>\n#else\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <arpa/inet.h>\n#endif\n\n#include \"dnsquery.h\"\n#include \"dnssrv.h\"\n\n#endif\n\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n\n#include \"purple-private.h\"\n\nstruct sipe_dns_query {\n\tstruct sipe_backend_private *purple_private;\n\tsipe_dns_resolved_cb  callback;\n\tgpointer\t      extradata;\n\tgpointer\t      purple_query_data;\n\tgboolean              is_valid;\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tguint\t\t      port;\n#else\n\tenum {\n\t\tA,\n\t\tSRV\n\t} type;\n#endif\n};\n\nstatic void sipe_dns_query_free(struct sipe_dns_query *query)\n{\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tg_object_unref(query->purple_query_data);\n#endif\n\tg_free(query);\n}\n\n#if PURPLE_VERSION_CHECK(3,0,0)\nstatic void dns_a_response(GObject *source,\n\t\t\t   GAsyncResult *res,\n\t\t\t   gpointer user_data)\n{\n\tstruct sipe_dns_query *query = user_data;\n\tGList *hosts;\n\tGError *error = NULL;\n\tgchar *address_str = NULL;\n\n\tif (!query->is_valid) {\n\t\t/* Ignore spurious responses after disconnect */\n\t\treturn;\n\t}\n\n\tquery->purple_private->dns_queries =\n\t\t\tg_slist_remove(query->purple_private->dns_queries,\n\t\t\t\t       query);\n\n\thosts = g_resolver_lookup_by_name_finish(G_RESOLVER(source), res,\n\t\t\t\t\t\t &error);\n\n\tif (!error && g_list_length(hosts) > 0) {\n\t\taddress_str = g_inet_address_to_string(hosts->data);\n\t}\n\n\tquery->callback(query->extradata, address_str,\n\t\t\taddress_str ? query->port : 0);\n\n\tg_free(address_str);\n\tif (error)\n\t\tg_error_free(error);\n\tg_resolver_free_addresses(hosts);\n\tsipe_dns_query_free(query);\n}\n#else\nstatic void dns_a_response(GSList *hosts,\n\t\t\t   struct sipe_dns_query *query,\n\t\t\t   const char *error_message)\n{\n\tchar ipstr[INET6_ADDRSTRLEN];\n\tstruct sockaddr *addr;\n\tconst void *addrdata;\n\tint port;\n\n        /* Ignore spurious responses after disconnect */\n\tif (query->is_valid) {\n\t\tstruct sipe_backend_private *purple_private = query->purple_private;\n\n\t\tpurple_private->dns_queries = g_slist_remove(purple_private->dns_queries,\n\t\t\t\t\t\t\t     query);\n\n\t\tif (error_message || !g_slist_next(hosts)) {\n\t\t\tquery->callback(query->extradata, NULL, 0);\n\t\t\tg_slist_free(hosts);\n\t\t\treturn;\n\t\t}\n\n\t\taddr = g_slist_next(hosts)->data;\n\t\tif (addr->sa_family == AF_INET6) {\n\t\t\t/* OS provides addr so it must be properly aligned */\n\t\t\tstruct sockaddr_in6 *sin6 = (void *) addr;\n\t\t\taddrdata = &sin6->sin6_addr;\n\t\t\tport = sin6->sin6_port;\n\t\t} else {\n\t\t\t/* OS provides addr so it must be properly aligned */\n\t\t\tstruct sockaddr_in *sin = (void *) addr;\n\t\t\taddrdata = &sin->sin_addr;\n\t\t\tport = sin->sin_port;\n\t\t}\n\n\t\tinet_ntop(addr->sa_family, addrdata, ipstr, sizeof (ipstr));\n\n\t\tquery->callback(query->extradata, ipstr, port);\n\n\t\tg_free(query);\n\t}\n\n\tfor (; hosts; hosts = g_slist_delete_link(hosts, hosts)) {\n\t\t// Free the addrlen, no data in this link\n\t\thosts = g_slist_delete_link(hosts, hosts);\n\t\t// Free the address\n\t\tg_free(hosts->data);\n\t}\n}\n#endif\n\nstruct sipe_dns_query *sipe_backend_dns_query_a(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\tconst gchar *hostname,\n\t\t\t\t\t\tguint port,\n\t\t\t\t\t\tsipe_dns_resolved_cb callback,\n\t\t\t\t\t\tgpointer data)\n{\n\tstruct sipe_dns_query *query = g_new(struct sipe_dns_query, 1);\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tGResolver *resolver = g_resolver_get_default();\n#endif\n\n\tquery->purple_private = purple_private;\n\tquery->callback       = callback;\n\tquery->extradata      = data;\n\tquery->is_valid       = TRUE;\n\n\tpurple_private->dns_queries = g_slist_prepend(purple_private->dns_queries,\n\t\t\t\t\t\t      query);\n\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tquery->port = port;\n\tquery->purple_query_data = g_cancellable_new();\n\n\tg_resolver_lookup_by_name_async(resolver,\n\t\t\t\t\thostname,\n\t\t\t\t\tquery->purple_query_data,\n\t\t\t\t\tdns_a_response,\n\t\t\t\t\tquery);\n\tg_object_unref(resolver);\n#else\n\tquery->type = A;\n\tquery->purple_query_data =\n#if PURPLE_VERSION_CHECK(2,8,0)\n\t\t\t\t\tpurple_dnsquery_a_account(\n\t\t\t\t\t\t     purple_private->account,\n#else\n\t\t\t\t\tpurple_dnsquery_a(\n#endif\n\t\t\t\t\t\t     hostname,\n\t\t\t\t\t\t     port,\n\t\t\t\t\t\t     (PurpleDnsQueryConnectFunction) dns_a_response,\n\t\t\t\t\t\t     query);\n#endif\n\n\treturn query;\n}\n\n#if PURPLE_VERSION_CHECK(3,0,0)\nstatic void dns_srv_response(GObject *source,\n\t\t\t     GAsyncResult *res,\n\t\t\t     gpointer user_data)\n{\n\tstruct sipe_dns_query *query = user_data;\n\tGError *error = NULL;\n\tGList *targets;\n\n\tif (!query->is_valid) {\n\t\t/* Ignore spurious responses after disconnect */\n\t\treturn;\n\t}\n\n\tquery->purple_private->dns_queries =\n\t\t\tg_slist_remove(query->purple_private->dns_queries,\n\t\t\t\t       query);\n\n\ttargets = g_resolver_lookup_service_finish(G_RESOLVER(source), res,\n\t\t\t\t\t\t   &error);\n\n\tif (error || g_list_length(targets) == 0) {\n\t\tquery->callback(query->extradata, NULL, 0);\n\t} else {\n\t\tquery->callback(query->extradata,\n\t\t\t\tg_srv_target_get_hostname(targets->data),\n\t\t\t\tg_srv_target_get_port(targets->data));\n\t}\n\n\tif (error)\n\t\tg_error_free(error);\n\tg_resolver_free_targets(targets);\n\tsipe_dns_query_free(query);\n}\n#else\nstatic void dns_srv_response(PurpleSrvResponse *resp,\n\t\t\t     int results,\n\t\t\t     struct sipe_dns_query *query)\n{\n        /* Ignore spurious responses after disconnect */\n\tif (query->is_valid) {\n\t\tstruct sipe_backend_private *purple_private = query->purple_private;\n\n\t\tpurple_private->dns_queries = g_slist_remove(purple_private->dns_queries,\n\t\t\t\t\t\t\t     query);\n\n\t\tif (results)\n\t\t\tquery->callback(query->extradata, resp->hostname, resp->port);\n\t\telse\n\t\t\tquery->callback(query->extradata, NULL, 0);\n\n\t\tg_free(query);\n\t}\n\n\tg_free(resp);\n}\n#endif\n\nstruct sipe_dns_query *sipe_backend_dns_query_srv(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t  const gchar *protocol,\n\t\t\t\t\t\t  const gchar *transport,\n\t\t\t\t\t\t  const gchar *domain,\n\t\t\t\t\t\t  sipe_dns_resolved_cb callback,\n\t\t\t\t\t\t  gpointer data)\n{\n\tstruct sipe_dns_query *query = g_new(struct sipe_dns_query, 1);\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tGResolver *resolver = g_resolver_get_default();\n#endif\n\n\tquery->purple_private = purple_private;\n\tquery->callback       = callback;\n\tquery->extradata      = data;\n\tquery->is_valid       = TRUE;\n\n\tpurple_private->dns_queries = g_slist_prepend(purple_private->dns_queries,\n\t\t\t\t\t\t      query);\n\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tquery->purple_query_data = g_cancellable_new();\n\n\tg_resolver_lookup_service_async(resolver,\n\t\t\t\t\tprotocol,\n\t\t\t\t\ttransport,\n\t\t\t\t\tdomain,\n\t\t\t\t\tquery->purple_query_data,\n\t\t\t\t\tdns_srv_response,\n\t\t\t\t\tquery);\n\tg_object_unref(resolver);\n#else\n\tquery->type = SRV;\n\tquery->purple_query_data =\n#if PURPLE_VERSION_CHECK(2,8,0)\n\t\t\t\t\tpurple_srv_resolve_account(\n\t\t\t\t\t\t      purple_private->account,\n#else\n\t\t\t\t\tpurple_srv_resolve(\n#endif\n\t\t\t\t\t\t      protocol,\n\t\t\t\t\t\t      transport,\n\t\t\t\t\t\t      domain,\n\t\t\t\t\t\t      (PurpleSrvCallback) dns_srv_response,\n\t\t\t\t\t\t      query);\n#endif\n\n\treturn query;\n}\n\nstatic gboolean dns_query_deferred_destroy(gpointer user_data)\n{\n\t/*\n\t * All pending events on query have been processed.\n\t * Now it is safe to destroy the data structure.\n\t */\n\tSIPE_DEBUG_INFO(\"dns_query_deferred_destroy: %p\", user_data);\n\tsipe_dns_query_free(user_data);\n\treturn(FALSE);\n}\n\nvoid sipe_backend_dns_query_cancel(struct sipe_dns_query *query)\n{\n\tSIPE_DEBUG_INFO(\"sipe_backend_dns_query_cancel: %p\", query);\n\n\tif (query->is_valid) {\n\t\tstruct sipe_backend_private *purple_private = query->purple_private;\n\t\tpurple_private->dns_queries = g_slist_remove(purple_private->dns_queries,\n\t\t\t\t\t\t\t     query);\n\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\tg_cancellable_cancel(query->purple_query_data);\n#else\n\t\tswitch (query->type) {\n\t\tcase A:\n\t\t\tpurple_dnsquery_destroy(query->purple_query_data);\n\t\t\tbreak;\n\t\tcase SRV:\n#if PURPLE_VERSION_CHECK(2,8,0)\n\t\t\tpurple_srv_txt_query_destroy(query->purple_query_data);\n#else\n\t\t\tpurple_srv_cancel(query->purple_query_data);\n#endif\n\t\t\tbreak;\n\t\t}\n#endif\n\n\t\t/* defer deletion of query data structure to idle callback */\n\t\tquery->is_valid = FALSE;\n\t\tg_idle_add(dns_query_deferred_destroy, query);\n\t}\n}\n\nvoid sipe_purple_dns_query_cancel_all(struct sipe_backend_private *purple_private)\n{\n\tGSList *entry;\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_purple_dns_query_cancel_all: entered\");\n\twhile ((entry = purple_private->dns_queries) != NULL)\n\t\tsipe_backend_dns_query_cancel(entry->data);\n}\n\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-ft.c",
    "content": "/**\n * @file purple-ft.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2010 Jakub Adam <jakub.adam@ktknet.cz>\n * Copyright (C) 2010 Tomáš Hrabčík <tomas.hrabcik@tieto.com>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <string.h>\n#include <fcntl.h>\n#include <errno.h>\n\n#ifdef HAVE_UNISTD_H\n#include <unistd.h>\n#endif\n\n#include <glib.h>\n\n#include \"version.h\"\n#if PURPLE_VERSION_CHECK(3,0,0)\n#include \"protocol.h\"\n#define PURPLE_XFER_TO_SIPE_CORE_PUBLIC        ((struct sipe_core_public *) purple_connection_get_protocol_data(purple_account_get_connection(purple_xfer_get_account(xfer))))\n#define PURPLE_XFER_TO_SIPE_FILE_TRANSFER      (SIPE_PURPLE_XFER(xfer)->ft)\n\n#define SIPE_TYPE_PURPLE_XFER (sipe_purple_xfer_get_type())\nG_DECLARE_FINAL_TYPE(SipePurpleXfer, sipe_purple_xfer, SIPE, PURPLE_XFER, PurpleXfer);\n\nstruct _SipePurpleXfer\n{\n\tPurpleXfer parent;\n\tstruct sipe_file_transfer *ft;\n};\n#else\n#include \"ft.h\"\n#define g_timeout_add(t, f, d)                 purple_timeout_add(t, f, d)\n#define PurpleXferStatus                       PurpleXferStatusType\n#define PURPLE_XFER_TO_SIPE_CORE_PUBLIC        ((struct sipe_core_public *) purple_account_get_connection(xfer->account)->proto_data)\n#define PURPLE_XFER_TO_SIPE_FILE_TRANSFER      ((struct sipe_file_transfer *) purple_xfer_get_protocol_data(xfer))\n#define PURPLE_XFER_TYPE_RECEIVE               PURPLE_XFER_RECEIVE\n#define PURPLE_XFER_TYPE_SEND                  PURPLE_XFER_SEND\n#define purple_xfer_get_fd(xfer)               xfer->fd\n#define purple_xfer_get_protocol_data(xfer)    xfer->data\n#define purple_xfer_get_status(xfer)           purple_xfer_get_status(xfer)\n#define purple_xfer_get_xfer_type(xfer)        purple_xfer_get_type(xfer)\n#define purple_xfer_get_watcher(xfer)          xfer->watcher\n#define purple_xfer_set_protocol_data(xfer, d) xfer->data = d\n#define purple_xfer_set_watcher(xfer, w)       xfer->watcher = w\n#endif\n\n#ifdef _WIN32\n/* wrappers for write() & friends for socket handling */\n#include \"win32/win32dep.h\"\n#endif\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n\n#include \"purple-private.h\"\n\n#define FT_TO_PURPLE_XFER                      ((PurpleXfer *) ft->backend_private)\n\nvoid sipe_backend_ft_error(struct sipe_file_transfer *ft,\n\t\t\t   const char *errmsg)\n{\n\tPurpleXfer *xfer = FT_TO_PURPLE_XFER;\n\tpurple_xfer_error(purple_xfer_get_xfer_type(xfer),\n\t\t\t  purple_xfer_get_account(xfer),\n\t\t\t  purple_xfer_get_remote_user(xfer),\n\t\t\t  errmsg);\n}\n\nconst gchar *sipe_backend_ft_get_error(SIPE_UNUSED_PARAMETER struct sipe_file_transfer *ft)\n{\n\treturn strerror(errno);\n}\n\nvoid sipe_backend_ft_deallocate(struct sipe_file_transfer *ft)\n{\n\tPurpleXfer *xfer = FT_TO_PURPLE_XFER;\n\tPurpleXferStatus status = purple_xfer_get_status(xfer);\n\n\t// If file transfer is not finished, cancel it\n\tif (   status != PURPLE_XFER_STATUS_DONE\n\t\t&& status != PURPLE_XFER_STATUS_CANCEL_LOCAL\n\t\t&& status != PURPLE_XFER_STATUS_CANCEL_REMOTE) {\n\t\tpurple_xfer_cancel_remote(xfer);\n\t}\n}\n\ngssize sipe_backend_ft_read(struct sipe_file_transfer *ft,\n\t\t\t    guchar *data,\n\t\t\t    gsize size)\n{\n\tgssize bytes_read = read(purple_xfer_get_fd(FT_TO_PURPLE_XFER),\n\t\t\t\t data,\n\t\t\t\t size);\n\tif (bytes_read == 0) {\n\t\t/* Sender canceled transfer before it was finished */\n\t\treturn -2;\n\t} else if (bytes_read == -1) {\n\t\tif (errno == EAGAIN)\n\t\t\treturn 0;\n\t\telse\n\t\t\treturn -1;\n\t}\n\treturn bytes_read;\n}\n\ngssize sipe_backend_ft_write(struct sipe_file_transfer *ft,\n\t\t\t     const guchar *data,\n\t\t\t     gsize size)\n{\n\tgssize bytes_written = write(purple_xfer_get_fd(FT_TO_PURPLE_XFER),\n\t\t\t\t     data,\n\t\t\t\t     size);\n\tif (bytes_written == -1) {\n\t\tif (errno == EAGAIN)\n\t\t\treturn 0;\n\t\telse\n\t\t\treturn -1;\n\t}\n\treturn bytes_written;\n}\n\nstatic gboolean\nend_transfer_cb(gpointer data)\n{\n\tpurple_xfer_end((PurpleXfer *)data);\n\treturn FALSE;\n}\n\nvoid\nsipe_backend_ft_set_completed(struct sipe_file_transfer *ft)\n{\n\tpurple_xfer_set_completed(FT_TO_PURPLE_XFER, TRUE);\n\tg_timeout_add(0, end_transfer_cb, FT_TO_PURPLE_XFER);\n}\n\nvoid sipe_backend_ft_cancel_local(struct sipe_file_transfer *ft)\n{\n\tpurple_xfer_cancel_local(FT_TO_PURPLE_XFER);\n}\n\nvoid sipe_backend_ft_cancel_remote(struct sipe_file_transfer *ft)\n{\n\tpurple_xfer_cancel_remote(FT_TO_PURPLE_XFER);\n}\n\nstatic void\nft_free_xfer_struct(PurpleXfer *xfer)\n{\n\tif (purple_xfer_get_watcher(xfer)) {\n\t\tpurple_input_remove(purple_xfer_get_watcher(xfer));\n\t\tpurple_xfer_set_watcher(xfer, 0);\n\t}\n\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tSIPE_PURPLE_XFER(xfer)->ft = NULL;\n#else\n\tpurple_xfer_set_protocol_data(xfer, NULL);\n#endif\n}\n\nstatic void\nft_request_denied(PurpleXfer *xfer)\n{\n\tstruct sipe_file_transfer *ft = PURPLE_XFER_TO_SIPE_FILE_TRANSFER;\n\tif (ft->ft_request_denied) {\n\t\tft->ft_request_denied(ft);\n\t}\n\n\tft_free_xfer_struct(xfer);\n}\n\nstatic void\nft_cancelled(PurpleXfer *xfer)\n{\n\tstruct sipe_file_transfer *ft = PURPLE_XFER_TO_SIPE_FILE_TRANSFER;\n\n\tif (ft->ft_cancelled &&\n\t    purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL) {\n\t\tft->ft_cancelled(ft);\n\t}\n\n\tft_free_xfer_struct(xfer);\n}\n\nstatic void\nft_init(PurpleXfer *xfer)\n{\n\tstruct sipe_file_transfer *ft = PURPLE_XFER_TO_SIPE_FILE_TRANSFER;\n\tg_return_if_fail(ft->ft_init);\n\n\tft->ft_init(ft,\n\t\t    purple_xfer_get_filename(xfer),\n\t\t    purple_xfer_get_size(xfer),\n\t\t    purple_xfer_get_remote_user(xfer));\n}\n\nstatic void\nft_start(PurpleXfer *xfer)\n{\n\tstruct sipe_file_transfer *ft = PURPLE_XFER_TO_SIPE_FILE_TRANSFER;\n\n\tif (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_RECEIVE) {\n\t\t/* Set socket to non-blocking mode */\n\t\tint flags = fcntl(purple_xfer_get_fd(xfer), F_GETFL, 0);\n\t\tif (flags == -1) {\n\t\t\tflags = 0;\n\t\t}\n\t\t/* @TODO: ignoring potential error return - how to handle? */\n\t\t(void) fcntl(purple_xfer_get_fd(xfer), F_SETFL, flags | O_NONBLOCK);\n\t}\n\n\tif (ft->ft_start) {\n\t\tft->ft_start(ft, purple_xfer_get_size(xfer));\n\t}\n}\n\nstatic void\nft_end(PurpleXfer *xfer)\n{\n\tstruct sipe_file_transfer *ft = PURPLE_XFER_TO_SIPE_FILE_TRANSFER;\n\n\tif (!ft->ft_end || ft->ft_end(ft)) {\n\t\t/* We're done with this transfer */\n\t\tft_free_xfer_struct(xfer);\n\t} else if (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_RECEIVE) {\n\t\t/* Remove incomplete file from failed transfer. */\n\t\tunlink(purple_xfer_get_local_filename(xfer));\n\t}\n}\n\nstatic gssize\nft_read(guchar **buffer,\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\tsize_t buffer_size,\n#endif\n\t\t\tPurpleXfer *xfer)\n{\n\tstruct sipe_file_transfer *ft = PURPLE_XFER_TO_SIPE_FILE_TRANSFER;\n\tg_return_val_if_fail(ft->ft_read, 0);\n\treturn ft->ft_read(ft, buffer, purple_xfer_get_bytes_remaining(xfer),\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t   buffer_size\n#else\n\t\t\t   xfer->current_buffer_size\n#endif\n\t);\n}\n\nstatic gssize\nft_write(const guchar *buffer, size_t size, PurpleXfer *xfer)\n{\n\tstruct sipe_file_transfer *ft = PURPLE_XFER_TO_SIPE_FILE_TRANSFER;\n\tgssize bytes_written = 0;\n\n\tg_return_val_if_fail(ft->ft_write, 0);\n\n\tbytes_written = ft->ft_write(ft, buffer, size);\n\n\tif ((purple_xfer_get_bytes_remaining(xfer) - bytes_written) == 0)\n\t\tpurple_xfer_set_completed(xfer, TRUE);\n\n\treturn bytes_written;\n}\n\nstatic PurpleXfer *\ncreate_xfer(PurpleAccount *account, PurpleXferType type, const char *who,\n\t    struct sipe_file_transfer *ft)\n{\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tSipePurpleXfer *xfer = g_object_new(SIPE_TYPE_PURPLE_XFER,\n\t\t\t\t\t    \"account\", account,\n\t\t\t\t\t    \"type\", type,\n\t\t\t\t\t    \"remote-user\", who,\n\t\t\t\t\t    NULL);\n\txfer->ft = ft;\n\tft->backend_private = (struct sipe_backend_file_transfer *)xfer;\n\n\treturn PURPLE_XFER (xfer);\n#else\n\tPurpleXfer *xfer = purple_xfer_new(account, type, who);\n\tif (xfer) {\n\t\tft->backend_private = (struct sipe_backend_file_transfer *)xfer;\n\n\t\tpurple_xfer_set_protocol_data(xfer, ft);\n\t\tpurple_xfer_set_init_fnc(xfer, ft_init);\n\t\tpurple_xfer_set_request_denied_fnc(xfer, ft_request_denied);\n\t\tpurple_xfer_set_cancel_send_fnc(xfer, ft_cancelled);\n\t\tpurple_xfer_set_cancel_recv_fnc(xfer, ft_cancelled);\n\t\tpurple_xfer_set_start_fnc(xfer, ft_start);\n\t\tpurple_xfer_set_end_fnc(xfer, ft_end);\n\t}\n\n\treturn xfer;\n#endif\n}\n\nvoid sipe_backend_ft_incoming(struct sipe_core_public *sipe_public,\n\t\t\t      struct sipe_file_transfer *ft,\n\t\t\t      const gchar *who,\n\t\t\t      const gchar *file_name,\n\t\t\t      gsize file_size)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tPurpleXfer *xfer = create_xfer(purple_private->account,\n\t\t\t\t       PURPLE_XFER_TYPE_RECEIVE, who, ft);\n\tif (xfer) {\n\t\tpurple_xfer_set_filename(xfer, file_name);\n\t\tpurple_xfer_set_size(xfer, file_size);\n\n\t\tpurple_xfer_request(xfer);\n\t}\n}\n\nvoid\nsipe_backend_ft_outgoing(struct sipe_core_public *sipe_public,\n\t\t\t struct sipe_file_transfer *ft,\n\t\t\t const gchar *who,\n\t\t\t const gchar *file_name)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tPurpleXfer *xfer = create_xfer(purple_private->account,\n\t\t\t\t       PURPLE_XFER_TYPE_SEND, who, ft);\n\tif (xfer) {\n\t\tif (file_name != NULL)\n\t\t\tpurple_xfer_request_accepted(xfer, file_name);\n\t\telse\n\t\t\tpurple_xfer_request(xfer);\n\t}\n}\n\nstatic void\nconnect_cb(gpointer data, gint fd, SIPE_UNUSED_PARAMETER const gchar *error_message)\n{\n\tstruct sipe_file_transfer *ft = data;\n\n\tif (fd < 0) {\n\t\tpurple_xfer_cancel_local(FT_TO_PURPLE_XFER);\n\t\treturn;\n\t}\n\n\tpurple_xfer_start(FT_TO_PURPLE_XFER, fd, NULL, 0);\n}\n\nvoid\nsipe_backend_ft_start(struct sipe_file_transfer *ft, struct sipe_backend_fd *fd,\n\t\t      const char* ip, unsigned port)\n{\n#if !PURPLE_VERSION_CHECK(3,0,0)\n\tPurpleXferType type = purple_xfer_get_xfer_type(FT_TO_PURPLE_XFER);\n\tif (type == PURPLE_XFER_TYPE_SEND && ft->ft_write) {\n\t\tpurple_xfer_set_write_fnc(FT_TO_PURPLE_XFER, ft_write);\n\t} else if (type == PURPLE_XFER_TYPE_RECEIVE && ft->ft_read) {\n\t\tpurple_xfer_set_read_fnc(FT_TO_PURPLE_XFER, ft_read);\n\t}\n#endif\n\n\tif (ip && port && !sipe_backend_ft_is_incoming(ft)) {\n\t\t/* Purple accepts ip & port only for incoming file transfers.\n\t\t * If we want to send file with Sender-Connect = TRUE negotiated,\n\t\t * we have to open the connection ourselves and pass the file\n\t\t * descriptor to purple_xfer_start. */\n\t\tpurple_proxy_connect(NULL,\n\t\t\t\t     purple_xfer_get_account(FT_TO_PURPLE_XFER),\n\t\t\t\t     ip,\n\t\t\t\t     port,\n\t\t\t\t     connect_cb,\n\t\t\t\t     ft);\n\t\treturn;\n\t}\n\n\tpurple_xfer_start(FT_TO_PURPLE_XFER, fd ? fd->fd : -1, ip, port);\n}\n\nvoid sipe_purple_ft_send_file(\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t      SIPE_UNUSED_PARAMETER PurpleProtocolXfer *xfer,\n#endif\n\t\t\t      PurpleConnection *gc,\n\t\t\t      const char *who,\n\t\t\t      const char *file)\n{\n\tsipe_core_ft_create_outgoing(PURPLE_GC_TO_SIPE_CORE_PUBLIC, who, file);\n}\n\ngboolean\nsipe_backend_ft_is_incoming(struct sipe_file_transfer *ft)\n{\n\treturn(purple_xfer_get_xfer_type(FT_TO_PURPLE_XFER) == PURPLE_XFER_TYPE_RECEIVE);\n}\n\n#if PURPLE_VERSION_CHECK(3,0,0)\n\nG_DEFINE_DYNAMIC_TYPE(SipePurpleXfer, sipe_purple_xfer, PURPLE_TYPE_XFER);\n\nstatic void\nsipe_purple_xfer_init(SIPE_UNUSED_PARAMETER SipePurpleXfer *xfer)\n{}\n\nstatic gssize\nsipe_purple_xfer_read(PurpleXfer *xfer, guchar **buffer, gsize size)\n{\n\tstruct sipe_file_transfer *ft = PURPLE_XFER_TO_SIPE_FILE_TRANSFER;\n\n\tif (ft->ft_read) {\n\t\treturn ft_read(buffer, size, xfer);\n\t} else {\n\t\tPurpleXferClass *xfer_class;\n\n\t\txfer_class = PURPLE_XFER_CLASS(sipe_purple_xfer_parent_class);\n\t\treturn xfer_class->read(xfer, buffer, size);\n\t}\n}\n\nstatic gssize\nsipe_purple_xfer_write(PurpleXfer *xfer, const guchar *buffer, gsize size)\n{\n\tstruct sipe_file_transfer *ft = PURPLE_XFER_TO_SIPE_FILE_TRANSFER;\n\n\tif (ft->ft_write) {\n\t\treturn ft_write(buffer, size, xfer);\n\t} else {\n\t\tPurpleXferClass *xfer_class;\n\n\t\txfer_class = PURPLE_XFER_CLASS(sipe_purple_xfer_parent_class);\n\t\treturn xfer_class->write(xfer, buffer, size);\n\t}\n}\n\nstatic void\nsipe_purple_xfer_class_init(SipePurpleXferClass *klass)\n{\n\tPurpleXferClass *xfer_class = PURPLE_XFER_CLASS(klass);\n\n\txfer_class->init = ft_init;\n\txfer_class->request_denied = ft_request_denied;\n\txfer_class->start = ft_start;\n\txfer_class->end = ft_end;\n\txfer_class->cancel_send = ft_cancelled;\n\txfer_class->cancel_recv = ft_cancelled;\n\txfer_class->read = sipe_purple_xfer_read;\n\txfer_class->write = sipe_purple_xfer_write;\n}\n\nstatic void\nsipe_purple_xfer_class_finalize(SIPE_UNUSED_PARAMETER SipePurpleXferClass *klass)\n{}\n\nvoid\nsipe_purple_xfer_register(GTypeModule *module)\n{\n\tsipe_purple_xfer_register_type(module);\n}\n\n#endif\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-groupchat.c",
    "content": "/**\n * @file purple-groupchat.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n\n#include \"conversation.h\"\n#include \"roomlist.h\"\n\n#include \"version.h\"\n#if PURPLE_VERSION_CHECK(3,0,0)\n#include \"conversations.h\"\n#else\n#define purple_roomlist_get_account(r) r->account\n#endif\n\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-nls.h\"\n\n#include \"purple-private.h\"\n\nGList *sipe_purple_chat_info(SIPE_UNUSED_PARAMETER PurpleConnection *gc)\n{\n\tGList *m = NULL;\n\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tPurpleProtocolChatEntry *pce = g_new0(PurpleProtocolChatEntry, 1);\n#else\n\tstruct proto_chat_entry *pce = g_new0(struct proto_chat_entry, 1);\n#endif\n\tpce->label = _(\"_URI:\");\n\tpce->identifier = \"uri\";\n\tpce->required = TRUE;\n\tm = g_list_append(m, pce);\n\n\treturn m;\n}\n\n/**\n * This callback is called for two reasons:\n *\n *  a) generate the defaults for the \"Add chat...\" dialog initiated from the\n *     roomlist (applies only to group chat)\n *  b) generate the components for the creation of a PurpleChat object\n *\n */\nGHashTable *sipe_purple_chat_info_defaults(PurpleConnection *gc,\n\t\t\t\t\t   const char *chat_name)\n{\n\tGHashTable *defaults = g_hash_table_new(g_str_hash, g_str_equal);\n\n\tif (chat_name != NULL) {\n\t\tstruct sipe_core_public *sipe_public = PURPLE_GC_TO_SIPE_CORE_PUBLIC;\n\t\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\t\tGHashTable *uri_map = purple_private->roomlist_map;\n\t\tconst gchar *uri = uri_map != NULL ?\n\t\t\tg_hash_table_lookup(uri_map, chat_name) :\n\t\t\tNULL;\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\tPurpleChatConversation *conv = purple_conversations_find_chat_with_account(\n#else\n\t\tPurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,\n#endif\n\t\t\t\t\t\t\t\t\t\t chat_name,\n\t\t\t\t\t\t\t\t\t\t purple_private->account);\n\t\t/* Group Chat rooms have a valid URI */\n\t\tif (uri) {\n\t\t\tg_hash_table_insert(defaults, (char *)\"uri\", (gpointer)uri);\n\t\t}\n\n\t\t/**\n\t\t * Remember the PurpleConversation\n\t\t *\n\t\t * libpurple API is so brain-dead that we don't receive this\n\t\t * information when it is known and we need it. Make our life\n\t\t * easier by remembering it here for later lookup....\n\t\t */\n\t\tif (conv) {\n\t\t\tg_hash_table_insert(defaults,\n\t\t\t\t\t    (char *)SIPE_PURPLE_COMPONENT_KEY_CONVERSATION,\n\t\t\t\t\t    conv);\n\t\t}\n\t}\n\n\treturn defaults;\n}\n\nvoid sipe_purple_chat_join(PurpleConnection *gc, GHashTable *data)\n{\n\tstruct sipe_core_public *sipe_public = PURPLE_GC_TO_SIPE_CORE_PUBLIC;\n\tconst gchar *uri = g_hash_table_lookup(data, \"uri\");\n\n\tif (uri) {\n\t\tSIPE_DEBUG_INFO(\"sipe_purple_chat_join: uri '%s'\", uri);\n\t\tsipe_core_groupchat_join(sipe_public, uri);\n\t}\n}\n\nstatic void clear_roomlist(struct sipe_backend_private *purple_private)\n{\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tg_object_unref(purple_private->roomlist);\n#else\n\tpurple_roomlist_unref(purple_private->roomlist);\n#endif\n\tpurple_private->roomlist = NULL;\n}\n\nPurpleRoomlist *sipe_purple_roomlist_get_list(PurpleConnection *gc)\n{\n\tstruct sipe_core_public *sipe_public = PURPLE_GC_TO_SIPE_CORE_PUBLIC;\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tPurpleAccount *account = purple_private->account;\n\tPurpleRoomlist *roomlist;\n\tGList *fields = NULL;\n\tPurpleRoomlistField *f;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_purple_roomlist_get_list\");\n\n\tif (purple_private->roomlist)\n\t\tclear_roomlist(purple_private);\n\tif (purple_private->roomlist_map)\n\t\tg_hash_table_destroy(purple_private->roomlist_map);\n\n\tpurple_private->roomlist = roomlist = purple_roomlist_new(account);\n\tpurple_private->roomlist_map = g_hash_table_new_full(g_str_hash,\n\t\t\t\t\t\t\t     g_str_equal,\n\t\t\t\t\t\t\t     g_free, g_free);\n\n\t/* The order needs to be kept in-sync with sipe_backend_groupchat_room_add() */\n\tf = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING,\n\t\t\t\t      \"\", \"uri\", TRUE);\n\tfields = g_list_append(fields, f);\n\tf = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_INT,\n\t\t\t\t      _(\"Users\"), \"users\", FALSE);\n\tfields = g_list_append(fields, f);\n\tf = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_BOOL,\n\t\t\t\t      _(\"Invite\"), \"invite\", FALSE);\n\tfields = g_list_append(fields, f);\n\tf = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_BOOL,\n\t\t\t\t      _(\"Private\"), \"private\", FALSE);\n\tfields = g_list_append(fields, f);\n\tf = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_BOOL,\n\t\t\t\t      _(\"Log\"), \"logged\", FALSE);\n\tfields = g_list_append(fields, f);\n\tf = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING,\n\t\t\t\t      _(\"Description\"), \"description\", FALSE);\n\tfields = g_list_append(fields, f);\n\n\tpurple_roomlist_set_fields(roomlist, fields);\n\tpurple_roomlist_set_in_progress(roomlist, TRUE);\n\n\tif (!sipe_core_groupchat_query_rooms(sipe_public)) {\n\t\tsipe_purple_roomlist_cancel(roomlist);\n\t\troomlist = NULL;\n\t}\n\n\treturn roomlist;\n}\n\nvoid sipe_purple_roomlist_cancel(PurpleRoomlist *roomlist)\n{\n\tPurpleAccount *account = purple_roomlist_get_account(roomlist);\n\tstruct sipe_core_public *sipe_public = PURPLE_ACCOUNT_TO_SIPE_CORE_PUBLIC;\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_purple_roomlist_cancel\");\n\n\tpurple_roomlist_set_in_progress(roomlist, FALSE);\n\n\tif (purple_private->roomlist == roomlist)\n\t\tclear_roomlist(purple_private);\n}\n\nvoid sipe_backend_groupchat_room_add(struct sipe_core_public *sipe_public,\n\t\t\t\t     const gchar *uri,\n\t\t\t\t     const gchar *name,\n\t\t\t\t     const gchar *description,\n\t\t\t\t     guint users,\n\t\t\t\t     guint32 flags)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tPurpleRoomlist *roomlist = purple_private->roomlist;\n\tif (roomlist) {\n\t\tPurpleRoomlistRoom *room = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM,\n\t\t\t\t\t\t\t\t    name, NULL);\n\n\t\t/* The order needs to be kept in-sync with sipe_roomlist_get_list() */\n\t\tpurple_roomlist_room_add_field(roomlist, room,\n\t\t\t\t\t       uri);\n\t\tpurple_roomlist_room_add_field(roomlist, room,\n\t\t\t\t\t       GUINT_TO_POINTER(users));\n\t\tpurple_roomlist_room_add_field(roomlist, room,\n\t\t\t\t\t       GUINT_TO_POINTER(flags & SIPE_GROUPCHAT_ROOM_INVITE));\n\t\tpurple_roomlist_room_add_field(roomlist, room,\n\t\t\t\t\t       GUINT_TO_POINTER(flags & SIPE_GROUPCHAT_ROOM_PRIVATE));\n\t\tpurple_roomlist_room_add_field(roomlist, room,\n\t\t\t\t\t       GUINT_TO_POINTER(flags & SIPE_GROUPCHAT_ROOM_LOGGED));\n\t\tpurple_roomlist_room_add_field(roomlist, room,\n\t\t\t\t\t       description);\n\n\t\t/* libpurple API only gives us the channel name */\n\t\tg_hash_table_insert(purple_private->roomlist_map,\n\t\t\t\t    g_strdup(name), g_strdup(uri));\n\n\t\tpurple_roomlist_room_add(roomlist, room);\n\t}\n}\n\nvoid sipe_backend_groupchat_room_terminate(struct sipe_core_public *sipe_public)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tPurpleRoomlist *roomlist = purple_private->roomlist;\n\tif (roomlist) {\n\t\tpurple_roomlist_set_in_progress(roomlist, FALSE);\n\t\tclear_roomlist(purple_private);\n\t}\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-im.c",
    "content": "/**\n * @file purple-im.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2013 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <time.h>\n\n#include <glib.h>\n\n#include \"server.h\"\n\n#include \"version.h\"\n#if PURPLE_VERSION_CHECK(3,0,0)\n#include \"conversations.h\"\n#else\n#define purple_serv_got_im(c, w, m, f, t)\tserv_got_im(c, w, m, f, t)\n#endif\n\n#include \"purple-private.h\"\n\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-nls.h\"\n\nvoid sipe_backend_im_message(struct sipe_core_public *sipe_public,\n\t\t\t     const gchar *from,\n\t\t\t     const gchar *html)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tpurple_serv_got_im(purple_private->gc,\n\t\t    from,\n\t\t    html,\n\t\t    0,\n\t\t    time(NULL));\n}\n\nvoid sipe_backend_im_topic(struct sipe_core_public *sipe_public,\n\t\t\t   const gchar *with,\n\t\t\t   const gchar *topic)\n{\n\tPurpleAccount *account = sipe_public->backend_private->account;\n\tPurpleConversation *conv;\n\tgchar *msg;\n\n\t/*\n\t * Ensure we have an open conversation with the buddy, otherwise\n\t * message would be lost.\n\t */\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tconv = (PurpleConversation *) purple_conversations_find_im_with_account(\n#else\n\tconv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY,\n#endif\n\t\t\t\t\t\t     with,\n\t\t\t\t\t\t     account);\n\tif (!conv)\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\tconv = (PurpleConversation *) purple_im_conversation_new(\n#else\n\t\tconv = purple_conversation_new(PURPLE_CONV_TYPE_IM,\n#endif\n\t\t\t\t\t       account,\n\t\t\t\t\t       with);\n\n\tmsg = g_strdup_printf(_(\"Conversation subject: %s\"), topic);\n\tsipe_backend_notify_message_info(sipe_public,\n\t\t\t\t\t (struct sipe_backend_chat_session *)conv,\n\t\t\t\t\t with,\n\t\t\t\t\t msg);\n\tg_free(msg);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-markup.c",
    "content": "/**\n * @file purple-markup.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n\n#include \"util.h\"\n\n#include \"sipe-backend.h\"\n\ngchar *sipe_backend_markup_css_property(const gchar *style,\n\t\t\t\t\tconst gchar *option)\n{\n\treturn purple_markup_get_css_property(style, option);\n}\n\ngchar *sipe_backend_markup_strip_html(const gchar *html)\n{\n\treturn purple_markup_strip_html(html);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-media.c",
    "content": "/**\n * @file purple-media.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include \"glib.h\"\n#include \"glib/gstdio.h\"\n#include <fcntl.h>\n#include <string.h>\n#ifdef HAVE_UNISTD_H\n#include <unistd.h>\n#endif\n\n#include \"sipe-common.h\"\n\n#include \"mediamanager.h\"\n#include \"agent.h\"\n#include \"version.h\"\n\n#ifdef _WIN32\n/* wrappers for write() & friends for socket handling */\n#include \"win32/win32dep.h\"\n#endif\n\n#if PURPLE_VERSION_CHECK(3,0,0)\n/* nothing here yet */\n#else\n#define purple_config_dir purple_user_dir\n#endif\n\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n\n#include \"purple-private.h\"\n\n/*\n * GStreamer interfaces fail to compile on ARM architecture with -Wcast-align\n *\n * Diagnostic #pragma was added in GCC 4.2.0\n */\n#if defined(__GNUC__)\n#if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) || (__GNUC__ >= 5)\n#if defined(__ARMEL__) || defined(__ARMEB__) || defined(__hppa__) || defined(__mips__) || defined(__sparc__) || (defined(__powerpc__) && defined(__NO_FPRS__))\n#pragma GCC diagnostic ignored \"-Wcast-align\"\n#endif\n#endif\n#endif\n\n#include \"media-gst.h\"\n#include <gst/rtp/gstrtcpbuffer.h>\n#include <farstream/fs-session.h>\n\nstruct sipe_backend_media {\n\tPurpleMedia *m;\n\t/**\n\t * Number of media streams that were not yet locally accepted or rejected.\n\t */\n\tguint unconfirmed_streams;\n};\n\nstruct sipe_backend_media_stream {\n\tgboolean local_on_hold;\n\tgboolean remote_on_hold;\n\tgboolean accepted;\n\tgboolean initialized_cb_was_fired;\n\n\tgulong gst_bus_cb_id;\n\n\tGObject *rtpsession;\n\tgulong on_sending_rtcp_cb_id;\n};\n\nvoid\nsipe_backend_media_stream_free(struct sipe_backend_media_stream *stream)\n{\n\tif (stream->gst_bus_cb_id != 0) {\n\t\tGstElement *pipe;\n\n\t\tpipe = purple_media_manager_get_pipeline(\n\t\t\t\tpurple_media_manager_get());\n\t\tif (pipe) {\n\t\t\tGstBus *bus;\n\n\t\t\tbus = gst_element_get_bus(pipe);\n\t\t\tg_signal_handler_disconnect(bus, stream->gst_bus_cb_id);\n\t\t\tstream->gst_bus_cb_id = 0;\n\t\t\tgst_object_unref(bus);\n\t\t}\n\t}\n\n\tif (stream->rtpsession) {\n\t\tg_clear_object(&stream->rtpsession);\n\t}\n\n\tg_free(stream);\n}\n\nstatic PurpleMediaSessionType sipe_media_to_purple(SipeMediaType type);\nstatic PurpleMediaCandidateType sipe_candidate_type_to_purple(SipeCandidateType type);\nstatic SipeCandidateType purple_candidate_type_to_sipe(PurpleMediaCandidateType type);\nstatic PurpleMediaNetworkProtocol sipe_network_protocol_to_purple(SipeNetworkProtocol proto);\nstatic SipeNetworkProtocol purple_network_protocol_to_sipe(PurpleMediaNetworkProtocol proto);\n\nstatic void\nmaybe_signal_stream_initialized(struct sipe_media_call *call, gchar *sessionid)\n{\n\tif (call->stream_initialized_cb) {\n\t\tstruct sipe_media_stream *stream;\n\t\tstream = sipe_core_media_get_stream_by_id(call, sessionid);\n\n\t\tif (stream &&\n\t\t    sipe_backend_stream_initialized(call, stream) &&\n\t\t    !stream->backend_private->initialized_cb_was_fired) {\n\t\t\tstream->backend_private->initialized_cb_was_fired = TRUE;\n\t\t\tcall->stream_initialized_cb(call, stream);\n\t\t}\n\t}\n}\n\nstatic void\non_candidates_prepared_cb(SIPE_UNUSED_PARAMETER PurpleMedia *media,\n\t\t\t  gchar *sessionid,\n\t\t\t  SIPE_UNUSED_PARAMETER gchar *participant,\n\t\t\t  struct sipe_media_call *call)\n{\n\tmaybe_signal_stream_initialized(call, sessionid);\n}\n\nstatic void\non_codecs_changed_cb(SIPE_UNUSED_PARAMETER PurpleMedia *media,\n\t\t    gchar *sessionid,\n\t\t    struct sipe_media_call *call)\n{\n\tmaybe_signal_stream_initialized(call, sessionid);\n}\n\nstatic void\non_state_changed_cb(SIPE_UNUSED_PARAMETER PurpleMedia *media,\n\t\t    PurpleMediaState state,\n\t\t    gchar *sessionid,\n\t\t    gchar *participant,\n\t\t    struct sipe_media_call *call)\n{\n\tSIPE_DEBUG_INFO(\"sipe_media_state_changed_cb: %d %s %s\\n\", state, sessionid, participant);\n\n\tif (state == PURPLE_MEDIA_STATE_CONNECTED && sessionid && participant) {\n\t\tstruct sipe_media_stream *stream;\n\n\t\tstream = sipe_core_media_get_stream_by_id(call, sessionid);\n\t\tif (stream && stream->backend_private->rtpsession &&\n\t\t    stream->backend_private->on_sending_rtcp_cb_id != 0) {\n\t\t\tstruct sipe_backend_media_stream *backend_stream;\n\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"Peer started sending. Ceasing\"\n\t\t\t\t\t\" video source requests.\");\n\n\t\t\tbackend_stream = stream->backend_private;\n\n\t\t\tg_signal_handler_disconnect(backend_stream->rtpsession,\n\t\t\t\t\tbackend_stream->on_sending_rtcp_cb_id);\n\t\t\tg_clear_object(&backend_stream->rtpsession);\n\t\t\tbackend_stream->on_sending_rtcp_cb_id = 0;\n\t\t}\n\t} else if (state == PURPLE_MEDIA_STATE_END) {\n\t\tif (sessionid && participant) {\n\t\t\tstruct sipe_media_stream *stream =\n\t\t\t\t\tsipe_core_media_get_stream_by_id(call, sessionid);\n\t\t\tif (stream) {\n\t\t\t\tsipe_core_media_stream_end(stream);\n\t\t\t}\n\t\t} else if (!sessionid && !participant && call->media_end_cb) {\n\t\t\tcall->media_end_cb(call);\n\t\t}\n\t}\n}\n\nvoid\ncapture_pipeline(const gchar *label) {\n\tPurpleMediaManager *manager = purple_media_manager_get();\n\tGstElement *pipeline = purple_media_manager_get_pipeline(manager);\n\tGST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, label);\n}\n\nstatic void\non_error_cb(SIPE_UNUSED_PARAMETER PurpleMedia *media, gchar *message,\n\t    struct sipe_media_call *call)\n{\n\tcapture_pipeline(\"ERROR\");\n\n\tif (call->error_cb)\n\t\tcall->error_cb(call, message);\n}\n\nstatic void\non_stream_info_cb(PurpleMedia *media,\n\t\t  PurpleMediaInfoType type,\n\t\t  gchar *sessionid,\n\t\t  gchar *participant,\n\t\t  gboolean local,\n\t\t  struct sipe_media_call *call)\n{\n\tif (type == PURPLE_MEDIA_INFO_ACCEPT) {\n\t\tif (call->call_accept_cb && !sessionid && !participant)\n\t\t\tcall->call_accept_cb(call, local);\n\t\telse if (sessionid && participant) {\n\t\t\tstruct sipe_media_stream *stream;\n\t\t\tstream = sipe_core_media_get_stream_by_id(call, sessionid);\n\t\t\tif (stream) {\n\t\t\t\tif (!stream->backend_private->accepted && local)\n\t\t\t\t\t --call->backend_private->unconfirmed_streams;\n\t\t\t\tstream->backend_private->accepted = TRUE;\n\t\t\t}\n\t\t}\n\t} else if (type == PURPLE_MEDIA_INFO_HOLD || type == PURPLE_MEDIA_INFO_UNHOLD) {\n\n\t\tgboolean state = (type == PURPLE_MEDIA_INFO_HOLD);\n\n\t\tif (sessionid) {\n\t\t\t// Hold specific stream\n\t\t\tstruct sipe_media_stream *stream;\n\t\t\tstream = sipe_core_media_get_stream_by_id(call, sessionid);\n\n\t\t\tif (stream) {\n\t\t\t\tif (local)\n\t\t\t\t\tstream->backend_private->local_on_hold = state;\n\t\t\t\telse\n\t\t\t\t\tstream->backend_private->remote_on_hold = state;\n\t\t\t}\n\t\t} else {\n\t\t\t// Hold all streams\n\t\t\tGList *session_ids = purple_media_get_session_ids(media);\n\n\t\t\tfor (; session_ids; session_ids = session_ids->next) {\n\t\t\t\tstruct sipe_media_stream *stream =\n\t\t\t\t\t\tsipe_core_media_get_stream_by_id(call, session_ids->data);\n\n\t\t\t\tif (stream) {\n\t\t\t\t\tif (local)\n\t\t\t\t\t\tstream->backend_private->local_on_hold = state;\n\t\t\t\t\telse\n\t\t\t\t\t\tstream->backend_private->remote_on_hold = state;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tg_list_free(session_ids);\n\t\t}\n\n\t\tif (call->call_hold_cb)\n\t\t\tcall->call_hold_cb(call, local, state);\n\t} else if (type == PURPLE_MEDIA_INFO_HANGUP || type == PURPLE_MEDIA_INFO_REJECT) {\n\t\tif (!sessionid && !participant) {\n\t\t\tif (type == PURPLE_MEDIA_INFO_HANGUP && call->call_hangup_cb)\n\t\t\t\tcall->call_hangup_cb(call, local);\n\t\t\telse if (type == PURPLE_MEDIA_INFO_REJECT && call->call_reject_cb && !local)\n\t\t\t\tcall->call_reject_cb(call, local);\n\t\t} else if (sessionid && participant) {\n\t\t\tstruct sipe_media_stream *stream;\n\t\t\tstream = sipe_core_media_get_stream_by_id(call, sessionid);\n\n#ifdef HAVE_XDATA\n\t\t\tpurple_media_manager_set_application_data_callbacks(\n\t\t\t\t\tpurple_media_manager_get(), media,\n\t\t\t\t\tsessionid, participant, NULL, NULL, NULL);\n#endif\n\n\t\t\tif (stream) {\n\t\t\t\tif (local && --call->backend_private->unconfirmed_streams == 0 &&\n\t\t\t\t    call->call_reject_cb)\n\t\t\t\t\tcall->call_reject_cb(call, local);\n\t\t\t}\n\t\t}\n\t} else if (type == PURPLE_MEDIA_INFO_MUTE || type == PURPLE_MEDIA_INFO_UNMUTE) {\n\t\tstruct sipe_media_stream *stream =\n\t\t\t\tsipe_core_media_get_stream_by_id(call, \"audio\");\n\n\t\tif (stream && stream->mute_cb) {\n\t\t\tstream->mute_cb(stream, type == PURPLE_MEDIA_INFO_MUTE);\n\t\t}\n\t}\n}\n\nstatic void\non_candidate_pair_established_cb(SIPE_UNUSED_PARAMETER PurpleMedia *media,\n\t\t\t\t const gchar *sessionid,\n\t\t\t\t SIPE_UNUSED_PARAMETER const gchar *participant,\n\t\t\t\t SIPE_UNUSED_PARAMETER PurpleMediaCandidate *local_candidate,\n\t\t\t\t SIPE_UNUSED_PARAMETER PurpleMediaCandidate *remote_candidate,\n\t\t\t\t struct sipe_media_call *call)\n{\n\tstruct sipe_media_stream *stream =\n\t\t\tsipe_core_media_get_stream_by_id(call, sessionid);\n\n\tif (!stream) {\n\t\treturn;\n\t}\n\n#ifdef HAVE_PURPLE_NEW_TCP_ENUMS\n\tif (purple_media_candidate_get_protocol(local_candidate) != PURPLE_MEDIA_NETWORK_PROTOCOL_UDP) {\n\t\tpurple_media_set_send_rtcp_mux(media, sessionid, participant, TRUE);\n\t}\n#endif\n\n\tsipe_core_media_stream_candidate_pair_established(stream);\n}\n\nstruct sipe_backend_media *\nsipe_backend_media_new(struct sipe_core_public *sipe_public,\n\t\t       struct sipe_media_call *call,\n\t\t       const gchar *participant,\n\t\t       SipeMediaCallFlags flags)\n{\n\tstruct sipe_backend_media *media = g_new0(struct sipe_backend_media, 1);\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tPurpleMediaManager *manager = purple_media_manager_get();\n\tGstElement *pipeline;\n\n\tif (flags & SIPE_MEDIA_CALL_NO_UI) {\n#ifdef HAVE_XDATA\n\t\tmedia->m = purple_media_manager_create_private_media(manager,\n\t\t\t\tpurple_private->account, \"fsrtpconference\",\n\t\t\t\tparticipant, flags & SIPE_MEDIA_CALL_INITIATOR);\n#else\n\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"Purple doesn't support private media\");\n#endif\n\t} else {\n\t\tmedia->m = purple_media_manager_create_media(manager,\n\t\t\t\tpurple_private->account, \"fsrtpconference\",\n\t\t\t\tparticipant, flags & SIPE_MEDIA_CALL_INITIATOR);\n\t}\n\n\tg_signal_connect(G_OBJECT(media->m), \"candidates-prepared\",\n\t\t\t G_CALLBACK(on_candidates_prepared_cb), call);\n\tg_signal_connect(G_OBJECT(media->m), \"codecs-changed\",\n\t\t\t G_CALLBACK(on_codecs_changed_cb), call);\n\tg_signal_connect(G_OBJECT(media->m), \"stream-info\",\n\t\t\t G_CALLBACK(on_stream_info_cb), call);\n\tg_signal_connect(G_OBJECT(media->m), \"error\",\n\t\t\t G_CALLBACK(on_error_cb), call);\n\tg_signal_connect(G_OBJECT(media->m), \"state-changed\",\n\t\t\t G_CALLBACK(on_state_changed_cb), call);\n\tg_signal_connect(G_OBJECT(media->m), \"candidate-pair-established\",\n\t\t\t G_CALLBACK(on_candidate_pair_established_cb), call);\n\n\n\t/* On error, the pipeline is no longer in PLAYING state and libpurple\n\t * will not switch it back to PLAYING, preventing any more calls until\n\t * application restart. We switch the state ourselves here to negate\n\t * effect of any error in previous call (if any). */\n\tpipeline = purple_media_manager_get_pipeline(manager);\n\tgst_element_set_state(pipeline, GST_STATE_PLAYING);\n\n\treturn media;\n}\n\nvoid\nsipe_backend_media_free(struct sipe_backend_media *media)\n{\n\tg_free(media);\n}\n\nvoid\nsipe_backend_media_set_cname(struct sipe_backend_media *media, gchar *cname)\n{\n\tif (media) {\n\t\tguint num_params = 3;\n\t\tGParameter *params = g_new0(GParameter, num_params);\n\t\tparams[0].name = \"sdes-cname\";\n\t\tg_value_init(&params[0].value, G_TYPE_STRING);\n\t\tg_value_set_string(&params[0].value, cname);\n\t\tparams[1].name = \"sdes-name\";\n\t\tg_value_init(&params[1].value, G_TYPE_STRING);\n\t\tparams[2].name = \"sdes-tool\";\n\t\tg_value_init(&params[2].value, G_TYPE_STRING);\n\n\t\tpurple_media_set_params(media->m, num_params, params);\n\n\t\tg_value_unset(&params[0].value);\n\t\tg_free(params);\n\t}\n}\n\n#define FS_CODECS_CONF \\\n\t\"# Automatically created by SIPE plugin\\n\" \\\n\t\"[video/H264]\\n\" \\\n\t\"farstream-send-profile=videoscale ! videoconvert ! fsvideoanyrate ! x264enc ! video/x-h264,profile=constrained-baseline ! rtph264pay\\n\" \\\n\t\"\\n\" \\\n\t\"[application/X-DATA]\\n\" \\\n\t\"id=127\\n\"\n\nstatic void\nensure_codecs_conf()\n{\n\tgchar *filename;\n\tconst gchar *fs_codecs_conf = FS_CODECS_CONF;\n\tGError *error = NULL;\n\n\tfilename = g_build_filename(purple_config_dir(), \"fs-codec.conf\", NULL);\n\n\tg_file_set_contents(filename, fs_codecs_conf, strlen(fs_codecs_conf),\n\t\t\t    &error);\n\tif (error) {\n\t\tSIPE_DEBUG_ERROR(\"Couldn't create fs-codec.conf: %s\",\n\t\t\t\t error->message);\n\t\tg_error_free(error);\n\t}\n\n\tg_free(filename);\n}\n\nstatic void\nappend_relay(struct sipe_backend_media_relays *relay_info, const gchar *ip,\n\t     guint port, const gchar *type, gchar *username, gchar *password)\n{\n\tGstStructure *gst_relay_info;\n\n\tgst_relay_info = gst_structure_new(\"relay-info\",\n\t\t\t\"ip\", G_TYPE_STRING, ip,\n\t\t\t\"port\", G_TYPE_UINT, port,\n\t\t\t\"relay-type\", G_TYPE_STRING, type,\n\t\t\t\"username\", G_TYPE_STRING, username,\n\t\t\t\"password\", G_TYPE_STRING, password,\n\t\t\tNULL);\n\n\tif (gst_relay_info) {\n\t\tg_ptr_array_add((GPtrArray *)relay_info, gst_relay_info);\n\t}\n}\n\nstruct sipe_backend_media_relays *\nsipe_backend_media_relays_convert(GSList *media_relays, gchar *username, gchar *password)\n{\n\tstruct sipe_backend_media_relays *relay_info;\n\n\trelay_info = (struct sipe_backend_media_relays *)\n\t\t\tg_ptr_array_new_with_free_func((GDestroyNotify) gst_structure_free);\n\n\tfor (; media_relays; media_relays = media_relays->next) {\\\n\t\tstruct sipe_media_relay *relay = media_relays->data;\n\n\t\t/* Skip relays where IP could not be resolved. */\n\t\tif (!relay->hostname)\n\t\t\tcontinue;\n\n\t\tif (relay->udp_port != 0)\n\t\t\tappend_relay(relay_info, relay->hostname, relay->udp_port,\n\t\t\t\t     \"udp\", username, password);\n\n#ifdef HAVE_PURPLE_NEW_TCP_ENUMS\n\t\tif (relay->tcp_port != 0) {\n\t\t\tconst gchar *type = \"tcp\";\n\t\t\tif (relay->tcp_port == 443)\n\t\t\t\ttype = \"tls\";\n\t\t\tappend_relay(relay_info, relay->hostname, relay->tcp_port,\n\t\t\t\t     type, username, password);\n\t\t}\n#endif\n\t}\n\n\treturn relay_info;\n}\n\nvoid\nsipe_backend_media_relays_free(struct sipe_backend_media_relays *media_relays)\n{\n\tg_ptr_array_unref((GPtrArray *)media_relays);\n}\n\n#ifdef HAVE_XDATA\nstatic void\nstream_readable_cb(SIPE_UNUSED_PARAMETER PurpleMediaManager *manager,\n\t\t SIPE_UNUSED_PARAMETER PurpleMedia *media,\n\t\t const gchar *session_id,\n\t\t SIPE_UNUSED_PARAMETER const gchar *participant,\n\t\t gpointer user_data)\n{\n\tstruct sipe_media_call *call = (struct sipe_media_call *)user_data;\n\tstruct sipe_media_stream *stream;\n\n\tSIPE_DEBUG_INFO(\"stream_readable_cb: %s is readable\", session_id);\n\n\tstream = sipe_core_media_get_stream_by_id(call, session_id);\n\n\tif (stream) {\n\t\tsipe_core_media_stream_readable(stream);\n\t}\n}\n\ngssize\nsipe_backend_media_stream_read(struct sipe_media_stream *stream,\n\t\t\t       guint8 *buffer, gsize len)\n{\n\treturn purple_media_manager_receive_application_data(\n\t\t\tpurple_media_manager_get(),\n\t\t\tstream->call->backend_private->m,\n\t\t\tstream->id, stream->call->with, buffer, len, FALSE);\n}\n\ngssize\nsipe_backend_media_stream_write(struct sipe_media_stream *stream,\n\t\t\t\tguint8 *buffer, gsize len)\n{\n\treturn purple_media_manager_send_application_data(\n\t\t\tpurple_media_manager_get(),\n\t\t\tstream->call->backend_private->m,\n\t\t\tstream->id, stream->call->with, buffer, len, FALSE);\n}\n\nstatic void\nstream_writable_cb(SIPE_UNUSED_PARAMETER PurpleMediaManager *manager,\n\t\t   SIPE_UNUSED_PARAMETER PurpleMedia *media,\n\t\t   const gchar *session_id,\n\t\t   SIPE_UNUSED_PARAMETER const gchar *participant,\n\t\t   gboolean writable,\n\t\t   gpointer user_data)\n{\n\tstruct sipe_media_call *call = (struct sipe_media_call *)user_data;\n\tstruct sipe_media_stream *stream;\n\n\tstream = sipe_core_media_get_stream_by_id(call, session_id);\n\n\tif (!stream) {\n\t\tSIPE_DEBUG_ERROR(\"stream_writable_cb: stream %s not found!\",\n\t\t\t\t session_id);\n\t\treturn;\n\t}\n\n\tSIPE_DEBUG_INFO(\"stream_writable_cb: %s has become %swritable\",\n\t\t\tsession_id, writable ? \"\" : \"not \");\n\n\tsipe_core_media_stream_writable(stream, writable);\n}\n#endif\n\nstatic gboolean\nwrite_ms_h264_video_source_request(GstRTCPBuffer *buffer, guint32 ssrc,\n                                   guint8 payload_type, guint32 media_source_id)\n{\n\tGstRTCPPacket packet;\n\tguint8 *fci_data;\n\n\tif (!gst_rtcp_buffer_add_packet(buffer, GST_RTCP_TYPE_PSFB, &packet)) {\n\t\treturn FALSE;\n\t}\n\n\tgst_rtcp_packet_fb_set_type(&packet, GST_RTCP_PSFB_TYPE_AFB);\n\tgst_rtcp_packet_fb_set_sender_ssrc(&packet, ssrc);\n\tgst_rtcp_packet_fb_set_media_ssrc(&packet, media_source_id);\n\n\tif (!gst_rtcp_packet_fb_set_fci_length(&packet,\n\t\t\t\t\t       SIPE_MSRTP_VSR_FCI_WORDLEN)) {\n\t\tgst_rtcp_packet_remove(&packet);\n\t\treturn FALSE;\n\t}\n\n\tfci_data = gst_rtcp_packet_fb_get_fci(&packet);\n\n\tsipe_core_msrtp_write_video_source_request(fci_data, payload_type,\n\t\t\t\t\t\t   media_source_id);\n\n\treturn TRUE;\n}\n\nstatic gboolean\non_sending_rtcp_cb(SIPE_UNUSED_PARAMETER GObject *rtpsession,\n\t\t   GstBuffer *buffer,\n\t\t   SIPE_UNUSED_PARAMETER gboolean is_early,\n\t\t   FsSession *fssession)\n{\n\tgboolean was_changed = FALSE;\n\tFsCodec *send_codec;\n\n\tg_object_get(fssession, \"current-send-codec\", &send_codec, NULL);\n\tif (!send_codec) {\n\t\treturn FALSE;\n\t}\n\n\tif (sipe_strequal(send_codec->encoding_name, \"H264\")) {\n\t\tGstRTCPBuffer rtcp_buffer = GST_RTCP_BUFFER_INIT;\n\t\tguint32 ssrc;\n\t\tstruct sipe_media_stream *stream;\n\n\t\tg_object_get(fssession, \"ssrc\", &ssrc, NULL);\n\t\tstream = g_object_get_data(G_OBJECT(fssession), \"sipe-media-stream\");\n\n\t\tgst_rtcp_buffer_map(buffer, GST_MAP_READWRITE, &rtcp_buffer);\n\t\twas_changed = write_ms_h264_video_source_request(&rtcp_buffer,\n\t\t\t\tssrc, send_codec->id, stream->media_source_id);\n\t\tgst_rtcp_buffer_unmap(&rtcp_buffer);\n\t}\n\n\tfs_codec_destroy(send_codec);\n\n\treturn was_changed;\n}\n\nstatic GstPadProbeReturn\nh264_buffer_cb(SIPE_UNUSED_PARAMETER GstPad *pad, GstPadProbeInfo *info,\n\t       SIPE_UNUSED_PARAMETER gpointer user_data)\n{\n\tGstBuffer *buffer;\n\tGstMemory *memory;\n\tGstMapInfo map;\n\tguint8 *data;\n\tguint8 nal_count = 0;\n\tgsize pacsi_len;\n\n\tbuffer = gst_pad_probe_info_get_buffer(info);\n\n\t// Count NALs in the buffer\n\tgst_buffer_map(buffer, &map, GST_MAP_READ);\n\n\tdata = map.data;\n\twhile (data < map.data + map.size) {\n\t\tguint32 size = GST_READ_UINT32_BE(data);\n\t\tdata += GST_READ_UINT32_BE(data) + sizeof (size);\n\t\t++nal_count;\n\t}\n\n\tgst_buffer_unmap(buffer, &map);\n\n\t// Write PACSI (RFC6190 section 4.9)\n\tmemory = gst_allocator_alloc(NULL, 100, NULL);\n\tgst_memory_map(memory, &map, GST_MAP_WRITE);\n\tpacsi_len = sipe_core_msrtp_write_video_scalability_info(map.data,\n\t\t\t\t\t\t\t\t nal_count);\n\tgst_memory_unmap(memory, &map);\n\tgst_memory_resize(memory, 0, pacsi_len);\n\n\tbuffer = gst_buffer_make_writable(buffer);\n\tgst_buffer_insert_memory(buffer, 0, memory);\n\tGST_PAD_PROBE_INFO_DATA(info) = buffer;\n\n\treturn GST_PAD_PROBE_OK;\n}\n\nstatic gint\nfind_payloader(GValue *value, GstCaps *rtpcaps)\n{\n\tgint result = 1;\n\tGstElement *element;\n\tGstPad *sinkpad;\n\tGstCaps *caps;\n\n\telement = g_value_get_object(value);\n\tsinkpad = gst_element_get_static_pad(element, \"sink\");\n\tcaps = gst_pad_query_caps(sinkpad, NULL);\n\n\t/* Elements are iterated from the most downstream. We're looking for the\n\t * first that does NOT consume RTP frames. */\n\tresult = gst_caps_can_intersect(caps, rtpcaps);\n\n\tgst_caps_unref(caps);\n\tgst_object_unref(sinkpad);\n\n\treturn result;\n}\n\nstatic void\ncurrent_send_codec_changed_cb(FsSession *fssession,\n\t\t\t      SIPE_UNUSED_PARAMETER GParamSpec *pspec,\n\t\t\t      GstBin *fsconference)\n{\n\tFsCodec *send_codec;\n\n\tg_object_get(fssession, \"current-send-codec\", &send_codec, NULL);\n\n\tif (sipe_strequal(send_codec->encoding_name, \"H264\")) {\n\t\tguint session_id;\n\t\tgchar *sendbin_name;\n\t\tGstBin *sendbin;\n\t\tGstCaps *caps;\n\t\tGstIterator *it;\n\t\tGValue val = G_VALUE_INIT;\n\n\t\tg_object_get(fssession, \"id\", &session_id, NULL);\n\n\t\tsendbin_name = g_strdup_printf(\"send_%u_%u\", session_id,\n\t\t\t\t\t       send_codec->id);\n\n\t\tsendbin = GST_BIN(gst_bin_get_by_name(fsconference,\n\t\t\t\t\t\t      sendbin_name));\n\t\tg_free(sendbin_name);\n\n\t\tif (!sendbin) {\n\t\t\tSIPE_DEBUG_ERROR(\"Couldn't find Farstream send bin for \"\n\t\t\t\t\t \"session %d\", session_id);\n\t\t\treturn;\n\t\t}\n\n\t\tcaps = gst_caps_new_empty_simple(\"application/x-rtp\");\n\t\tit = gst_bin_iterate_sorted(sendbin);\n\t\tif (gst_iterator_find_custom(it, (GCompareFunc)find_payloader,\n\t\t\t\t\t     &val, caps)) {\n\t\t\tGstElement *payloader;\n\t\t\tGstPad *sinkpad;\n\n\t\t\tpayloader = g_value_get_object(&val);\n\t\t\tsinkpad = gst_element_get_static_pad(payloader, \"sink\");\n\t\t\tif (sinkpad) {\n\t\t\t\tgst_pad_add_probe(sinkpad,\n\t\t\t\t\t\t  GST_PAD_PROBE_TYPE_BUFFER,\n\t\t\t\t\t\t  h264_buffer_cb, NULL, NULL);\n\t\t\t\tgst_object_unref(sinkpad);\n\t\t\t}\n\t\t\tg_value_unset(&val);\n\t\t}\n\t\tgst_caps_unref(caps);\n\n\t\tgst_iterator_free(it);\n\t\tgst_object_unref(sendbin);\n\t}\n\n\tfs_codec_destroy(send_codec);\n}\n\nstatic gint\nfind_sinkpad(GValue *value, GstPad *fssession_sinkpad)\n{\n\tGstElement *tee_srcpad = g_value_get_object(value);\n\n\treturn !(GST_PAD_PEER(tee_srcpad) == fssession_sinkpad);\n}\n\nstatic void\ngst_bus_cb(GstBus *bus, GstMessage *msg, struct sipe_media_stream *stream)\n{\n\tPurpleMedia *m;\n\tconst GstStructure *s;\n\tFsSession *fssession;\n\tGstElement *tee;\n\tGstPad *sinkpad;\n\tGstIterator *it;\n\tGValue val = G_VALUE_INIT;\n\n\tif (GST_MESSAGE_TYPE(msg) != GST_MESSAGE_ELEMENT) {\n\t\treturn;\n\t}\n\n\tm = stream->call->backend_private->m;\n\n\ts = gst_message_get_structure(msg);\n\tif (!gst_structure_has_name(s, \"farstream-codecs-changed\")) {\n\t\treturn;\n\t}\n\n\tfssession = g_value_get_object(gst_structure_get_value(s, \"session\"));\n\tg_return_if_fail(fssession);\n\n\ttee = purple_media_get_tee(m, stream->id, NULL);\n\tg_return_if_fail(tee);\n\n\tg_object_get(fssession, \"sink-pad\", &sinkpad, NULL);\n\tg_return_if_fail(sinkpad);\n\n\t/* Check whether this message is from the FsSession we're waiting for.\n\t * For this to be true, the tee we got from libpurple has to be linked\n\t * to \"sink-pad\" of the message's FsSession. */\n\tit = gst_element_iterate_src_pads(tee);\n\tif (gst_iterator_find_custom(it, (GCompareFunc)find_sinkpad, &val,\n\t\t\t\t     sinkpad)) {\n\t\tFsMediaType media_type;\n\n\t\tif (stream->ssrc_range) {\n\t\t\tg_object_set(fssession, \"ssrc\",\n\t\t\t\t     stream->ssrc_range->begin, NULL);\n\t\t}\n\n\t\tg_object_set_data(G_OBJECT(fssession),\n\t\t\t\t  \"sipe-media-stream\",\n\t\t\t\t  stream);\n\n\t\tg_object_get(fssession, \"media-type\", &media_type, NULL);\n\n\t\tif (media_type == FS_MEDIA_TYPE_VIDEO) {\n\t\t\tGObject *rtpsession;\n\t\t\tGstBin *fsconference;\n\n\t\t\tg_object_get(fssession,\n\t\t\t\t     \"internal-session\", &rtpsession, NULL);\n\t\t\tif (rtpsession) {\n\t\t\t\tstream->backend_private->rtpsession =\n\t\t\t\t\tgst_object_ref(rtpsession);\n\t\t\t\tstream->backend_private->on_sending_rtcp_cb_id =\n\t\t\t\t\tg_signal_connect(rtpsession,\n\t\t\t\t\t\t\"on-sending-rtcp\",\n\t\t\t\t\t\tG_CALLBACK(on_sending_rtcp_cb),\n\t\t\t\t\t\tfssession);\n\n\t\t\t\tg_object_unref (rtpsession);\n\t\t\t}\n\n\t\t\tg_object_get(fssession,\n\t\t\t\t     \"conference\", &fsconference, NULL);\n\n\t\t\tg_signal_connect_object(fssession,\n\t\t\t\t\"notify::current-send-codec\",\n\t\t\t\tG_CALLBACK(current_send_codec_changed_cb),\n\t\t\t\tfsconference, 0);\n\t\t\tgst_object_unref(fsconference);\n\t\t}\n\n\t\tg_signal_handler_disconnect(bus,\n\t\t\t\tstream->backend_private->gst_bus_cb_id);\n\t\tstream->backend_private->gst_bus_cb_id = 0;\n\t\tg_value_unset (&val);\n\t}\n\n\tgst_iterator_free(it);\n\tgst_object_unref(sinkpad);\n}\n\nstruct sipe_backend_media_stream *\nsipe_backend_media_add_stream(struct sipe_media_stream *stream,\n\t\t\t      SipeMediaType type,\n\t\t\t      SipeIceVersion ice_version,\n\t\t\t      gboolean initiator,\n\t\t\t      struct sipe_backend_media_relays *media_relays,\n\t\t\t      guint min_port, guint max_port)\n{\n\tstruct sipe_backend_media *media = stream->call->backend_private;\n\tstruct sipe_backend_media_stream *backend_stream = NULL;\n\tGstElement *pipe;\n\t// Preallocate enough space for all potential parameters to fit.\n\tGParameter *params = g_new0(GParameter, 7);\n\tguint params_cnt = 0;\n\tconst gchar *transmitter;\n#ifdef HAVE_XDATA\n\tPurpleMediaAppDataCallbacks callbacks = {\n\t\t\tstream_readable_cb, stream_writable_cb\n\t};\n#endif\n\n\tif (ice_version != SIPE_ICE_NO_ICE) {\n\t\ttransmitter = \"nice\";\n\n\t\tparams[params_cnt].name = \"compatibility-mode\";\n\t\tg_value_init(&params[params_cnt].value, G_TYPE_UINT);\n\t\tg_value_set_uint(&params[params_cnt].value,\n\t\t\t\t ice_version == SIPE_ICE_DRAFT_6 ?\n\t\t\t\t NICE_COMPATIBILITY_OC2007 :\n\t\t\t\t NICE_COMPATIBILITY_OC2007R2);\n\t\t++params_cnt;\n\n\t\tif (min_port != 0) {\n\t\t\tparams[params_cnt].name = \"min-port\";\n\t\t\tg_value_init(&params[params_cnt].value, G_TYPE_UINT);\n\t\t\tg_value_set_uint(&params[params_cnt].value, min_port);\n\t\t\t++params_cnt;\n\t\t}\n\n\t\tif (max_port != 0) {\n\t\t\tparams[params_cnt].name = \"max-port\";\n\t\t\tg_value_init(&params[params_cnt].value, G_TYPE_UINT);\n\t\t\tg_value_set_uint(&params[params_cnt].value, max_port);\n\t\t\t++params_cnt;\n\t\t}\n\n\t\tif (media_relays) {\n\t\t\tparams[params_cnt].name = \"relay-info\";\n\t\t\tg_value_init(&params[params_cnt].value, G_TYPE_PTR_ARRAY);\n\t\t\tg_value_set_boxed(&params[params_cnt].value, media_relays);\n\t\t\t++params_cnt;\n\t\t}\n\n\t\tif (type == SIPE_MEDIA_APPLICATION) {\n\t\t\tparams[params_cnt].name = \"ice-udp\";\n\t\t\tg_value_init(&params[params_cnt].value, G_TYPE_BOOLEAN);\n\t\t\tg_value_set_boolean(&params[params_cnt].value, FALSE);\n\t\t\t++params_cnt;\n\n\t\t\tparams[params_cnt].name = \"reliable\";\n\t\t\tg_value_init(&params[params_cnt].value, G_TYPE_BOOLEAN);\n\t\t\tg_value_set_boolean(&params[params_cnt].value, TRUE);\n\t\t\t++params_cnt;\n\t\t}\n\n\t\t/* Don't use the globally defined stun server (it is used by\n\t\t * default in backend-fs2) because it generates srflx local\n\t\t * candidates that confuse SfB when they contribute to valid\n\t\t * pairs in controlled mode:\n\t\t *\n\t\t * ms-client-diagnostics: 21\n\t\t *   \"Call failed to establish due to a media connectivity\n\t\t *   failure where one endpoint is of unknown type\"\n\t\t *\n\t\t * These candidates will be discovered anyway during the\n\t\t * conncheck as prflx, and they will be accepted and nominated\n\t\t * by SfB when having this type. */\n\t\tparams[params_cnt].name = \"stun-ip\";\n\t\tg_value_init(&params[params_cnt].value, G_TYPE_STRING);\n\t\tg_value_set_string(&params[params_cnt].value, NULL);\n\t\t++params_cnt;\n\t} else {\n\t\t// TODO: session naming here, Communicator needs audio/video\n\t\ttransmitter = \"rawudp\";\n\t\t//sessionid = \"sipe-voice-rawudp\";\n\t}\n\n\tensure_codecs_conf();\n\n#ifdef HAVE_XDATA\n\tif (type == SIPE_MEDIA_APPLICATION) {\n\t\tpurple_media_manager_set_application_data_callbacks(\n\t\t\t\tpurple_media_manager_get(),\n\t\t\t\tmedia->m, stream->id, stream->call->with,\n\t\t\t\t&callbacks, stream->call, NULL);\n\t}\n#endif\n\n\tbackend_stream = g_new0(struct sipe_backend_media_stream, 1);\n\n\tpipe = purple_media_manager_get_pipeline(purple_media_manager_get());\n\tif (pipe) {\n\t\tGstBus *bus;\n\n\t\tbus = gst_element_get_bus(pipe);\n\t\tbackend_stream->gst_bus_cb_id = g_signal_connect(bus, \"message\",\n\t\t\t\tG_CALLBACK(gst_bus_cb), stream);\n\t\tgst_object_unref(bus);\n\t}\n\n\tif (purple_media_add_stream(media->m, stream->id, stream->call->with,\n\t\t\t\t    sipe_media_to_purple(type),\n\t\t\t\t    initiator, transmitter, params_cnt,\n\t\t\t\t    params)) {\n\t\tif (!initiator)\n\t\t\t++media->unconfirmed_streams;\n\t} else {\n\t\tsipe_backend_media_stream_free(backend_stream);\n\t\tbackend_stream = NULL;\n\t}\n\n\tg_free(params);\n\n\treturn backend_stream;\n}\n\nvoid\nsipe_backend_media_stream_end(struct sipe_media_call *media,\n\t\t\t      struct sipe_media_stream *stream)\n{\n\tpurple_media_end(media->backend_private->m, stream->id, NULL);\n}\n\nvoid\nsipe_backend_media_add_remote_candidates(struct sipe_media_call *media,\n\t\t\t\t\t struct sipe_media_stream *stream,\n\t\t\t\t\t GList *candidates)\n{\n\tGList *udp_candidates = NULL;\n\n#ifndef HAVE_PURPLE_NEW_TCP_ENUMS\n\t/* Keep only UDP candidates in the list to set. */\n\twhile (candidates) {\n\t\tPurpleMediaCandidate *candidate = candidates->data;\n\t\tPurpleMediaNetworkProtocol proto;\n\n\t\tproto = purple_media_candidate_get_protocol(candidate);\n\t\tif (proto == PURPLE_MEDIA_NETWORK_PROTOCOL_UDP)\n\t\t\tudp_candidates = g_list_append(udp_candidates, candidate);\n\n\t\tcandidates = candidates->next;\n\t}\n\n\tcandidates = udp_candidates;\n#endif\n\n\tpurple_media_add_remote_candidates(media->backend_private->m,\n\t\t\t\t\t   stream->id, media->with, candidates);\n\n\tg_list_free(udp_candidates);\n}\n\ngboolean sipe_backend_media_is_initiator(struct sipe_media_call *media,\n\t\t\t\t\t struct sipe_media_stream *stream)\n{\n\treturn purple_media_is_initiator(media->backend_private->m,\n\t\t\t\t\t stream ? stream->id : NULL,\n\t\t\t\t\t stream ? media->with : NULL);\n}\n\ngboolean sipe_backend_media_accepted(struct sipe_backend_media *media)\n{\n\treturn purple_media_accepted(media->m, NULL, NULL);\n}\n\ngboolean\nsipe_backend_stream_initialized(struct sipe_media_call *media,\n\t\t\t\tstruct sipe_media_stream *stream)\n{\n\tg_return_val_if_fail(media, FALSE);\n\tg_return_val_if_fail(stream, FALSE);\n\n\tif (purple_media_candidates_prepared(media->backend_private->m,\n\t\t\t\t\t     stream->id, media->with)) {\n\t\tGList *codecs;\n\t\tcodecs = purple_media_get_codecs(media->backend_private->m,\n\t\t\t\t\t\t stream->id);\n\t\tif (codecs) {\n\t\t\tpurple_media_codec_list_free(codecs);\n\t\t\treturn TRUE;\n\t\t}\n\t}\n\treturn FALSE;\n}\n\nstatic GList *\nduplicate_tcp_candidates(GList *candidates)\n{\n\tGList *i;\n\tGList *result = NULL;\n\n\tfor (i = candidates; i; i = i->next) {\n\t\tPurpleMediaCandidate *candidate = i->data;\n\t\tPurpleMediaNetworkProtocol protocol =\n\t\t\t\tpurple_media_candidate_get_protocol(candidate);\n\t\tguint component_id =\n\t\t\t\tpurple_media_candidate_get_component_id(candidate);\n\n\t\tif (protocol != PURPLE_MEDIA_NETWORK_PROTOCOL_UDP) {\n\t\t\tPurpleMediaCandidate *c2;\n\n\t\t\tif (component_id != PURPLE_MEDIA_COMPONENT_RTP) {\n\t\t\t\t/* Ignore TCP candidates for other than\n\t\t\t\t * the first component. */\n\t\t\t\tg_object_unref(candidate);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tc2 = purple_media_candidate_copy(candidate);\n\t\t\tg_object_set(c2,\n\t\t\t\t     \"component-id\", PURPLE_MEDIA_COMPONENT_RTCP,\n\t\t\t\t     NULL);\n\t\t\tresult = g_list_append(result, c2);\n\t\t}\n\n\t\tresult = g_list_append(result, candidate);\n\t}\n\n\tg_list_free(candidates);\n\n\treturn result;\n}\n\nGList *\nsipe_backend_media_stream_get_active_local_candidates(struct sipe_media_stream *stream)\n{\n\tGList *candidates = purple_media_get_active_local_candidates(\n\t\t\tstream->call->backend_private->m, stream->id,\n\t\t\tstream->call->with);\n\treturn duplicate_tcp_candidates(candidates);\n}\n\nGList *\nsipe_backend_media_stream_get_active_remote_candidates(struct sipe_media_stream *stream)\n{\n\tGList *candidates = purple_media_get_active_remote_candidates(\n\t\t\tstream->call->backend_private->m, stream->id,\n\t\t\tstream->call->with);\n\treturn duplicate_tcp_candidates(candidates);\n}\n\n#ifdef HAVE_SRTP\nvoid\nsipe_backend_media_set_encryption_keys(struct sipe_media_call *media,\n\t\t\t\t       struct sipe_media_stream *stream,\n\t\t\t\t       const guchar *encryption_key,\n\t\t\t\t       const guchar *decryption_key)\n{\n\tpurple_media_set_encryption_parameters(media->backend_private->m,\n\t\t\tstream->id,\n\t\t\t\"aes-128-icm\",\n\t\t\t\"hmac-sha1-80\",\n\t\t\t(gchar *)encryption_key, SIPE_SRTP_KEY_LEN);\n\tpurple_media_set_decryption_parameters(media->backend_private->m,\n\t\t\tstream->id, media->with,\n\t\t\t\"aes-128-icm\",\n\t\t\t\"hmac-sha1-80\",\n\t\t\t(gchar *)decryption_key, SIPE_SRTP_KEY_LEN);\n}\n#else\nvoid\nsipe_backend_media_set_encryption_keys(SIPE_UNUSED_PARAMETER struct sipe_media_call *media,\n\t\t\t\t       SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream,\n\t\t\t\t       SIPE_UNUSED_PARAMETER const guchar *encryption_key,\n\t\t\t\t       SIPE_UNUSED_PARAMETER const guchar *decryption_key)\n{}\n#endif\n\n#if defined(HAVE_SRTP) && PURPLE_VERSION_CHECK(2,14,0)\nvoid\nsipe_backend_media_set_require_encryption(struct sipe_media_call *media,\n\t\t\t\t\t  struct sipe_media_stream *stream,\n\t\t\t\t\t  const gboolean require_encryption)\n{\n\tpurple_media_set_require_encryption(media->backend_private->m,\n\t\t\tstream->id, media->with, require_encryption);\n}\n#else\nvoid\nsipe_backend_media_set_require_encryption(SIPE_UNUSED_PARAMETER struct sipe_media_call *media,\n\t\t\t\t\t  SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream,\n\t\t\t\t\t  SIPE_UNUSED_PARAMETER const gboolean require_encryption)\n{}\n#endif\n\nvoid sipe_backend_stream_hold(struct sipe_media_call *media,\n\t\t\t      struct sipe_media_stream *stream,\n\t\t\t      gboolean local)\n{\n\tpurple_media_stream_info(media->backend_private->m, PURPLE_MEDIA_INFO_HOLD,\n\t\t\t\t stream->id, media->with, local);\n}\n\nvoid sipe_backend_stream_unhold(struct sipe_media_call *media,\n\t\t\t\tstruct sipe_media_stream *stream,\n\t\t\t\tgboolean local)\n{\n\tpurple_media_stream_info(media->backend_private->m, PURPLE_MEDIA_INFO_UNHOLD,\n\t\t\t\t stream->id, media->with, local);\n}\n\ngboolean sipe_backend_stream_is_held(struct sipe_media_stream *stream)\n{\n\tg_return_val_if_fail(stream, FALSE);\n\n\treturn stream->backend_private->local_on_hold ||\n\t       stream->backend_private->remote_on_hold;\n}\n\nstruct sipe_backend_codec *\nsipe_backend_codec_new(int id, const char *name, SipeMediaType type,\n\t\t       guint clock_rate, guint channels)\n{\n\tPurpleMediaCodec *codec;\n\n\tif (sipe_strcase_equal(name, \"X-H264UC\")) {\n\t\tname = \"H264\";\n\t}\n\n\tcodec = purple_media_codec_new(id, name, sipe_media_to_purple(type),\n\t\t\t\t       clock_rate);\n\tg_object_set(codec, \"channels\", channels, NULL);\n\n\treturn (struct sipe_backend_codec *)codec;\n}\n\nvoid\nsipe_backend_codec_free(struct sipe_backend_codec *codec)\n{\n\tif (codec)\n\t\tg_object_unref(codec);\n}\n\nint\nsipe_backend_codec_get_id(struct sipe_backend_codec *codec)\n{\n\treturn purple_media_codec_get_id((PurpleMediaCodec *)codec);\n}\n\ngchar *\nsipe_backend_codec_get_name(struct sipe_backend_codec *codec)\n{\n\t/* Not explicitly documented, but return value must be g_free()'d */\n\treturn purple_media_codec_get_encoding_name((PurpleMediaCodec *)codec);\n}\n\nguint\nsipe_backend_codec_get_clock_rate(struct sipe_backend_codec *codec)\n{\n\treturn purple_media_codec_get_clock_rate((PurpleMediaCodec *)codec);\n}\n\nvoid\nsipe_backend_codec_add_optional_parameter(struct sipe_backend_codec *codec,\n\t\t\t\t\t\t\t\t\t\t  const gchar *name, const gchar *value)\n{\n\tpurple_media_codec_add_optional_parameter((PurpleMediaCodec *)codec, name, value);\n}\n\nGList *\nsipe_backend_codec_get_optional_parameters(struct sipe_backend_codec *codec)\n{\n\treturn purple_media_codec_get_optional_parameters((PurpleMediaCodec *)codec);\n}\n\ngboolean\nsipe_backend_set_remote_codecs(struct sipe_media_call *media,\n\t\t\t       struct sipe_media_stream *stream,\n\t\t\t       GList *codecs)\n{\n\tgboolean result;\n\n\t/* Lync offers multichannel audio as a codec with the same encoding name\n\t * as the mono variant, but a different payload type and an extra\n\t * encoding parameter:\n\t *\n\t *  a=rtpmap:117 G722/8000/2\n\t *  a=rtpmap:9 G722/8000\n\t *\n\t * Since avenc_g722 from gst-libav can encode only one audio channel, ignore\n\t * multichannel codecs we were offered by the remote host.\n\t */\n\tGList *tmp = NULL;\n\tPurpleMediaSessionType type;\n\n\tfor (; codecs; codecs = codecs->next) {\n\t\tPurpleMediaCodec *codec = codecs->data;\n\n\t\tg_object_get(codec, \"media-type\", &type, NULL);\n\n\t\tif (type == PURPLE_MEDIA_AUDIO &&\n\t\t    purple_media_codec_get_channels(codec) > 1) {\n\t\t\tcontinue;\n\t\t}\n\n\t\ttmp = g_list_append(tmp, codec);\n\t}\n\n\tresult = purple_media_set_remote_codecs(media->backend_private->m,\n\t\t\t\t\t\tstream->id, media->with,\n\t\t\t\t\t\ttmp);\n\tg_list_free(tmp);\n\n\treturn result;\n}\n\nGList*\nsipe_backend_get_local_codecs(struct sipe_media_call *media,\n\t\t\t      struct sipe_media_stream *stream)\n{\n\tGList *codecs = purple_media_get_codecs(media->backend_private->m,\n\t\t\t\t\t\tstream->id);\n\tGList *i = codecs;\n\n\twhile (i) {\n\t\tPurpleMediaCodec *codec = i->data;\n\t\tgchar *encoding_name = purple_media_codec_get_encoding_name(codec);\n\n\t\tif (sipe_strequal(encoding_name, \"H264\")) {\n\t\t\t/*\n\t\t\t * Sanitize H264 codec:\n\t\t\t * - the encoding name must be \"X-H264UC\"\n\t\t\t * - remove \"sprop-parameter-sets\" parameter which is\n\t\t\t *   rejected by Lync\n\t\t\t * - add \"packetization-mode\" parameter if not already\n\t\t\t *   present\n\t\t\t */\n\n\t\t\tPurpleMediaCodec *new_codec;\n\t\t\tGList *it;\n\n\t\t\tnew_codec = purple_media_codec_new(\n\t\t\t\t\tpurple_media_codec_get_id(codec),\n\t\t\t\t\t\"X-H264UC\",\n\t\t\t\t\tPURPLE_MEDIA_VIDEO,\n\t\t\t\t\tpurple_media_codec_get_clock_rate(codec));\n\n\t\t\tg_object_set(new_codec, \"channels\",\n\t\t\t\t\tpurple_media_codec_get_channels(codec),\n\t\t\t\t\tNULL);\n\n\t\t\tit = purple_media_codec_get_optional_parameters(codec);\n\n\t\t\tfor (; it; it = g_list_next(it)) {\n\t\t\t\tPurpleKeyValuePair *pair = it->data;\n\n\t\t\t\tif (sipe_strequal(pair->key, \"sprop-parameter-sets\")) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tpurple_media_codec_add_optional_parameter(new_codec,\n\t\t\t\t\t\tpair->key, pair->value);\n\t\t\t}\n\n\t\t\tif (!purple_media_codec_get_optional_parameter(new_codec,\n\t\t\t\t\t\"packetization-mode\", NULL)) {\n\t\t\t\tpurple_media_codec_add_optional_parameter(new_codec,\n\t\t\t\t\t\t\"packetization-mode\",\n\t\t\t\t\t\t\"1;mst-mode=NI-TC\");\n\t\t\t}\n\n\t\t\ti->data = new_codec;\n\n\t\t\tg_object_unref(codec);\n\t\t} else\n\t\t\ti = i->next;\n\n\t\tg_free(encoding_name);\n\t}\n\n\treturn codecs;\n}\n\nstruct sipe_backend_candidate *\nsipe_backend_candidate_new(const gchar *foundation,\n\t\t\t   SipeComponentType component,\n\t\t\t   SipeCandidateType type, SipeNetworkProtocol proto,\n\t\t\t   const gchar *ip, guint port,\n\t\t\t   const gchar *username,\n\t\t\t   const gchar *password)\n{\n\tPurpleMediaCandidate *c = purple_media_candidate_new(\n\t\t/* Libnice and Farsight rely on non-NULL foundation to\n\t\t * distinguish between candidates of a component. When NULL\n\t\t * foundation is passed (ie. ICE draft 6 does not use foudation),\n\t\t * use username instead. If no foundation is provided, Farsight\n\t\t * may signal an active candidate different from the one actually\n\t\t * in use. See Farsight's agent_new_selected_pair() in\n\t\t * fs-nice-stream-transmitter.h where first candidate in the\n\t\t * remote list is always selected when no foundation. */\n\t\tfoundation ? foundation : username,\n\t\tcomponent,\n\t\tsipe_candidate_type_to_purple(type),\n\t\tsipe_network_protocol_to_purple(proto),\n\t\tip,\n\t\tport);\n\tg_object_set(c, \"username\", username, \"password\", password, NULL);\n\treturn (struct sipe_backend_candidate *)c;\n}\n\nvoid\nsipe_backend_candidate_free(struct sipe_backend_candidate *candidate)\n{\n\tif (candidate)\n\t\tg_object_unref(candidate);\n}\n\ngchar *\nsipe_backend_candidate_get_username(struct sipe_backend_candidate *candidate)\n{\n\t/* Not explicitly documented, but return value must be g_free()'d */\n\treturn purple_media_candidate_get_username((PurpleMediaCandidate*)candidate);\n}\n\ngchar *\nsipe_backend_candidate_get_password(struct sipe_backend_candidate *candidate)\n{\n\t/* Not explicitly documented, but return value must be g_free()'d */\n\treturn purple_media_candidate_get_password((PurpleMediaCandidate*)candidate);\n}\n\ngchar *\nsipe_backend_candidate_get_foundation(struct sipe_backend_candidate *candidate)\n{\n\t/* Not explicitly documented, but return value must be g_free()'d */\n\treturn purple_media_candidate_get_foundation((PurpleMediaCandidate*)candidate);\n}\n\ngchar *\nsipe_backend_candidate_get_ip(struct sipe_backend_candidate *candidate)\n{\n\t/* Not explicitly documented, but return value must be g_free()'d */\n\treturn purple_media_candidate_get_ip((PurpleMediaCandidate*)candidate);\n}\n\nguint\nsipe_backend_candidate_get_port(struct sipe_backend_candidate *candidate)\n{\n\treturn purple_media_candidate_get_port((PurpleMediaCandidate*)candidate);\n}\n\ngchar *\nsipe_backend_candidate_get_base_ip(struct sipe_backend_candidate *candidate)\n{\n\t/* Not explicitly documented, but return value must be g_free()'d */\n\treturn purple_media_candidate_get_base_ip((PurpleMediaCandidate*)candidate);\n}\n\nguint\nsipe_backend_candidate_get_base_port(struct sipe_backend_candidate *candidate)\n{\n\treturn purple_media_candidate_get_base_port((PurpleMediaCandidate*)candidate);\n}\n\nguint32\nsipe_backend_candidate_get_priority(struct sipe_backend_candidate *candidate)\n{\n\treturn purple_media_candidate_get_priority((PurpleMediaCandidate*)candidate);\n}\n\nvoid\nsipe_backend_candidate_set_priority(struct sipe_backend_candidate *candidate, guint32 priority)\n{\n\tg_object_set(candidate, \"priority\", priority, NULL);\n}\n\nSipeComponentType\nsipe_backend_candidate_get_component_type(struct sipe_backend_candidate *candidate)\n{\n\treturn purple_media_candidate_get_component_id((PurpleMediaCandidate*)candidate);\n}\n\nSipeCandidateType\nsipe_backend_candidate_get_type(struct sipe_backend_candidate *candidate)\n{\n\tPurpleMediaCandidateType type =\n\t\tpurple_media_candidate_get_candidate_type((PurpleMediaCandidate*)candidate);\n\treturn purple_candidate_type_to_sipe(type);\n}\n\nSipeNetworkProtocol\nsipe_backend_candidate_get_protocol(struct sipe_backend_candidate *candidate)\n{\n\tPurpleMediaNetworkProtocol proto =\n\t\tpurple_media_candidate_get_protocol((PurpleMediaCandidate*)candidate);\n\treturn purple_network_protocol_to_sipe(proto);\n}\n\n/*\n * libnice can return a candidate list with duplicates. It is currently\n * unknown if this is a bug in libnice or a configuration error in Skype\n * for Business setups.\n *\n * While this is not a bug in SIPE, by removing these duplicates we make\n * sure that SIPE doesn't generate incorrect SDP messages.\n */\nstatic GList *\nfilter_duplicate_candidates(GList *candidates)\n{\n\tGHashTable *seen   = g_hash_table_new_full(g_str_hash, g_str_equal,\n\t\t\t\t\t\t   g_free, NULL);\n\tGList      *result = NULL;\n\tGList      *it;\n\n\tfor (it = candidates; it; it = it->next) {\n\t\tPurpleMediaCandidate *c = it->data;\n\t\tgchar *foundation = purple_media_candidate_get_foundation(c);\n\t\tgchar *ip         = purple_media_candidate_get_ip(c);\n\t\tgchar *base_ip    = purple_media_candidate_get_base_ip(c);\n\t\tgchar *id = g_strdup_printf(\"%s %d %d %d %s %d %d %s %d\",\n\t\t\tfoundation ? foundation : \"-\",\n\t\t\tpurple_media_candidate_get_component_id(c),\n\t\t\tpurple_media_candidate_get_protocol(c),\n\t\t\tpurple_media_candidate_get_priority(c),\n\t\t\tip ? ip : \"-\",\n\t\t\tpurple_media_candidate_get_port(c),\n\t\t\tpurple_media_candidate_get_candidate_type(c),\n\t\t\tbase_ip ? base_ip : \"-\",\n\t\t\tpurple_media_candidate_get_base_port(c)\n\t\t);\n\n\t\tg_free(base_ip);\n\t\tg_free(ip);\n\t\tg_free(foundation);\n\n\t\tif (g_hash_table_lookup(seen, id)) {\n\t\t\tSIPE_DEBUG_INFO(\"filter_duplicate_candidates: dropping '%s'\",\n\t\t\t\t\tid);\n\t\t\tg_free(id);\n\t\t\tg_object_unref(c);\n\t\t} else {\n\t\t\tg_hash_table_insert(seen, id, GUINT_TO_POINTER(TRUE));\n\t\t\tresult = g_list_append(result, c);\n\t\t}\n\t}\n\n\tg_hash_table_destroy(seen);\n\tg_list_free(candidates);\n\n\treturn result;\n}\n\nstatic void\nremove_lone_candidate_cb(SIPE_UNUSED_PARAMETER gpointer key,\n\t\t\t gpointer value,\n\t\t\t gpointer user_data)\n{\n\tGList  *entry = value;\n\tGList **candidates = user_data;\n\n\tg_object_unref(entry->data);\n\t*candidates = g_list_delete_link(*candidates, entry);\n}\n\nstatic GList *\nensure_candidate_pairs(GList *candidates)\n{\n\tGHashTable *lone_cand_links;\n\tGList\t   *i;\n\n\tlone_cand_links = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);\n\n\tfor (i = candidates; i; i = i->next) {\n\t\tPurpleMediaCandidate *c = i->data;\n\t\tgchar *foundation = purple_media_candidate_get_foundation(c);\n\n\t\tif (g_hash_table_lookup(lone_cand_links, foundation)) {\n\t\t\tg_hash_table_remove(lone_cand_links, foundation);\n\t\t\tg_free(foundation);\n\t\t} else {\n\t\t\tg_hash_table_insert(lone_cand_links, foundation, i);\n\t\t}\n\t}\n\n\tg_hash_table_foreach(lone_cand_links, remove_lone_candidate_cb, &candidates);\n\tg_hash_table_destroy(lone_cand_links);\n\n\treturn candidates;\n}\n\nGList *\nsipe_backend_get_local_candidates(struct sipe_media_call *media,\n\t\t\t\t  struct sipe_media_stream *stream)\n{\n\tGList *candidates =\n\t\t\tpurple_media_get_local_candidates(media->backend_private->m,\n\t\t\t\t\t\t\t  stream->id,\n\t\t\t\t\t\t\t  media->with);\n\tcandidates = filter_duplicate_candidates(candidates);\n\tcandidates = duplicate_tcp_candidates(candidates);\n\n\t/*\n\t * Sometimes purple will not return complete list of candidates, even\n\t * after \"candidates-prepared\" signal is emitted. This is a feature of\n\t * libnice, namely affecting candidates discovered via UPnP. Nice does\n\t * not wait until discovery is finished and can signal end of candidate\n\t * gathering before all responses from UPnP enabled gateways are received.\n\t *\n\t * Remove any incomplete RTP+RTCP candidate pairs from the list.\n\t */\n\tcandidates = ensure_candidate_pairs(candidates);\n\treturn candidates;\n}\n\nvoid\nsipe_backend_media_accept(struct sipe_backend_media *media, gboolean local)\n{\n\tif (media)\n\t\tpurple_media_stream_info(media->m, PURPLE_MEDIA_INFO_ACCEPT,\n\t\t\t\t\t NULL, NULL, local);\n}\n\nvoid\nsipe_backend_media_hangup(struct sipe_backend_media *media, gboolean local)\n{\n\tif (media)\n\t\tpurple_media_stream_info(media->m, PURPLE_MEDIA_INFO_HANGUP,\n\t\t\t\t\t NULL, NULL, local);\n}\n\nvoid\nsipe_backend_media_reject(struct sipe_backend_media *media, gboolean local)\n{\n\tif (media)\n\t\tpurple_media_stream_info(media->m, PURPLE_MEDIA_INFO_REJECT,\n\t\t\t\t\t NULL, NULL, local);\n}\n\nstatic PurpleMediaSessionType sipe_media_to_purple(SipeMediaType type)\n{\n\tswitch (type) {\n\t\tcase SIPE_MEDIA_AUDIO: return PURPLE_MEDIA_AUDIO;\n\t\tcase SIPE_MEDIA_VIDEO: return PURPLE_MEDIA_VIDEO;\n#ifdef HAVE_XDATA\n\t\tcase SIPE_MEDIA_APPLICATION: return PURPLE_MEDIA_APPLICATION;\n#endif\n\t\tdefault:               return PURPLE_MEDIA_NONE;\n\t}\n}\n\nstatic PurpleMediaCandidateType\nsipe_candidate_type_to_purple(SipeCandidateType type)\n{\n\tswitch (type) {\n\t\tcase SIPE_CANDIDATE_TYPE_HOST:\treturn PURPLE_MEDIA_CANDIDATE_TYPE_HOST;\n\t\tcase SIPE_CANDIDATE_TYPE_RELAY:\treturn PURPLE_MEDIA_CANDIDATE_TYPE_RELAY;\n\t\tcase SIPE_CANDIDATE_TYPE_SRFLX:\treturn PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX;\n\t\tcase SIPE_CANDIDATE_TYPE_PRFLX: return PURPLE_MEDIA_CANDIDATE_TYPE_PRFLX;\n\t\tdefault:\t\t\treturn PURPLE_MEDIA_CANDIDATE_TYPE_HOST;\n\t}\n}\n\nstatic SipeCandidateType\npurple_candidate_type_to_sipe(PurpleMediaCandidateType type)\n{\n\tswitch (type) {\n\t\tcase PURPLE_MEDIA_CANDIDATE_TYPE_HOST:\treturn SIPE_CANDIDATE_TYPE_HOST;\n\t\tcase PURPLE_MEDIA_CANDIDATE_TYPE_RELAY:\treturn SIPE_CANDIDATE_TYPE_RELAY;\n\t\tcase PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX:\treturn SIPE_CANDIDATE_TYPE_SRFLX;\n\t\tcase PURPLE_MEDIA_CANDIDATE_TYPE_PRFLX: return SIPE_CANDIDATE_TYPE_PRFLX;\n\t\tdefault:\t\t\t\treturn SIPE_CANDIDATE_TYPE_HOST;\n\t}\n}\n\nstatic PurpleMediaNetworkProtocol\nsipe_network_protocol_to_purple(SipeNetworkProtocol proto)\n{\n\tswitch (proto) {\n#ifdef HAVE_PURPLE_NEW_TCP_ENUMS\n\t\tcase SIPE_NETWORK_PROTOCOL_TCP_ACTIVE:\n\t\t\treturn PURPLE_MEDIA_NETWORK_PROTOCOL_TCP_ACTIVE;\n\t\tcase SIPE_NETWORK_PROTOCOL_TCP_PASSIVE:\n\t\t\treturn PURPLE_MEDIA_NETWORK_PROTOCOL_TCP_PASSIVE;\n\t\tcase SIPE_NETWORK_PROTOCOL_TCP_SO:\n\t\t\treturn PURPLE_MEDIA_NETWORK_PROTOCOL_TCP_SO;\n#else\n\t\tcase SIPE_NETWORK_PROTOCOL_TCP_ACTIVE:\n\t\tcase SIPE_NETWORK_PROTOCOL_TCP_PASSIVE:\n\t\tcase SIPE_NETWORK_PROTOCOL_TCP_SO:\n\t\t\treturn PURPLE_MEDIA_NETWORK_PROTOCOL_TCP;\n#endif\n\t\tdefault:\n\t\tcase SIPE_NETWORK_PROTOCOL_UDP:\n\t\t\treturn PURPLE_MEDIA_NETWORK_PROTOCOL_UDP;\n\t}\n}\n\nstatic SipeNetworkProtocol\npurple_network_protocol_to_sipe(PurpleMediaNetworkProtocol proto)\n{\n\tswitch (proto) {\n#ifdef HAVE_PURPLE_NEW_TCP_ENUMS\n\t\tcase PURPLE_MEDIA_NETWORK_PROTOCOL_TCP_ACTIVE:\n\t\t\treturn SIPE_NETWORK_PROTOCOL_TCP_ACTIVE;\n\t\tcase PURPLE_MEDIA_NETWORK_PROTOCOL_TCP_PASSIVE:\n\t\t\treturn SIPE_NETWORK_PROTOCOL_TCP_PASSIVE;\n\t\tcase PURPLE_MEDIA_NETWORK_PROTOCOL_TCP_SO:\n\t\t\treturn SIPE_NETWORK_PROTOCOL_TCP_SO;\n#else\n\t\tcase PURPLE_MEDIA_NETWORK_PROTOCOL_TCP:\n\t\t\treturn SIPE_NETWORK_PROTOCOL_TCP_ACTIVE;\n#endif\n\t\tdefault:\n\t\tcase PURPLE_MEDIA_NETWORK_PROTOCOL_UDP:\n\t\t\treturn SIPE_NETWORK_PROTOCOL_UDP;\n\t}\n}\n\n#ifdef HAVE_SRTP\nSipeEncryptionPolicy\nsipe_backend_media_get_encryption_policy(struct sipe_core_public *sipe_public)\n{\n\tPurpleAccount *account = sipe_public->backend_private->account;\n\n\tconst char *policy =\n\t\t\tpurple_account_get_string(account, \"encryption-policy\",\n\t\t\t\t\t\t  \"obey-server\");\n\n\tif (sipe_strequal(policy, \"disabled\")) {\n\t\treturn SIPE_ENCRYPTION_POLICY_REJECTED;\n\t} else if (sipe_strequal(policy, \"optional\")) {\n\t\treturn SIPE_ENCRYPTION_POLICY_OPTIONAL;\n\t} else if (sipe_strequal(policy, \"required\")) {\n\t\treturn SIPE_ENCRYPTION_POLICY_REQUIRED;\n\t} else {\n\t\treturn SIPE_ENCRYPTION_POLICY_OBEY_SERVER;\n\t}\n}\n#else\nSipeEncryptionPolicy\nsipe_backend_media_get_encryption_policy(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public)\n{\n\treturn SIPE_ENCRYPTION_POLICY_REJECTED;\n}\n#endif\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-mime.c",
    "content": "/**\n * @file purple-mime.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2015 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include \"glib.h\"\n\n#include \"mime.h\"\n\n#include \"sipe-mime.h\"\n#include \"sipe-core.h\"\n\nvoid sipe_mime_init(void)\n{\n\t/* Nothing to do */\n}\n\nvoid sipe_mime_shutdown(void)\n{\n\t/* Nothing to do */\n}\n\nstatic\nGSList * mime_fields_to_nameval(PurpleMimePart* part)\n{\n\tGList *keys = purple_mime_part_get_fields(part);\n\tGSList *fields = NULL;\n\n\twhile (keys) {\n\t\tconst char *key = keys->data;\n\t\tconst char *value = purple_mime_part_get_field(part, key);\n\n\t\tfields = sipe_utils_nameval_add(fields, key, value);\n\n\t\tkeys = keys->next;\n\t}\n\n\treturn fields;\n}\n\nvoid sipe_mime_parts_foreach(const gchar *type,\n\t\t\t     const gchar *body,\n\t\t\t     sipe_mime_parts_cb callback,\n\t\t\t     gpointer user_data)\n{\n\tgchar *doc = g_strdup_printf(\"Content-Type: %s\\r\\n\\r\\n%s\", type, body);\n\tPurpleMimeDocument *mime = purple_mime_document_parse(doc);\n\n\tif (mime) {\n\t\tGList* parts = purple_mime_document_get_parts(mime);\n\n\t\twhile (parts) {\n\t\t\tconst gchar *content_type = purple_mime_part_get_field(parts->data,\n\t\t\t\t\t\t\t\t\t       \"Content-Type\");\n\t\t\tif (content_type) {\n\t\t\t\tconst gchar *content = NULL;\n\t\t\t\tguchar *content_decoded = NULL;\n\t\t\t\tgsize length = 0;\n\n\t\t\t\tGSList *fields = mime_fields_to_nameval(parts->data);\n\n\t\t\t\tpurple_mime_part_get_data_decoded(parts->data,\n\t\t\t\t\t\t\t\t  &content_decoded,\n\t\t\t\t\t\t\t\t  &length);\n\t\t\t\tif (content_decoded) {\n\t\t\t\t\tcontent = (gchar *) content_decoded;\n\t\t\t\t} else {\n\t\t\t\t\t/* Unknown encoding in Content-Transfer-Encoding\n\t\t\t\t\t * field; revert to the plain content extraction. */\n\t\t\t\t\tcontent = purple_mime_part_get_data(parts->data);\n\t\t\t\t\tlength = purple_mime_part_get_length(parts->data);\n\t\t\t\t}\n\n\t\t\t\t(*callback)(user_data, fields, content, length);\n\n\t\t\t\tsipe_utils_nameval_free(fields);\n\t\t\t\tg_free(content_decoded);\n\t\t\t}\n\t\t\tparts = parts->next;\n\t\t}\n\t\tpurple_mime_document_free(mime);\n\t}\n\tg_free(doc);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-network.c",
    "content": "/**\n * @file purple-network.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\" /* coverity[hfa: FALSE] */\n#endif\n\n#include <string.h>\n\n#include \"glib.h\"\n\n#include \"conversation.h\"\n#include \"network.h\"\n#include \"eventloop.h\"\n\n#ifdef _WIN32\n/* wrappers for write() & friends for socket handling */\n#include \"win32/win32dep.h\"\n#include <nspapi.h>\n#else\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <arpa/inet.h>\n#endif\n\n#ifdef HAVE_UNISTD_H\n#include <unistd.h>\n#endif\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"purple-private.h\"\n\nstruct sipe_backend_listendata {\n\tsipe_listen_start_cb listen_cb;\n\tsipe_client_connected_cb connect_cb;\n\n\tPurpleNetworkListenData *listener;\n\tint watcher;\n\n\tint listenfd;\n\tgpointer data;\n};\n\nstatic void\nclient_connected_cb(struct sipe_backend_listendata *ldata, gint listenfd,\n\t\t    SIPE_UNUSED_PARAMETER PurpleInputCondition cond)\n{\n\tstruct sockaddr_in saddr;\n\tsocklen_t slen = sizeof (saddr);\n\n\tint fd = accept(listenfd, (struct sockaddr*)&saddr, &slen);\n\n\tpurple_input_remove(ldata->watcher);\n\tldata->watcher = 0;\n\tclose(listenfd);\n\tldata->listenfd = -1;\n\n\tif (fd >= 0) {\n\t\tif (ldata->connect_cb) {\n\t\t\tldata->connect_cb(sipe_backend_fd_from_int(fd), ldata->data);\n\t\t} else {\n\t\t\tclose(fd);\n\t\t}\n\t}\n\n\tg_free(ldata);\n}\n\nstatic void\nbackend_listen_cb(int listenfd, struct sipe_backend_listendata *ldata)\n{\n\tldata->listenfd = -1;\n\tldata->listener = NULL;\n\tldata->listenfd = listenfd;\n\n\tif (ldata->listen_cb) {\n\t\t/*\n\t\t * NOTE: getsockname() on Windows seems to be picky about the\n\t\t *       buffer location. Use an allocated buffer instead of\n\t\t *       one on the stack,\n\t\t */\n\t\tunion socket_info {\n\t\t\tstruct sockaddr         sa;     /* to avoid casts */\n\t\t\tstruct sockaddr_in      sa_in;  /* IPv4 variant   */\n\t\t\tstruct sockaddr_in6     sa_in6; /* IPv6 variant   */\n\t\t\tstruct sockaddr_storage unused; /* for alignment  */\n\t\t} *si = g_new(union socket_info, 1);\n\t\tsocklen_t si_len = sizeof(*si);\n\t\tguint port = htons(0); /* error fallback */\n\n\t\tif (getsockname(listenfd, &si->sa, &si_len) == 0) {\n\t\t\tport = (si->sa.sa_family == AF_INET)  ? si->sa_in.sin_port :\n\t\t\t       (si->sa.sa_family == AF_INET6) ? si->sa_in6.sin6_port :\n\t\t\t       port;\n\t\t}\n\t\tg_free(si);\n\n\t\tldata->listen_cb(ntohs(port), ldata->data);\n\t}\n\n\tldata->watcher = purple_input_add(listenfd, PURPLE_INPUT_READ,\n\t\t\t\t\t  (PurpleInputFunction)client_connected_cb,\n\t\t\t\t\t  ldata);\n}\n\nstruct sipe_backend_listendata *\nsipe_backend_network_listen_range(unsigned short port_min,\n\t\t\t\t  unsigned short port_max,\n\t\t\t\t  sipe_listen_start_cb listen_cb,\n\t\t\t\t  sipe_client_connected_cb connect_cb,\n\t\t\t\t  gpointer data)\n{\n\tstruct sipe_backend_listendata *ldata;\n\tldata = g_new0(struct sipe_backend_listendata, 1);\n\n\tldata->listen_cb = listen_cb;\n\tldata->connect_cb = connect_cb;\n\tldata->data = data;\n\tldata->listener = purple_network_listen_range(port_min, port_max,\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t\t\t\t      /* @TODO: does FT work with IPv6? */\n\t\t\t\t\t\t      AF_INET,\n#endif\n\t\t\t\t\t\t      SOCK_STREAM,\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t\t\t\t      /* @TODO: should we allow external mapping? */\n\t\t\t\t\t\t      FALSE,\n#endif\n\t\t\t\t\t\t      (PurpleNetworkListenCallback)backend_listen_cb,\n\t\t\t\t\t\t      ldata);\n\n\tif (!ldata->listener) {\n\t\tg_free(ldata);\n\t\treturn NULL;\n\t}\n\n\treturn ldata;\n}\n\nvoid sipe_backend_network_listen_cancel(struct sipe_backend_listendata *ldata)\n{\n\tg_return_if_fail(ldata);\n\n\tif (ldata->listener)\n\t\tpurple_network_listen_cancel(ldata->listener);\n\tif (ldata->listenfd)\n\t\tclose(ldata->listenfd);\n\tg_free(ldata);\n}\n\nstruct sipe_backend_fd *\nsipe_backend_fd_from_int(int fd)\n{\n\tstruct sipe_backend_fd *sipe_fd = g_new(struct sipe_backend_fd, 1);\n\tsipe_fd->fd = fd;\n\treturn sipe_fd;\n}\n\ngboolean\nsipe_backend_fd_is_valid(struct sipe_backend_fd *fd)\n{\n\treturn fd && fd->fd >= 0;\n}\n\nvoid\nsipe_backend_fd_free(struct sipe_backend_fd *fd)\n{\n\tg_free(fd);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-notify.c",
    "content": "/**\n * @file purple-notify.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <time.h>\n\n#include <glib.h>\n\n#include \"conversation.h\"\n#include \"notify.h\"\n\n#include \"version.h\"\n#if PURPLE_VERSION_CHECK(3,0,0)\n#include \"conversations.h\"\n#endif\n\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n\n#include \"purple-private.h\"\n\nstatic void notify_message(struct sipe_core_public *sipe_public,\n\t\t\t   PurpleMessageFlags flags,\n\t\t\t   struct sipe_backend_chat_session *backend_session,\n\t\t\t   const gchar *who,\n\t\t\t   const gchar *message)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tPurpleConversation *conv;\n\n\tif (backend_session) {\n\t\tconv = (PurpleConversation *) backend_session;\n\t} else {\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\tconv = (PurpleConversation *) purple_conversations_find_im_with_account(\n#else\n\t\tconv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY,\n#endif\n\t\t\t\t\t\t\t     who,\n\t\t\t\t\t\t\t     purple_private->account);\n\t}\n\tif (conv) {\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\tpurple_conversation_write_system_message(conv, message, flags);\n#else\n\t\tpurple_conversation_write(conv, NULL, message, flags,\n\t\t\t\t\t  time(NULL));\n#endif\n\t}\n}\n\nvoid sipe_backend_notify_message_error(struct sipe_core_public *sipe_public,\n\t\t\t\t       struct sipe_backend_chat_session *backend_session,\n\t\t\t\t       const gchar *who,\n\t\t\t\t       const gchar *message)\n{\n\tnotify_message(sipe_public, PURPLE_MESSAGE_ERROR,\n\t\t       backend_session, who, message);\n}\n\nvoid sipe_backend_notify_message_info(struct sipe_core_public *sipe_public,\n\t\t\t\t      struct sipe_backend_chat_session *backend_session,\n\t\t\t\t      const gchar *who,\n\t\t\t\t      const gchar *message)\n{\n\tnotify_message(sipe_public, PURPLE_MESSAGE_SYSTEM,\n\t\t       backend_session, who, message);\n}\n\nvoid sipe_backend_notify_error(struct sipe_core_public *sipe_public,\n\t\t\t       const gchar *title,\n\t\t\t       const gchar *msg)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\n\tpurple_notify_error(purple_private->gc, NULL, title, msg\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t    , NULL\n#endif\n\t\t\t    );\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-plugin-common.c",
    "content": "/**\n * @file purple-plugin-common.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n#include <string.h>\n\n#include \"sipe-common.h\"\n\n#include \"account.h\"\n#include \"core.h\"\n#include \"notify.h\"\n#include \"request.h\"\n#include \"version.h\"\n\n#if PURPLE_VERSION_CHECK(3,0,0)\n#include \"action.h\"\n#define PURPLE_TYPE_STRING G_TYPE_STRING\n#define SIPE_PURPLE_ACTION_TO_CONNECTION              action->connection\n#else\n#include \"accountopt.h\"\n#include \"blist.h\"\n#define g_source_remove(t)                            purple_timeout_remove(t)\n#define PURPLE_CONNECTION_FLAG_ALLOW_CUSTOM_SMILEY    PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY\n#define PURPLE_CONNECTION_FLAG_FORMATTING_WBFO        PURPLE_CONNECTION_FORMATTING_WBFO\n#define PURPLE_CONNECTION_FLAG_HTML                   PURPLE_CONNECTION_HTML\n#define PURPLE_CONNECTION_FLAG_NO_BGCOLOR             PURPLE_CONNECTION_NO_BGCOLOR\n#define PURPLE_CONNECTION_FLAG_NO_FONTSIZE            PURPLE_CONNECTION_NO_FONTSIZE\n#define PURPLE_CONNECTION_FLAG_NO_URLDESC             PURPLE_CONNECTION_NO_URLDESC\n#define PURPLE_IS_BUDDY(n)                            PURPLE_BLIST_NODE_IS_BUDDY(n)\n#define PURPLE_IS_CHAT(n)                             PURPLE_BLIST_NODE_IS_CHAT(n)\n#define PURPLE_IM_TYPING                              PURPLE_TYPING\n#define PURPLE_IM_NOT_TYPING                          PURPLE_NOT_TYPING\n#define purple_account_option_string_set_masked(o, f) purple_account_option_set_masked(o, f)\n#define purple_connection_error(g, e, m)              purple_connection_error_reason(g, e, m)\n#define purple_connection_get_flags(gc)               0\n#define purple_connection_set_protocol_data(gc, p)    gc->proto_data = p\n#define purple_connection_set_flags(gc, f)            gc->flags |= f\n#define purple_protocol_action_new(l, c)              purple_plugin_action_new(l, c)\n#define PurpleProtocolAction                          PurplePluginAction\n#define SIPE_PURPLE_ACTION_TO_CONNECTION              action->context\n#endif\n\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-nls.h\"\n\n#include \"purple-private.h\"\n\n/*\n * NOTE: this flag means two things:\n *\n *  - is Single Sign-On supported, and\n *  - is Kerberos supported\n */\n#if defined(HAVE_GSSAPI_GSSAPI_H) || defined(HAVE_SSPI)\n#define PURPLE_SIPE_SSO_AND_KERBEROS 1\n#else\n#define PURPLE_SIPE_SSO_AND_KERBEROS 0\n#endif\n\n/*\n * SIPE core activity <-> Purple status mapping\n *\n * NOTE: this needs to be kept in sync with sipe_purple_status_types()\n */\nstatic const gchar * const activity_to_purple_map[SIPE_ACTIVITY_NUM_TYPES] = {\n/* SIPE_ACTIVITY_UNSET       */ \"unset\",     /* == purple_primitive_get_id_from_type(PURPLE_STATUS_UNSET) */\n/* SIPE_ACTIVITY_AVAILABLE   */ \"available\", /* == purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE) */\n/* SIPE_ACTIVITY_ONLINE      */ \"online\",\n/* SIPE_ACTIVITY_INACTIVE    */ \"idle\",\n/* SIPE_ACTIVITY_BUSY        */ \"busy\",\n/* SIPE_ACTIVITY_BUSYIDLE    */ \"busyidle\",\n/* SIPE_ACTIVITY_DND         */ \"do-not-disturb\",\n/* SIPE_ACTIVITY_BRB         */ \"be-right-back\",\n/* SIPE_ACTIVITY_AWAY        */ \"away\",      /* == purple_primitive_get_id_from_type(PURPLE_STATUS_AWAY) */\n/* SIPE_ACTIVITY_LUNCH       */ \"out-to-lunch\",\n/* SIPE_ACTIVITY_INVISIBLE   */ \"invisible\", /* == purple_primitive_get_id_from_type(PURPLE_STATUS_INVISIBLE) */\n/* SIPE_ACTIVITY_OFFLINE     */ \"offline\",   /* == purple_primitive_get_id_from_type(PURPLE_STATUS_OFFLINE) */\n/* SIPE_ACTIVITY_ON_PHONE    */ \"on-the-phone\",\n/* SIPE_ACTIVITY_IN_CONF     */ \"in-a-conference\",\n/* SIPE_ACTIVITY_IN_MEETING  */ \"in-a-meeting\",\n/* SIPE_ACTIVITY_OOF         */ \"out-of-office\",\n/* SIPE_ACTIVITY_URGENT_ONLY */ \"urgent-interruptions-only\",\n/* SIPE_ACTIVITY_IN_PRES     */ \"presenting\",\n/* SIPE_ACTIVIY_NUM_TYPES == 18 -> compare to sipe_purple_status_types() */\n};\n\nGHashTable *purple_token_map;\n\nstatic void sipe_purple_activity_init(void)\n{\n\tguint index;\n\n\tpurple_token_map = g_hash_table_new(g_str_hash, g_str_equal);\n\tfor (index = SIPE_ACTIVITY_UNSET;\n\t     index < SIPE_ACTIVITY_NUM_TYPES;\n\t     index++) {\n\t\tg_hash_table_insert(purple_token_map,\n\t\t\t\t    (gchar *) activity_to_purple_map[index],\n\t\t\t\t    GUINT_TO_POINTER(index));\n\t}\n}\n\nstatic void sipe_purple_activity_shutdown(void)\n{\n\tg_hash_table_destroy(purple_token_map);\n}\n\nconst gchar *sipe_purple_activity_to_token(guint type)\n{\n\treturn(activity_to_purple_map[type]);\n}\n\nguint sipe_purple_token_to_activity(const gchar *token)\n{\n\treturn(GPOINTER_TO_UINT(g_hash_table_lookup(purple_token_map, token)));\n}\n\ngchar *sipe_backend_version(void)\n{\n\treturn(g_strdup_printf(\"Purple/%s\", purple_core_get_version()));\n}\n\nconst char *sipe_purple_list_icon(SIPE_UNUSED_PARAMETER PurpleAccount *a,\n\t\t\t\t  SIPE_UNUSED_PARAMETER PurpleBuddy *b)\n{\n\treturn \"sipe\";\n}\n\ngchar *sipe_purple_status_text(PurpleBuddy *buddy)\n{\n\tPurpleStatus *status = purple_presence_get_active_status(purple_buddy_get_presence(buddy));\n\treturn sipe_core_buddy_status(PURPLE_BUDDY_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t      purple_buddy_get_name(buddy),\n\t\t\t\t      sipe_purple_token_to_activity(purple_status_get_id(status)),\n\t\t\t\t      purple_status_get_name(status));\n}\n\nvoid sipe_purple_tooltip_text(PurpleBuddy *buddy,\n\t\t\t      PurpleNotifyUserInfo *user_info,\n\t\t\t      SIPE_UNUSED_PARAMETER gboolean full)\n{\n\tPurplePresence *presence = purple_buddy_get_presence(buddy);\n\tsipe_core_buddy_tooltip_info(PURPLE_BUDDY_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t     purple_buddy_get_name(buddy),\n\t\t\t\t     purple_status_get_name(purple_presence_get_active_status(presence)),\n\t\t\t\t     purple_presence_is_online(presence),\n\t\t\t\t     (struct sipe_backend_buddy_tooltip *) user_info);\n}\n\nGList *sipe_purple_status_types(SIPE_UNUSED_PARAMETER PurpleAccount *acc)\n{\n\tPurpleStatusType *type;\n\tGList *types = NULL;\n\n\t/* Macro to reduce code repetition\n\t   Translators: noun */\n#define SIPE_ADD_STATUS(prim,activity,user) type = purple_status_type_new_with_attrs( \\\n\t\tprim, \\\n\t\tsipe_purple_activity_to_token(activity), \\\n\t\tsipe_core_activity_description(activity), \\\n\t\tTRUE, user, FALSE,          \\\n\t\tSIPE_PURPLE_STATUS_ATTR_ID_MESSAGE, _(\"Message\"), purple_value_new(PURPLE_TYPE_STRING), \\\n\t\tNULL);                      \\\n\ttypes = g_list_append(types, type);\n\n\t/*\n\t * NOTE: needs to be kept in sync with activity_to_purple_map[],\n\t *       i.e. for each SIPE_ACTIVITY_xxx value there must be an\n\t *       entry on this list.\n\t *\n\t * NOTE: the following code is sorted by purple primitive type not\n\t *       by SIPE_ACTIVITY_xxx value.\n\t */\n\n\t/*  1: Unset - special case: no entry needed */\n\n\t/*\n\t * Status list entries for primitive type AVAILABLE\n\t *\n\t *  2: Available */\n\tSIPE_ADD_STATUS(PURPLE_STATUS_AVAILABLE,\n\t\t\tSIPE_ACTIVITY_AVAILABLE,\n\t\t\tTRUE);\n\n\t/*  3: Online */\n\tSIPE_ADD_STATUS(PURPLE_STATUS_AVAILABLE,\n\t\t\tSIPE_ACTIVITY_ONLINE,\n\t\t\tFALSE);\n\n\t/*  4: Inactive (Idle) */\n\tSIPE_ADD_STATUS(PURPLE_STATUS_AVAILABLE,\n\t\t\tSIPE_ACTIVITY_INACTIVE,\n\t\t\tFALSE);\n\n\t/*\n\t * Status list entries for primitive type UNAVAILABLE\n\t *\n\t *  5: Busy */\n\tSIPE_ADD_STATUS(PURPLE_STATUS_UNAVAILABLE,\n\t\t\tSIPE_ACTIVITY_BUSY,\n\t\t\tTRUE);\n\n\t/*  6: Busy-Idle */\n\tSIPE_ADD_STATUS(PURPLE_STATUS_UNAVAILABLE,\n\t\t\tSIPE_ACTIVITY_BUSYIDLE,\n\t\t\tFALSE);\n\n\t/*  7: Do Not Disturb */\n\tSIPE_ADD_STATUS(PURPLE_STATUS_UNAVAILABLE,\n\t\t\tSIPE_ACTIVITY_DND,\n\t\t\tTRUE);\n\n\t/*  8: In a call */\n\tSIPE_ADD_STATUS(PURPLE_STATUS_UNAVAILABLE,\n\t\t\tSIPE_ACTIVITY_ON_PHONE,\n\t\t\tFALSE);\n\n\t/*  9: In a conference call */\n\tSIPE_ADD_STATUS(PURPLE_STATUS_UNAVAILABLE,\n\t\t\tSIPE_ACTIVITY_IN_CONF,\n\t\t\tFALSE);\n\n\t/* 10: In a meeting */\n\tSIPE_ADD_STATUS(PURPLE_STATUS_UNAVAILABLE,\n\t\t\tSIPE_ACTIVITY_IN_MEETING,\n\t\t\tFALSE);\n\n\t/* 11: Urgent interruptions only */\n\tSIPE_ADD_STATUS(PURPLE_STATUS_UNAVAILABLE,\n\t\t\tSIPE_ACTIVITY_URGENT_ONLY,\n\t\t\tFALSE);\n\n\t/* Presenting */\n\tSIPE_ADD_STATUS(PURPLE_STATUS_UNAVAILABLE,\n\t\t\tSIPE_ACTIVITY_IN_PRES,\n\t\t\tFALSE);\n\n\t/*\n\t * Status list entries for primitive type AWAY\n\t *\n\t * 12: Away - special case: needs to go first in the list as purple\n\t *            picks the first status with primitive type AWAY for idle\n\t */\n\tSIPE_ADD_STATUS(PURPLE_STATUS_AWAY,\n\t\t\tSIPE_ACTIVITY_AWAY,\n\t\t\tTRUE);\n\n\t/* 13: Be Right Back */\n\tSIPE_ADD_STATUS(PURPLE_STATUS_AWAY,\n\t\t\tSIPE_ACTIVITY_BRB,\n\t\t\tTRUE);\n\n\t/* 14: Out to lunch */\n\tSIPE_ADD_STATUS(PURPLE_STATUS_AWAY,\n\t\t\tSIPE_ACTIVITY_LUNCH,\n\t\t\tFALSE);\n\n\t/*\n\t * Status list entries for primitive type EXTENDED_AWAY\n\t *\n\t * 15: Out of office */\n\tSIPE_ADD_STATUS(PURPLE_STATUS_EXTENDED_AWAY,\n\t\t\tSIPE_ACTIVITY_OOF,\n\t\t\tFALSE);\n\n\t/*\n\t * Status list entries for primitive type INVISIBLE\n\t *\n\t * 16: Appear Offline */\n\tSIPE_ADD_STATUS(PURPLE_STATUS_INVISIBLE,\n\t\t\tSIPE_ACTIVITY_INVISIBLE,\n\t\t\tTRUE);\n\n\t/*\n\t * Status list entries for primitive type OFFLINE\n\t *\n\t * NOTE: this is always the last entry. Compare the number\n\t *       with the comment in activity_to_purple_map[].\n\t *\n\t * 17: Offline - special case: no message text */\n\ttype = purple_status_type_new(PURPLE_STATUS_OFFLINE,\n\t\t\t\t      NULL,\n\t\t\t\t      NULL,\n\t\t\t\t      TRUE);\n\ttypes = g_list_append(types, type);\n\n\treturn types;\n}\n\nGList *sipe_purple_blist_node_menu(PurpleBlistNode *node)\n{\n\tif (PURPLE_IS_BUDDY(node))\n\t{\n\t\treturn sipe_purple_buddy_menu((PurpleBuddy *) node);\n\t} else\n\tif (PURPLE_IS_CHAT(node))\n\t{\n\t\treturn sipe_purple_chat_menu((PurpleChat *)node);\n\t} else {\n\t\treturn NULL;\n\t}\n}\n\nstatic guint get_authentication_type(PurpleAccount *account)\n{\n\tconst gchar *auth = purple_account_get_string(account, \"authentication\", \"ntlm\");\n\n\t/* map option list to type - default is automatic */\n\tguint authentication_type = SIPE_AUTHENTICATION_TYPE_AUTOMATIC;\n\tif (sipe_strequal(auth, \"ntlm\")) {\n\t\tauthentication_type = SIPE_AUTHENTICATION_TYPE_NTLM;\n\t} else\n#if PURPLE_SIPE_SSO_AND_KERBEROS\n\tif (sipe_strequal(auth, \"krb5\")) {\n\t\tauthentication_type = SIPE_AUTHENTICATION_TYPE_KERBEROS;\n\t} else\n#endif\n\tif (sipe_strequal(auth, \"tls-dsk\")) {\n\t\tauthentication_type = SIPE_AUTHENTICATION_TYPE_TLS_DSK;\n\t}\n\n\treturn(authentication_type);\n}\n\nstatic gboolean get_sso_flag(PurpleAccount *account)\n{\n#if PURPLE_SIPE_SSO_AND_KERBEROS\n\t/*\n\t * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n\t *       SIPE that it is OK to use Single Sign-On or not.\n\t */\n\treturn(purple_account_get_bool(account, \"sso\", FALSE));\n#else\n\t(void) account; /* keep compiler happy */\n\treturn(FALSE);\n#endif\n}\n\nstatic gboolean get_dont_publish_flag(PurpleAccount *account)\n{\n\t/* default is to publish calendar information */\n\treturn(purple_account_get_bool(account, \"dont-publish\", FALSE));\n}\n\nstatic gboolean get_allow_web_photo_flag(PurpleAccount *account)\n{\n\t/* default is to not allow insecure download of buddy icons from web */\n\treturn purple_account_get_bool(account, \"allow-web-photo\", FALSE);\n}\n\nstatic void connect_to_core(PurpleConnection *gc,\n\t\t\t    PurpleAccount *account,\n\t\t\t    const gchar *password)\n{\n\tconst gchar *username  = purple_account_get_username(account);\n\tconst gchar *email     = purple_account_get_string(account, \"email\", NULL);\n\tconst gchar *email_url = purple_account_get_string(account, \"email_url\", NULL);\n\tconst gchar *transport = purple_account_get_string(account, \"transport\", \"auto\");\n\tstruct sipe_core_public *sipe_public;\n\tgchar **username_split;\n\tconst gchar *errmsg;\n\tguint transport_type;\n\tstruct sipe_backend_private *purple_private;\n\n\t/* username format: <username>,[<optional login>] */\n\tSIPE_DEBUG_INFO(\"sipe_purple_login: username '%s'\", username);\n\tusername_split = g_strsplit(username, \",\", 2);\n\n\tsipe_public = sipe_core_allocate(username_split[0],\n\t\t\t\t\t get_sso_flag(account),\n\t\t\t\t\t username_split[1],\n\t\t\t\t\t password,\n\t\t\t\t\t email,\n\t\t\t\t\t email_url,\n\t\t\t\t\t &errmsg);\n\tg_strfreev(username_split);\n\n\tif (!sipe_public) {\n\t\tpurple_connection_error(gc,\n\t\t\t\t\tPURPLE_CONNECTION_ERROR_INVALID_USERNAME,\n\t\t\t\t\terrmsg);\n\t\treturn;\n\t}\n\n\tsipe_public->backend_private = purple_private = g_new0(struct sipe_backend_private, 1);\n\tpurple_private->public = sipe_public;\n\tpurple_private->gc = gc;\n\tpurple_private->account = account;\n\n\tsipe_purple_chat_setup_rejoin(purple_private);\n\n\tSIPE_CORE_FLAG_UNSET(DONT_PUBLISH);\n\tif (get_dont_publish_flag(account))\n\t\tSIPE_CORE_FLAG_SET(DONT_PUBLISH);\n\tSIPE_CORE_FLAG_UNSET(ALLOW_WEB_PHOTO);\n\tif (get_allow_web_photo_flag(account))\n\t\tSIPE_CORE_FLAG_SET(ALLOW_WEB_PHOTO);\n\n\tpurple_connection_set_protocol_data(gc, sipe_public);\n\tpurple_connection_set_flags(gc,\n\t\t\t\t    purple_connection_get_flags(gc) |\n\t\t\t\t    PURPLE_CONNECTION_FLAG_HTML |\n\t\t\t\t    PURPLE_CONNECTION_FLAG_FORMATTING_WBFO |\n\t\t\t\t    PURPLE_CONNECTION_FLAG_NO_BGCOLOR |\n\t\t\t\t    PURPLE_CONNECTION_FLAG_NO_FONTSIZE |\n\t\t\t\t    PURPLE_CONNECTION_FLAG_NO_URLDESC |\n\t\t\t\t    PURPLE_CONNECTION_FLAG_ALLOW_CUSTOM_SMILEY);\n\tpurple_connection_set_display_name(gc, sipe_public->sip_name);\n\tpurple_connection_update_progress(gc, _(\"Connecting\"), 1, 2);\n\n\tusername_split = g_strsplit(purple_account_get_string(account, \"server\", \"\"), \":\", 2);\n\tif (sipe_strequal(transport, \"auto\")) {\n\t\ttransport_type = (username_split[0] == NULL) ?\n\t\t\tSIPE_TRANSPORT_AUTO : SIPE_TRANSPORT_TLS;\n\t} else if (sipe_strequal(transport, \"tls\")) {\n\t\ttransport_type = SIPE_TRANSPORT_TLS;\n\t} else {\n\t\ttransport_type = SIPE_TRANSPORT_TCP;\n\t}\n\tsipe_core_transport_sip_connect(sipe_public,\n\t\t\t\t\ttransport_type,\n\t\t\t\t\tget_authentication_type(account),\n\t\t\t\t\tusername_split[0],\n\t\t\t\t\tusername_split[0] ? username_split[1] : NULL);\n\tg_strfreev(username_split);\n}\n\nstatic void password_required_cb(PurpleConnection *gc,\n\t\t\t\t SIPE_UNUSED_PARAMETER PurpleRequestFields *fields)\n{\n#if !PURPLE_VERSION_CHECK(3,0,0)\n\tif (!PURPLE_CONNECTION_IS_VALID(gc)) {\n\t\treturn;\n\t}\n#endif\n\n\tpurple_connection_error(gc,\n\t\t\t\tPURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,\n\t\t\t\t_(\"Password required\"));\n}\n\nstatic void password_ok_cb(PurpleConnection *gc,\n\t\t\t   PurpleRequestFields *fields)\n{\n\tconst gchar *password;\n\n#if !PURPLE_VERSION_CHECK(3,0,0)\n\tif (!PURPLE_CONNECTION_IS_VALID(gc)) {\n\t\treturn;\n\t}\n#endif\n\n\tpassword = purple_request_fields_get_string(fields, \"password\");\n\n\tif (password && strlen(password)) {\n\t\tPurpleAccount *account = purple_connection_get_account(gc);\n\n\t\tif (purple_request_fields_get_bool(fields, \"remember\"))\n\t\t\tpurple_account_set_remember_password(account, TRUE);\n\t\tpurple_account_set_password(account, password\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t\t\t    , NULL, NULL\n#endif\n\t\t\t\t\t   );\n\n\t\t/* Now we have a password and we can connect */\n\t\tconnect_to_core(gc, account, password);\n\n\t} else\n\t\t/* reject an empty password */\n\t\tpassword_required_cb(gc, fields);\n}\n\nvoid sipe_purple_login(PurpleAccount *account)\n{\n\tPurpleConnection *gc = purple_account_get_connection(account);\n\tconst gchar *password = purple_connection_get_password(gc);\n\n\t/* Password required? */\n\tif (sipe_core_transport_sip_requires_password(get_authentication_type(account),\n\t\t\t\t\t\t      get_sso_flag(account)) &&\n\t    (!password || !strlen(password)))\n\t\t/* No password set - request one from user */\n\t\tpurple_account_request_password(account,\n\t\t\t\t\t\tG_CALLBACK(password_ok_cb),\n\t\t\t\t\t\tG_CALLBACK(password_required_cb),\n\t\t\t\t\t\tgc);\n\telse\n\t\t/* No password required or saved password - connect now */\n\t\tconnect_to_core(gc, account, password);\n\n}\n\nvoid sipe_purple_close(PurpleConnection *gc)\n{\n\tstruct sipe_core_public *sipe_public = PURPLE_GC_TO_SIPE_CORE_PUBLIC;\n\n\tif (sipe_public) {\n\t\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\n\t\tsipe_core_deallocate(sipe_public);\n\n\t\t/* anything left after that must be in pending state... */\n\t\tsipe_purple_dns_query_cancel_all(purple_private);\n\t\tsipe_purple_transport_close_all(purple_private);\n\n\t\tif (purple_private->roomlist_map)\n\t\t\tg_hash_table_destroy(purple_private->roomlist_map);\n\t\tsipe_purple_chat_destroy_rejoin(purple_private);\n\n\t\tif (purple_private->deferred_status_timeout)\n\t\t\tg_source_remove(purple_private->deferred_status_timeout);\n\t\tg_free(purple_private->deferred_status_note);\n\n\t\tg_free(purple_private);\n\t\tpurple_connection_set_protocol_data(gc, NULL);\n\t}\n}\n\nunsigned int sipe_purple_send_typing(PurpleConnection *gc,\n\t\t\t\t     const char *who,\n\t\t\t\t     PurpleIMTypingState state)\n{\n\tgboolean typing = (state == PURPLE_IM_TYPING);\n\n\t/* only enable this debug output while testing\n\t   SIPE_DEBUG_INFO(\"sipe_purple_send_typing: '%s' state %d\", who, state); */\n\n\t/*\n\t * libpurple calls this function with PURPLE_NOT_TYPING *after*\n\t * calling sipe_purple_send_im() with the message. This causes\n\t * SIPE core to send out two SIP messages to the same dialog in\n\t * short succession without waiting for the response to the first\n\t * one. Some servers then reject the first one with\n\t *\n\t *    SIP/2.0 500 Stale CSeq Value\n\t *\n\t * which triggers a \"message not delivered\" error for the user.\n\t *\n\t * Work around this by filtering out PURPLE_NOT_TYPING events.\n\t */\n\tif (state != PURPLE_IM_NOT_TYPING)\n\t\tsipe_core_user_feedback_typing(PURPLE_GC_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t\t       who,\n\t\t\t\t\t       typing);\n\n\t/* tell libpurple to send typing indications every 4 seconds */\n\treturn(typing ? 4 : 0);\n}\n\nvoid sipe_purple_get_info(PurpleConnection *gc, const char *who)\n{\n\tsipe_core_buddy_get_info(PURPLE_GC_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t who);\n}\n\nvoid sipe_purple_add_permit(PurpleConnection *gc, const char *name)\n{\n\tsipe_core_contact_allow_deny(PURPLE_GC_TO_SIPE_CORE_PUBLIC, name, TRUE);\n}\n\nvoid sipe_purple_add_deny(PurpleConnection *gc, const char *name)\n{\n\tsipe_core_contact_allow_deny(PURPLE_GC_TO_SIPE_CORE_PUBLIC, name, FALSE);\n}\n\nvoid sipe_purple_alias_buddy(PurpleConnection *gc, const char *name,\n\t\t\t     const char *alias)\n{\n\tsipe_core_group_set_alias(PURPLE_GC_TO_SIPE_CORE_PUBLIC, name, alias);\n}\n\nvoid sipe_purple_group_rename(PurpleConnection *gc, const char *old_name,\n\t\t\t      PurpleGroup *group,\n\t\t\t      SIPE_UNUSED_PARAMETER GList *moved_buddies)\n{\n\tsipe_core_group_rename(PURPLE_GC_TO_SIPE_CORE_PUBLIC,\n\t\t\t       old_name,\n\t\t\t       purple_group_get_name(group));\n}\n\nvoid sipe_purple_convo_closed(PurpleConnection *gc, const char *who)\n{\n\tsipe_core_im_close(PURPLE_GC_TO_SIPE_CORE_PUBLIC, who);\n}\n\nvoid sipe_purple_group_remove(PurpleConnection *gc, PurpleGroup *group)\n{\n\tsipe_core_group_remove(PURPLE_GC_TO_SIPE_CORE_PUBLIC,\n\t\t\t       purple_group_get_name(group));\n}\n\nGHashTable *\nsipe_purple_get_account_text_table(SIPE_UNUSED_PARAMETER PurpleAccount *account)\n{\n\tGHashTable *table;\n\ttable = g_hash_table_new(g_str_hash, g_str_equal);\n\tg_hash_table_insert(table, (char *)\"login_label\", (gpointer)_(\"user@company.com\"));\n\treturn table;\n}\n\n#ifdef HAVE_VV\n\nstatic void\nsipe_purple_sigusr1_handler(SIPE_UNUSED_PARAMETER int signum)\n{\n\tcapture_pipeline(\"PURPLE_SIPE_PIPELINE\");\n}\n\ngboolean sipe_purple_initiate_media(PurpleAccount *account, const char *who,\n\t\t\t\t    SIPE_UNUSED_PARAMETER PurpleMediaSessionType type)\n{\n\tsipe_core_media_initiate_call(PURPLE_ACCOUNT_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t      who,\n\t\t\t\t      (type & PURPLE_MEDIA_VIDEO));\n\treturn TRUE;\n}\n\nPurpleMediaCaps sipe_purple_get_media_caps(SIPE_UNUSED_PARAMETER PurpleAccount *account,\n\t\t\t\t\t   SIPE_UNUSED_PARAMETER const char *who)\n{\n\treturn   PURPLE_MEDIA_CAPS_AUDIO\n\t       | PURPLE_MEDIA_CAPS_AUDIO_VIDEO\n\t       | PURPLE_MEDIA_CAPS_MODIFY_SESSION;\n}\n#endif\n\n/* PurplePluginInfo function calls & data structure */\ngboolean sipe_purple_plugin_load(SIPE_UNUSED_PARAMETER PurplePlugin *plugin)\n{\n#ifdef HAVE_VV\n\t{\n\t\tstruct sigaction action;\n\t\tmemset(&action, 0, sizeof (action));\n\t\taction.sa_handler = sipe_purple_sigusr1_handler;\n\t\tsigaction(SIGUSR1, &action, NULL);\n\t}\n#endif\n\n\tsipe_purple_activity_init();\n\n\treturn TRUE;\n}\n\ngboolean sipe_purple_plugin_unload(SIPE_UNUSED_PARAMETER PurplePlugin *plugin)\n{\n#ifdef HAVE_VV\n\tstruct sigaction action;\n\tmemset(&action, 0, sizeof (action));\n\taction.sa_handler = SIG_DFL;\n\tsigaction(SIGUSR1, &action, NULL);\n#endif\n\n\tsipe_purple_activity_shutdown();\n\n\treturn TRUE;\n}\n\nstatic void sipe_purple_show_about_plugin(PurpleProtocolAction *action)\n{\n\tgchar *tmp = sipe_core_about();\n\tpurple_notify_formatted(SIPE_PURPLE_ACTION_TO_CONNECTION,\n\t\t\t\tNULL, \" \", NULL, tmp, NULL, NULL);\n\tg_free(tmp);\n}\n\nstatic void sipe_purple_join_conference_cb(PurpleConnection *gc,\n\t\t\t\t\t   PurpleRequestFields *fields)\n{\n\tGList *entries = purple_request_field_group_get_fields(purple_request_fields_get_groups(fields)->data);\n\n\tif (entries) {\n\t\tconst gchar *location = purple_request_fields_get_string(fields,\n\t\t\t\t\t\t\t\t\t \"meetingLocation\");\n\t\tconst gchar *organizer = purple_request_fields_get_string(fields,\n\t\t\t\t\t\t\t\t\t  \"meetingOrganizer\");\n\t\tconst gchar *meeting_id = purple_request_fields_get_string(fields,\n\t\t\t\t\t\t\t\t\t   \"meetingID\");\n\t\tsipe_core_conf_create(PURPLE_GC_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t      location,\n\t\t\t\t      organizer,\n\t\t\t\t      meeting_id);\n\t}\n}\n\n#ifdef HAVE_VV\n\nstatic void sipe_purple_phone_call_cb(PurpleConnection *gc,\n\t\t\t\t      PurpleRequestFields *fields)\n{\n\tGList *entries = purple_request_field_group_get_fields(purple_request_fields_get_groups(fields)->data);\n\n\tif (entries)\n\t\tsipe_core_media_phone_call(PURPLE_GC_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t\t   purple_request_fields_get_string(fields,\n\t\t\t\t\t\t\t\t\t    \"phoneNumber\"));\n}\n\nstatic void sipe_purple_phone_call(PurpleProtocolAction *action)\n{\n\tPurpleConnection *gc = SIPE_PURPLE_ACTION_TO_CONNECTION;\n\tPurpleRequestFields *fields;\n\tPurpleRequestFieldGroup *group;\n\tPurpleRequestField *field;\n\n\tfields = purple_request_fields_new();\n\tgroup = purple_request_field_group_new(NULL);\n\tpurple_request_fields_add_group(fields, group);\n\n\tfield = purple_request_field_string_new(\"phoneNumber\", _(\"Phone number\"), NULL, FALSE);\n\tpurple_request_field_group_add_field(group, field);\n\n\tpurple_request_fields(gc,\n\t\t\t      _(\"Call a phone number\"),\n\t\t\t      _(\"Call a phone number\"),\n\t\t\t      NULL,\n\t\t\t      fields,\n\t\t\t      _(\"_Call\"), G_CALLBACK(sipe_purple_phone_call_cb),\n\t\t\t      _(\"_Cancel\"), NULL,\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t      purple_request_cpar_from_connection(gc),\n#else\n\t\t\t      purple_connection_get_account(gc), NULL, NULL,\n#endif\n\t\t\t      gc);\n}\n\nstatic void sipe_purple_test_call(PurpleProtocolAction *action)\n{\n\tPurpleConnection *gc = SIPE_PURPLE_ACTION_TO_CONNECTION;\n\tsipe_core_media_test_call(PURPLE_GC_TO_SIPE_CORE_PUBLIC);\n}\n#endif\n\nstatic void sipe_purple_show_join_conference(PurpleProtocolAction *action)\n{\n\tPurpleConnection *gc = SIPE_PURPLE_ACTION_TO_CONNECTION;\n\tPurpleRequestFields *fields;\n\tPurpleRequestFieldGroup *group;\n\tPurpleRequestField *field;\n\n\tfields = purple_request_fields_new();\n\tgroup = purple_request_field_group_new(NULL);\n\tpurple_request_fields_add_group(fields, group);\n\n\tfield = purple_request_field_string_new(\"meetingLocation\", _(\"Meeting location\"), NULL, FALSE);\n\tpurple_request_field_group_add_field(group, field);\n\tfield = purple_request_field_label_new(\"separator\", _(\"Alternatively\"));\n\tpurple_request_field_group_add_field(group, field);\n\tfield = purple_request_field_string_new(\"meetingOrganizer\", _(\"Organizer email\"), NULL, FALSE);\n\tpurple_request_field_group_add_field(group, field);\n\tfield = purple_request_field_string_new(\"meetingID\", _(\"Meeting ID\"), NULL, FALSE);\n\tpurple_request_field_group_add_field(group, field);\n\n\tpurple_request_fields(gc,\n\t\t\t      _(\"Join conference\"),\n\t\t\t      _(\"Join scheduled conference\"),\n\t\t\t      _(\"Enter meeting location string you received in the invitation.\\n\"\n\t\t\t\t\"\\n\"\n\t\t\t\t\"Valid location will be something like\\n\"\n\t\t\t\t\"meet:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\t\t\t\t\"conf:sip:someone@company.com;gruu;opaque=app:conf:focus:id:abcdef1234\\n\"\n\t\t\t\t\"or\\n\"\n\t\t\t\t\"https://meet.company.com/someone/abcdef1234\"),\n\t\t\t      fields,\n\t\t\t      _(\"_Join\"), G_CALLBACK(sipe_purple_join_conference_cb),\n\t\t\t      _(\"_Cancel\"), NULL,\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t      purple_request_cpar_from_connection(gc),\n#else\n\t\t\t      purple_connection_get_account(gc), NULL, NULL,\n#endif\n\t\t\t      gc);\n}\n\nvoid sipe_purple_republish_calendar(PurpleAccount *account)\n{\n\tstruct sipe_core_public *sipe_public = PURPLE_ACCOUNT_TO_SIPE_CORE_PUBLIC;\n\tif (get_dont_publish_flag(account)) {\n\t\tsipe_backend_notify_error(sipe_public,\n\t\t\t\t\t  _(\"Publishing of calendar information has been disabled\"),\n\t\t\t\t\t  NULL);\n\t} else {\n\t\tsipe_core_update_calendar(sipe_public);\n\t}\n}\n\nstatic void sipe_purple_republish_calendar_action(PurpleProtocolAction *action)\n{\n\tPurpleConnection *gc = SIPE_PURPLE_ACTION_TO_CONNECTION;\n\tPurpleAccount *account = purple_connection_get_account(gc);\n\tsipe_purple_republish_calendar(account);\n}\n\nvoid sipe_purple_reset_status(PurpleAccount *account)\n{\n\tif (get_dont_publish_flag(account)) {\n\t\tsipe_backend_notify_error(PURPLE_ACCOUNT_TO_SIPE_CORE_PUBLIC,\n\t\t\t\t\t  _(\"Publishing of calendar information has been disabled\"),\n\t\t\t\t\t  NULL);\n\t} else {\n\t\tsipe_core_reset_status(PURPLE_ACCOUNT_TO_SIPE_CORE_PUBLIC);\n\t}\n}\n\nstatic void sipe_purple_reset_status_action(PurpleProtocolAction *action)\n{\n\tPurpleConnection *gc = SIPE_PURPLE_ACTION_TO_CONNECTION;\n\tPurpleAccount *account = purple_connection_get_account(gc);\n\tsipe_purple_reset_status(account);\n}\n\nGList *sipe_purple_actions()\n{\n\tGList *menu = NULL;\n\tPurpleProtocolAction *act;\n\n\tact = purple_protocol_action_new(_(\"About SIPE plugin...\"), sipe_purple_show_about_plugin);\n\tmenu = g_list_prepend(menu, act);\n\n\tact = purple_protocol_action_new(_(\"Contact search...\"), sipe_purple_show_find_contact);\n\tmenu = g_list_prepend(menu, act);\n\n#ifdef HAVE_VV\n\tact = purple_protocol_action_new(_(\"Call a phone number...\"), sipe_purple_phone_call);\n\tmenu = g_list_prepend(menu, act);\n\n\tact = purple_protocol_action_new(_(\"Test call\"), sipe_purple_test_call);\n\tmenu = g_list_prepend(menu, act);\n#endif\n\n\tact = purple_protocol_action_new(_(\"Join scheduled conference...\"), sipe_purple_show_join_conference);\n\tmenu = g_list_prepend(menu, act);\n\n\tact = purple_protocol_action_new(_(\"Republish Calendar\"), sipe_purple_republish_calendar_action);\n\tmenu = g_list_prepend(menu, act);\n\n\tact = purple_protocol_action_new(_(\"Reset status\"), sipe_purple_reset_status_action);\n\tmenu = g_list_prepend(menu, act);\n\n\treturn g_list_reverse(menu);\n}\n\nGList * sipe_purple_account_options()\n{\n\tPurpleAccountOption *option;\n\tGList *options = NULL;\n\n\t/**\n\t * When adding new string settings please make sure to keep these\n\t * in sync:\n\t *\n\t *     api/sipe-backend.h\n\t *     purple-settings.c:setting_name[]\n\t */\n\toption = purple_account_option_string_new(_(\"Server[:Port]\\n(leave empty for auto-discovery)\"), \"server\", \"\");\n\toptions = g_list_append(options, option);\n\n\toption = purple_account_option_list_new(_(\"Connection type\"), \"transport\", NULL);\n\tpurple_account_option_add_list_item(option, _(\"Auto\"), \"auto\");\n\tpurple_account_option_add_list_item(option, _(\"SSL/TLS\"), \"tls\");\n\tpurple_account_option_add_list_item(option, _(\"TCP\"), \"tcp\");\n\toptions = g_list_append(options, option);\n\n\t/*option = purple_account_option_bool_new(_(\"Publish status (note: everyone may watch you)\"), \"doservice\", TRUE);\n\tsipe_prpl_info.protocol_options = g_list_append(sipe_prpl_info.protocol_options, option);*/\n\n\toption = purple_account_option_string_new(_(\"User Agent\"), \"useragent\", \"\");\n\toptions = g_list_append(options, option);\n\n\toption = purple_account_option_list_new(_(\"Authentication scheme\"), \"authentication\", NULL);\n\tpurple_account_option_add_list_item(option, _(\"Auto\"), \"auto\");\n\tpurple_account_option_add_list_item(option, _(\"NTLM\"), \"ntlm\");\n#if PURPLE_SIPE_SSO_AND_KERBEROS\n\tpurple_account_option_add_list_item(option, _(\"Kerberos\"), \"krb5\");\n#endif\n\tpurple_account_option_add_list_item(option, _(\"TLS-DSK\"), \"tls-dsk\");\n\toptions = g_list_append(options, option);\n\n#if PURPLE_SIPE_SSO_AND_KERBEROS\n\t/*\n\t * When the user selects Single Sign-On then SIPE will ignore the\n\t * settings for \"login name\" and \"password\". Instead it will use the\n\t * default credentials provided by the OS.\n\t *\n\t * NOTE: the default must be *OFF*, i.e. it is up to the user to tell\n\t *       SIPE that it is OK to use Single Sign-On or not.\n\t *\n\t * Configurations that are known to support Single Sign-On:\n\t *\n\t *  - Windows, host joined to domain, SIPE with SSPI: NTLM\n\t *  - Windows, host joined to domain, SIPE with SSPI: Kerberos\n\t *  - SIPE with libkrb5, valid TGT in cache (kinit):  Kerberos\n\t */\n\toption = purple_account_option_bool_new(_(\"Use Single Sign-On\"), \"sso\", FALSE);\n\toptions = g_list_append(options, option);\n#endif\n\n\t/** Example (Exchange): https://server.company.com/EWS/Exchange.asmx\n\t *  Example (Domino)  : https://[domino_server]/[mail_database_name].nsf\n\t */\n\toption = purple_account_option_bool_new(_(\"Don't publish my calendar information\"), \"dont-publish\", FALSE);\n\toptions = g_list_append(options, option);\n\n\toption = purple_account_option_bool_new(_(\"Show profile pictures from web\\n(potentially dangerous)\"), \"allow-web-photo\", FALSE);\n\toptions = g_list_append(options, option);\n\n\toption = purple_account_option_string_new(_(\"Email services URL\\n(leave empty for auto-discovery)\"), \"email_url\", \"\");\n\toptions = g_list_append(options, option);\n\n\toption = purple_account_option_string_new(_(\"Email address\\n(if different from Username)\"), \"email\", \"\");\n\toptions = g_list_append(options, option);\n\n\t/** Example (Exchange): DOMAIN\\user  or  user@company.com\n\t *  Example (Domino)  : email_address\n\t */\n\toption = purple_account_option_string_new(_(\"Email login\\n(if different from Login)\"), \"email_login\", \"\");\n\toptions = g_list_append(options, option);\n\n\toption = purple_account_option_string_new(_(\"Email password\\n(if different from Password)\"), \"email_password\", \"\");\n\tpurple_account_option_string_set_masked(option, TRUE);\n\toptions = g_list_append(options, option);\n\n\t/** Example (federated domain): company.com      (i.e. ocschat@company.com)\n\t *  Example (non-default user): user@company.com\n\t */\n\toption = purple_account_option_string_new(_(\"Group Chat Proxy\\n   company.com  or  user@company.com\\n(leave empty to determine from Username)\"), \"groupchat_user\", \"\");\n\toptions = g_list_append(options, option);\n\n#ifdef HAVE_APPSHARE\n\toption = purple_account_option_string_new(_(\"Remote desktop client\"), \"rdp_client\", \"\");\n\toptions = g_list_append(options, option);\n#endif\n\n#ifdef HAVE_SRTP\n\toption = purple_account_option_list_new(_(\"Media encryption\"), \"encryption-policy\", NULL);\n\tpurple_account_option_add_list_item(option, _(\"Obey server policy\"), \"obey-server\");\n\tpurple_account_option_add_list_item(option, _(\"Always\"), \"required\");\n\tpurple_account_option_add_list_item(option, _(\"Optional\"), \"optional\");\n\tpurple_account_option_add_list_item(option, _(\"Disabled\"), \"disabled\");\n\toptions = g_list_append(options, option);\n#endif\n\n\treturn options;\n}\n\ngpointer sipe_purple_user_split()\n{\n\tPurpleAccountUserSplit *split =\n\t\tpurple_account_user_split_new(\n\t\t\t_(\"Login\\n   user  or  DOMAIN\\\\user  or\\n   user@company.com\"),\n\t\t\t/*\n\t\t\t * pidgin works fine with NULL as default\n\t\t\t * finch returns string \"(null)\" for NULL\n\t\t\t */\n\t\t\t\"\",\n\t\t\t',');\n\tpurple_account_user_split_set_reverse(split, FALSE);\n\n\treturn split;\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-plugin.c",
    "content": "/**\n * @file purple-plugin.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n\n/* Flag needed for correct version of PURPLE_INIT_PLUGIN() */\n#ifndef PURPLE_PLUGINS\n#define PURPLE_PLUGINS\n#endif\n\n/* for LOCALEDIR\n * as it's determined on runtime, as Pidgin installation can be anywhere.\n */\n#ifdef _WIN32\n#include \"win32/win32dep.h\"\n#endif\n\n#include \"accountopt.h\"\n#include \"prpl.h\"\n\n#include \"sipe-core.h\"\n\n#define _PurpleMessageFlags PurpleMessageFlags\n#include \"purple-private.h\"\n\n#ifdef HAVE_DBUS\n#include \"purple-dbus.h\"\n#endif\n\n#if !PURPLE_VERSION_CHECK(2,7,0)\n#error purple >= 2.7.0 is required to build SIPE\n#endif\n\nstatic int sipe_purple_send_im(PurpleConnection *gc,\n\t\t\t       const char *who,\n\t\t\t       const char *what,\n\t\t\t       SIPE_UNUSED_PARAMETER PurpleMessageFlags flags)\n{\n\tsipe_core_im_send(PURPLE_GC_TO_SIPE_CORE_PUBLIC, who, what);\n\treturn 1;\n}\n\n/*\n * Simplistic source upward compatibility path for newer libpurple APIs\n *\n * Usually we compile with -Werror=missing-field-initializers if GCC supports\n * it. But that means that the compilation of this structure can fail if the\n * newer API has added additional plugin callbacks. For the benefit of the\n * user we downgrade it to a warning here.\n *\n * Diagnostic #pragma was added in GCC 4.2.0\n * Diagnostic push/pop was added in GCC 4.6.0\n */\n#ifdef __GNUC__\n#if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) || (__GNUC__ >= 5)\n#if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ >= 5)\n#pragma GCC diagnostic push\n#endif\n#pragma GCC diagnostic warning \"-Wmissing-field-initializers\"\n#endif\n#endif\nstatic PurplePluginProtocolInfo sipe_prpl_info =\n{\n\tSIPE_PURPLE_PROTOCOL_OPTIONS,\n\tNULL,\t\t\t\t\t/* user_splits */\n\tNULL,\t\t\t\t\t/* protocol_options */\n\tNO_BUDDY_ICONS,\t\t\t\t/* icon_spec */\n\tsipe_purple_list_icon,\t\t\t/* list_icon */\n\tNULL,\t\t\t\t\t/* list_emblems */\n\tsipe_purple_status_text,\t\t/* status_text */\n\tsipe_purple_tooltip_text,\t\t/* tooltip_text */\t// add custom info to contact tooltip\n\tsipe_purple_status_types,\t\t/* away_states */\n\tsipe_purple_blist_node_menu,\t\t/* blist_node_menu */\n\tsipe_purple_chat_info,\t\t\t/* chat_info */\n\tsipe_purple_chat_info_defaults,\t\t/* chat_info_defaults */\n\tsipe_purple_login,\t\t\t/* login */\n\tsipe_purple_close,\t\t\t/* close */\n\tsipe_purple_send_im,\t\t\t/* send_im */\n\tNULL,\t\t\t\t\t/* set_info */\t\t// TODO maybe\n\tsipe_purple_send_typing,\t\t/* send_typing */\n\tsipe_purple_get_info,\t\t\t/* get_info */\n\tsipe_purple_set_status,\t\t\t/* set_status */\n\tsipe_purple_set_idle,\t\t\t/* set_idle */\n\tNULL,\t\t\t\t\t/* change_passwd */\n\tsipe_purple_add_buddy,\t\t\t/* add_buddy */\n\tNULL,\t\t\t\t\t/* add_buddies */\n\tsipe_purple_remove_buddy,\t\t/* remove_buddy */\n\tNULL,\t\t\t\t\t/* remove_buddies */\n\tsipe_purple_add_permit,\t\t\t/* add_permit */\n\tsipe_purple_add_deny,\t\t\t/* add_deny */\n\tsipe_purple_add_deny,\t\t\t/* rem_permit */\n\tsipe_purple_add_permit,\t\t\t/* rem_deny */\n\tNULL,\t\t\t\t\t/* set_permit_deny */\n\tsipe_purple_chat_join,\t\t\t/* join_chat */\n\tNULL,\t\t\t\t\t/* reject_chat */\n\tNULL,\t\t\t\t\t/* get_chat_name */\n\tsipe_purple_chat_invite,\t\t/* chat_invite */\n\tsipe_purple_chat_leave,\t\t\t/* chat_leave */\n\tNULL,\t\t\t\t\t/* chat_whisper */\n\tsipe_purple_chat_send,\t\t\t/* chat_send */\n\tNULL,\t\t\t\t\t/* keepalive */\n\tNULL,\t\t\t\t\t/* register_user */\n\tNULL,\t\t\t\t\t/* get_cb_info */\t// deprecated\n\tNULL,\t\t\t\t\t/* get_cb_away */\t// deprecated\n\tsipe_purple_alias_buddy,\t\t/* alias_buddy */\n\tsipe_purple_group_buddy,\t\t/* group_buddy */\n\tsipe_purple_group_rename,\t\t/* rename_group */\n\tNULL,\t\t\t\t\t/* buddy_free */\n\tsipe_purple_convo_closed,\t\t/* convo_closed */\n\tpurple_normalize_nocase,\t\t/* normalize */\n\tNULL,\t\t\t\t\t/* set_buddy_icon */\n\tsipe_purple_group_remove,\t\t/* remove_group */\n\tNULL,\t\t\t\t\t/* get_cb_real_name */\t// TODO?\n\tNULL,\t\t\t\t\t/* set_chat_topic */\n\tNULL,\t\t\t\t\t/* find_blist_chat */\n\tsipe_purple_roomlist_get_list,\t\t/* roomlist_get_list */\n\tsipe_purple_roomlist_cancel,\t\t/* roomlist_cancel */\n\tNULL,\t\t\t\t\t/* roomlist_expand_category */\n\tNULL,\t\t\t\t\t/* can_receive_file */\n\tsipe_purple_ft_send_file,\t\t/* send_file */\n\tNULL,\t\t\t\t\t/* new_xfer */\n\tNULL,\t\t\t\t\t/* offline_message */\n\tNULL,\t\t\t\t\t/* whiteboard_prpl_ops */\n\tNULL,\t\t\t\t\t/* send_raw */\n\tNULL,\t\t\t\t\t/* roomlist_room_serialize */\n\tNULL,\t\t\t\t\t/* unregister_user */\n\tNULL,\t\t\t\t\t/* send_attention */\n\tNULL,\t\t\t\t\t/* get_attention_types */\n\tsizeof(PurplePluginProtocolInfo),       /* struct_size */\n\tsipe_purple_get_account_text_table,\t/* get_account_text_table */\n#ifdef HAVE_VV\n\tsipe_purple_initiate_media,\t\t/* initiate_media */\n\tsipe_purple_get_media_caps,\t\t/* get_media_caps */\n#else\n\tNULL,\t\t\t\t\t/* initiate_media */\n\tNULL,\t\t\t\t\t/* get_media_caps */\n#endif\n\tNULL,\t\t\t\t\t/* get_moods */\n\tNULL,\t\t\t\t\t/* set_public_alias */\n\tNULL,\t\t\t\t\t/* get_public_alias */\n#if PURPLE_VERSION_CHECK(2,8,0)\n\tNULL,\t\t\t\t\t/* add_buddy_with_invite */\n\tNULL,\t\t\t\t\t/* add_buddies_with_invite */\n#endif\n#if PURPLE_VERSION_CHECK(2,14,0)\n\tNULL,\t\t\t\t\t/* get_cb_alias */\n#endif\n};\n#ifdef __GNUC__\n#if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ >= 5)\n#pragma GCC diagnostic pop\n#endif\n#endif\n/* Original GCC error checking restored from here on... (see above) */\n\n/* PurplePluginInfo function calls & data structure */\nstatic void sipe_purple_plugin_destroy(SIPE_UNUSED_PARAMETER PurplePlugin *plugin)\n{\n\tGList *entry;\n\n\tsipe_core_destroy();\n\n\tentry = sipe_prpl_info.protocol_options;\n\twhile (entry) {\n\t\tpurple_account_option_destroy(entry->data);\n\t\tentry = g_list_delete_link(entry, entry);\n\t}\n\tsipe_prpl_info.protocol_options = NULL;\n\n\tentry = sipe_prpl_info.user_splits;\n\twhile (entry) {\n\t\tpurple_account_user_split_destroy(entry->data);\n\t\tentry = g_list_delete_link(entry, entry);\n\t}\n\tsipe_prpl_info.user_splits = NULL;\n}\n\nstatic gboolean plugin_load(PurplePlugin *plugin)\n{\n#ifdef HAVE_DBUS\n\tif (purple_dbus_get_init_error() == NULL) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_purple_plugin_load: registering D-Bus bindings\");\n\t\tpurple_dbus_register_bindings(plugin, sipe_purple_dbus_bindings);\n\t}\n#endif\n\n\treturn sipe_purple_plugin_load(plugin);\n}\n\nstatic GList *purple_actions(SIPE_UNUSED_PARAMETER PurplePlugin *plugin,\n\t\t\t     SIPE_UNUSED_PARAMETER gpointer context)\n{\n\treturn sipe_purple_actions();\n}\n\nstatic PurplePluginInfo sipe_purple_info = {\n\tPURPLE_PLUGIN_MAGIC,\n\tPURPLE_MAJOR_VERSION,\n\tPURPLE_MINOR_VERSION,\n\tPURPLE_PLUGIN_PROTOCOL,                           /**< type           */\n\tNULL,                                             /**< ui_requirement */\n\t0,                                                /**< flags          */\n\tNULL,                                             /**< dependencies   */\n\tPURPLE_PRIORITY_DEFAULT,                          /**< priority       */\n\tSIPE_PURPLE_PLUGIN_ID,                            /**< id             */\n\tSIPE_PURPLE_PLUGIN_NAME,                          /**< name           */\n\tPACKAGE_VERSION,                                  /**< version        */\n\tSIPE_PURPLE_PLUGIN_SUMMARY,                       /**< summary        */\n\tSIPE_PURPLE_PLUGIN_DESCRIPTION,                   /**< description    */\n\tSIPE_PURPLE_PLUGIN_AUTHORS,                       /**< authors        */\n\tPACKAGE_URL,                                      /**< homepage       */\n\tplugin_load,                                      /**< load           */\n\tsipe_purple_plugin_unload,                        /**< unload         */\n\tsipe_purple_plugin_destroy,                       /**< destroy        */\n\tNULL,                                             /**< ui_info        */\n\t&sipe_prpl_info,                                  /**< extra_info     */\n\tNULL,\n\tpurple_actions,\n\tNULL,\n\tNULL,\n\tNULL,\n\tNULL\n};\n\nstatic void sipe_purple_init_plugin(PurplePlugin *plugin)\n{\n\t/* This needs to be called first */\n\tsipe_core_init(LOCALEDIR);\n\n\tpurple_plugin_register(plugin);\n\n\tsipe_prpl_info.user_splits = g_list_append(sipe_prpl_info.user_splits,\n\t\t\t\t\t\t   sipe_purple_user_split());\n\n\tsipe_prpl_info.protocol_options = sipe_purple_account_options();\n}\n\n/* This macro makes the code a purple plugin */\nPURPLE_INIT_PLUGIN(sipe, sipe_purple_init_plugin, sipe_purple_info);\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-plugin3.c",
    "content": "/**\n * @file purple-plugin3.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2015-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n#include <gmodule.h>\n\n#include \"protocol.h\"\n\n#include \"purple-private.h\"\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n\n#define SIPE_TYPE_PROTOCOL (sipe_protocol_get_type())\n\ntypedef struct _SipeProtocol {\n\tPurpleProtocol parent;\n} SipeProtocol;\n\ntypedef struct _SipeProtocolClass {\n\tPurpleProtocolClass parent_class;\n} SipeProtocolClass;\n\nG_MODULE_EXPORT GType sipe_protocol_get_type(void);\n\nstatic void\nsipe_protocol_class_init(SipeProtocolClass *klass)\n{\n\tPurpleProtocolClass *protocol_class = PURPLE_PROTOCOL_CLASS(klass);\n\n\tprotocol_class->login = sipe_purple_login;\n\tprotocol_class->close = sipe_purple_close;\n\tprotocol_class->status_types = sipe_purple_status_types;\n\tprotocol_class->list_icon = sipe_purple_list_icon;\n}\n\nstatic void\nsipe_protocol_class_finalize(SIPE_UNUSED_PARAMETER SipeProtocolClass *klass)\n{\n}\n\nstatic void\nsipe_protocol_init(SipeProtocol *self)\n{\n\tPurpleProtocol *protocol = PURPLE_PROTOCOL(self);\n\n\tsipe_core_init(LOCALEDIR);\n\n\tprotocol->id = SIPE_PURPLE_PLUGIN_ID;\n\tprotocol->name = SIPE_PURPLE_PLUGIN_NAME;\n\tprotocol->options = SIPE_PURPLE_PROTOCOL_OPTIONS;\n\tprotocol->user_splits = g_list_append(NULL, sipe_purple_user_split());\n\tprotocol->account_options = sipe_purple_account_options();\n}\n\nstatic GList *\nget_actions(SIPE_UNUSED_PARAMETER PurpleConnection *gc)\n{\n\treturn sipe_purple_actions();\n}\n\nstatic void\nsipe_protocol_client_iface_init(PurpleProtocolClientInterface *client_iface,\n\t\t\t\tSIPE_UNUSED_PARAMETER void *unused)\n{\n\tclient_iface->get_actions = get_actions;\n\tclient_iface->status_text = sipe_purple_status_text;\n\tclient_iface->tooltip_text = sipe_purple_tooltip_text;\n\tclient_iface->blist_node_menu = sipe_purple_blist_node_menu;\n\tclient_iface->convo_closed = sipe_purple_convo_closed;\n\tclient_iface->normalize = purple_normalize_nocase;\n\tclient_iface->get_account_text_table = sipe_purple_get_account_text_table;\n}\n\nstatic void\nsipe_protocol_server_iface_init(PurpleProtocolServerInterface *server_iface,\n\t\t\t\tSIPE_UNUSED_PARAMETER void *unused)\n{\n\tserver_iface->get_info = sipe_purple_get_info;\n\tserver_iface->set_status = sipe_purple_set_status;\n\tserver_iface->set_idle = sipe_purple_set_idle;\n\tserver_iface->add_buddy = sipe_purple_add_buddy;\n\tserver_iface->remove_buddy = sipe_purple_remove_buddy;\n\tserver_iface->alias_buddy = sipe_purple_alias_buddy;\n\tserver_iface->group_buddy = sipe_purple_group_buddy;\n\tserver_iface->rename_group = sipe_purple_group_rename;\n\tserver_iface->remove_group = sipe_purple_group_remove;\n}\n\nstatic int\nsend_im(PurpleConnection *gc, PurpleMessage *msg)\n{\n\tsipe_core_im_send(PURPLE_GC_TO_SIPE_CORE_PUBLIC,\n\t\t\t  purple_message_get_recipient(msg),\n\t\t\t  purple_message_get_contents(msg));\n\treturn 1;\n}\n\nstatic void\nsipe_protocol_im_iface_init(PurpleProtocolIMInterface *im_iface,\n\t\t\t    SIPE_UNUSED_PARAMETER void *unused)\n{\n\tim_iface->send = send_im;\n\tim_iface->send_typing = sipe_purple_send_typing;\n}\n\nstatic void\nsipe_protocol_chat_iface_init(PurpleProtocolChatInterface *chat_iface,\n\t\t\t      SIPE_UNUSED_PARAMETER void *unused)\n{\n\tchat_iface->info = sipe_purple_chat_info;\n\tchat_iface->info_defaults = sipe_purple_chat_info_defaults;\n\tchat_iface->join = sipe_purple_chat_join;\n\tchat_iface->invite = sipe_purple_chat_invite;\n\tchat_iface->leave = sipe_purple_chat_leave;\n\tchat_iface->send = sipe_purple_chat_send;\n}\n\nstatic void\nsipe_protocol_privacy_iface_init(PurpleProtocolPrivacyInterface *privacy_iface,\n\t\t\t\t SIPE_UNUSED_PARAMETER void *unused)\n{\n\tprivacy_iface->add_permit = sipe_purple_add_permit;\n\tprivacy_iface->add_deny = sipe_purple_add_deny;\n\tprivacy_iface->rem_permit = sipe_purple_add_deny;\n\tprivacy_iface->rem_deny = sipe_purple_add_permit;\n}\n\nstatic void\nsipe_protocol_xfer_iface_init(PurpleProtocolXferInterface *xfer_iface,\n\t\t\t      SIPE_UNUSED_PARAMETER void *unused)\n{\n\txfer_iface->send_file = sipe_purple_ft_send_file;\n}\n\nstatic void\nsipe_protocol_roomlist_iface_init(PurpleProtocolRoomlistInterface *roomlist_iface,\n\t\t\t\t  SIPE_UNUSED_PARAMETER void *unused)\n{\n\troomlist_iface->get_list = sipe_purple_roomlist_get_list;\n\troomlist_iface->cancel = sipe_purple_roomlist_cancel;\n}\n\n#ifdef HAVE_VV\nstatic void\nsipe_protocol_media_iface_init(PurpleProtocolMediaInterface *media_iface,\n\t\t\t       SIPE_UNUSED_PARAMETER void *unused)\n{\n\tmedia_iface->initiate_session = sipe_purple_initiate_media;\n\tmedia_iface->get_caps = sipe_purple_get_media_caps;\n}\n#endif /* HAVE_VV */\n\nG_DEFINE_DYNAMIC_TYPE_EXTENDED(\n\tSipeProtocol, sipe_protocol, PURPLE_TYPE_PROTOCOL, 0,\n\n\tG_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_CLIENT,\n\t\t\t\t      sipe_protocol_client_iface_init)\n\tG_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_SERVER,\n\t\t\t\t      sipe_protocol_server_iface_init)\n\tG_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_IM,\n\t\t\t\t      sipe_protocol_im_iface_init)\n\tG_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_CHAT,\n\t\t\t\t      sipe_protocol_chat_iface_init)\n\tG_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_PRIVACY,\n\t\t\t\t      sipe_protocol_privacy_iface_init)\n\tG_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_XFER,\n\t\t\t\t      sipe_protocol_xfer_iface_init)\n\tG_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_ROOMLIST,\n\t\t\t\t      sipe_protocol_roomlist_iface_init)\n#ifdef HAVE_VV\n\tG_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_MEDIA,\n\t\t\t\t      sipe_protocol_media_iface_init)\n#endif /* HAVE_VV */\n)\n\nstatic PurplePluginInfo *\nplugin_query(SIPE_UNUSED_PARAMETER GError **error)\n{\n\tgchar ** authors = g_strsplit(SIPE_PURPLE_PLUGIN_AUTHORS, \", \", -1);\n\tPurplePluginInfo *info = purple_plugin_info_new(\n\t\t\t\"id\", SIPE_PURPLE_PLUGIN_ID,\n\t\t\t\"name\", SIPE_PURPLE_PLUGIN_NAME,\n\t\t\t\"version\", PACKAGE_VERSION,\n\t\t\t\"category\", \"Protocol\",\n\t\t\t\"summary\", SIPE_PURPLE_PLUGIN_SUMMARY,\n\t\t\t\"description\", SIPE_PURPLE_PLUGIN_DESCRIPTION,\n\t\t\t\"authors\", authors,\n\t\t\t\"website\", PACKAGE_URL,\n\t\t\t\"abi-version\", PURPLE_ABI_VERSION,\n\t\t\t\"flags\", PURPLE_PLUGIN_INFO_FLAGS_AUTO_LOAD,\n\t\t\tNULL);\n\n\tg_strfreev(authors);\n\n\treturn info;\n}\n\nstatic PurpleProtocol *sipe_protocol = NULL;\n\nstatic gboolean\nplugin_load(PurplePlugin *plugin, GError **error)\n{\n\tsipe_protocol_register_type(G_TYPE_MODULE(plugin));\n\n\tsipe_purple_xfer_register(G_TYPE_MODULE(plugin));\n\n\tsipe_protocol = purple_protocols_add(SIPE_TYPE_PROTOCOL, error);\n\tif (!sipe_protocol) {\n\t\treturn FALSE;\n\t}\n\n\tif (!sipe_purple_plugin_load(plugin)) {\n\t\treturn FALSE;\n\t}\n\n\treturn TRUE;\n}\n\nstatic gboolean\nplugin_unload(PurplePlugin *plugin, GError **error)\n{\n\tsipe_purple_plugin_unload(plugin);\n\n\tif (!purple_protocols_remove(sipe_protocol, error)) {\n\t\treturn FALSE;\n\t}\n\n\treturn TRUE;\n}\n\nPURPLE_PLUGIN_INIT(sipe, plugin_query, plugin_load, plugin_unload);\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-private.h",
    "content": "/**\n * @file purple-private.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include \"version.h\"\n\n#define SIPE_PURPLE_PLUGIN_ID \"prpl-sipe\"\n#define SIPE_PURPLE_PLUGIN_NAME \"Office Communicator\"\n\n#define SIPE_PURPLE_PLUGIN_SUMMARY \\\n\t\"Microsoft Office Communicator Protocol Plugin\"\n\n#define SIPE_PURPLE_PLUGIN_DESCRIPTION \\\n\t\"A plugin for the extended SIP/SIMPLE protocol used by \" \\\n\t\"Microsoft Live/Office Communications/Lync Server (LCS2005/OCS2007+)\"\n\n#define SIPE_PURPLE_PLUGIN_AUTHORS \\\n\t\"Stefan Becker <chemobejk@gmail.com>, \" \\\n\t\"Jakub Adam <jakub.adam@ktknet.cz>, \" \\\n\t\"Anibal Avelar <avelar@gmail.com> (retired), \" \\\n\t\"pier11 <pier11@operamail.com> (retired), \" \\\n\t\"Gabriel Burt <gburt@novell.com> (retired)\"\n\n#define SIPE_PURPLE_PROTOCOL_OPTIONS OPT_PROTO_CHAT_TOPIC | OPT_PROTO_PASSWORD_OPTIONAL\n\n#if PURPLE_VERSION_CHECK(3,0,0)\n#include \"conversationtypes.h\" /* PurpleIMTypingState */\n#include \"plugins.h\"           /* PurplePlugin */\n\n/* Forward declarations */\nstruct _PurpleProtocolAction;\nstruct _PurpleProtocolXfer;\n#else\n#include \"conversation.h\"      /* PurpleTypingState */\n#include \"plugin.h\"            /* PurplePlugin */\n#define PurpleIMTypingState PurpleTypingState\n#define _PurpleProtocolAction _PurplePluginAction\n\n/* Forward declarations */\nstruct _PurplePluginAction;\n#endif\n\n/* Forward declarations */\nstruct sipe_chat_session;\nstruct sipe_core_public;\nstruct _PurpleAccount;\nstruct _PurpleBlistNode;\nstruct _PurpleBuddy;\nstruct _PurpleChat;\nstruct _PurpleConnection;\nstruct _PurpleConversation;\nstruct _PurpleGroup;\nstruct _PurpleMessage;\nstruct _PurpleNotifyUserInfo;\nstruct _PurpleRoomlist;\nstruct _PurpleStatus;\nstruct _PurpleXfer;\n\n#ifndef _PurpleMessageFlags\n#define _PurpleMessageFlags int\n#endif\n\nstruct sipe_backend_private {\n\tstruct sipe_core_public *public;\n\tstruct _PurpleConnection *gc;\n\tstruct _PurpleAccount *account;\n\tstruct _PurpleRoomlist *roomlist;\n\t/* see sipe_backend_chat_create() */\n\tstruct sipe_chat_session *adium_chat_session;\n\tGHashTable *roomlist_map; /* name -> uri */\n\tGList *rejoin_chats;\n\tGSList *transports;\n\tGSList *dns_queries;\n\n\t/* work around broken libpurple idle notification */\n\tgchar *deferred_status_note;\n\tguint  deferred_status_activity;\n\tguint  deferred_status_timeout;\n\n\t/* flags */\n\tgboolean status_changed_by_core; /* status changed by core */\n\tgboolean user_is_not_idle;       /* user came back online */\n};\n\nstruct sipe_backend_fd {\n\tint fd;\n};\n\n/* Status attributes */\n#define SIPE_PURPLE_STATUS_ATTR_ID_MESSAGE \"message\"\n\nconst gchar *sipe_purple_activity_to_token(guint type);\nguint sipe_purple_token_to_activity(const gchar *token);\n\n/* DNS queries */\nvoid sipe_purple_dns_query_cancel_all(struct sipe_backend_private *purple_private);\n\n/**\n * Initiates outgoing file transfer, sending @c file to remote peer identified\n * by @c who.\n *\n * @param gc   a PurpleConnection\n * @param who  string identifying receiver of the file\n * @param file local file system path of the file to send\n */\nvoid sipe_purple_ft_send_file(\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t      struct _PurpleProtocolXfer *xfer,\n#endif\n\t\t\t      struct _PurpleConnection *gc,\n\t\t\t      const char *who,\n\t\t\t      const char *file);\n\nvoid sipe_purple_xfer_register(GTypeModule *module);\n\n/* libpurple chat callbacks */\n#define SIPE_PURPLE_COMPONENT_KEY_CONVERSATION \"_conv\"\n\nstruct sipe_chat_session *sipe_purple_chat_get_session(struct _PurpleConversation *conv);\nvoid sipe_purple_chat_setup_rejoin(struct sipe_backend_private *purple_private);\nvoid sipe_purple_chat_destroy_rejoin(struct sipe_backend_private *purple_private);\nvoid sipe_purple_chat_invite(struct _PurpleConnection *gc,\n\t\t\t     int id,\n\t\t\t     const char *message,\n\t\t\t     const char *name);\nvoid sipe_purple_chat_leave(struct _PurpleConnection *gc, int id);\nint sipe_purple_chat_send(struct _PurpleConnection *gc,\n\t\t\t  int id,\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t  struct _PurpleMessage *msg);\n#else\n\t\t\t  const char *what,\n\t\t\t  _PurpleMessageFlags flags);\n#endif\nGList *sipe_purple_chat_menu(struct _PurpleChat *chat);\n\n/* libpurple chat room callbacks */\nGList *sipe_purple_chat_info(struct _PurpleConnection *gc);\nGHashTable *sipe_purple_chat_info_defaults(struct _PurpleConnection *gc,\n\t\t\t\t\t   const char *chat_name);\nvoid sipe_purple_chat_join(struct _PurpleConnection *gc, GHashTable *data);\nstruct _PurpleRoomlist *sipe_purple_roomlist_get_list(struct _PurpleConnection *gc);\nvoid sipe_purple_roomlist_cancel(struct _PurpleRoomlist *list);\n\n/* libpurple buddy callbacks */\n#ifdef PURPLE_VERSION_CHECK\nvoid sipe_purple_add_buddy(struct _PurpleConnection *gc,\n\t\t\t   struct _PurpleBuddy *buddy,\n\t\t\t   struct _PurpleGroup *group\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t   , const gchar *message\n#endif\n);\n#endif\nvoid sipe_purple_remove_buddy(struct _PurpleConnection *gc,\n\t\t\t      struct _PurpleBuddy *buddy,\n\t\t\t      struct _PurpleGroup *group);\nvoid sipe_purple_group_buddy(struct _PurpleConnection *gc,\n\t\t\t     const char *who,\n\t\t\t     const char *old_group_name,\n\t\t\t     const char *new_group_name);\nGList *sipe_purple_buddy_menu(struct _PurpleBuddy *buddy);\n\n/* libpurple search callbacks */\nvoid sipe_purple_show_find_contact(struct _PurpleProtocolAction *action);\n\n/* libpurple status callbacks */\nvoid sipe_purple_set_status(struct _PurpleAccount *account,\n\t\t\t    struct _PurpleStatus *status);\nvoid sipe_purple_set_idle(struct _PurpleConnection *gc,\n\t\t\t  int interval);\n\n/* media */\nvoid capture_pipeline(const gchar *label);\n\n/* transport */\nvoid sipe_purple_transport_close_all(struct sipe_backend_private *purple_private);\n\n/* Convenience macros */\n#define PURPLE_ACCOUNT_TO_SIPE_CORE_PUBLIC ((struct sipe_core_public *) purple_connection_get_protocol_data(purple_account_get_connection(account)))\n#define PURPLE_BUDDY_TO_SIPE_CORE_PUBLIC   ((struct sipe_core_public *) purple_connection_get_protocol_data(purple_account_get_connection(purple_buddy_get_account(buddy))))\n#define PURPLE_GC_TO_SIPE_CORE_PUBLIC      ((struct sipe_core_public *) purple_connection_get_protocol_data(gc))\n\n/* Protocol common functions */\n\ngboolean sipe_purple_plugin_load(PurplePlugin *plugin);\ngboolean sipe_purple_plugin_unload(PurplePlugin *plugin);\n\ngpointer sipe_purple_user_split(void);\nGList *sipe_purple_account_options(void);\n\nvoid sipe_purple_republish_calendar(struct _PurpleAccount *account);\nvoid sipe_purple_reset_status(struct _PurpleAccount *account);\n\nGList *sipe_purple_actions(void);\ngchar *sipe_purple_status_text(struct _PurpleBuddy *buddy);\nvoid sipe_purple_tooltip_text(struct _PurpleBuddy *buddy,\n\t\t\t      struct _PurpleNotifyUserInfo *user_info,\n\t\t\t      gboolean full);\nGList *sipe_purple_blist_node_menu(struct _PurpleBlistNode *node);\nvoid sipe_purple_convo_closed(struct _PurpleConnection *gc, const char *who);\nGHashTable *sipe_purple_get_account_text_table(struct _PurpleAccount *account);\n\nvoid sipe_purple_login(struct _PurpleAccount *account);\nvoid sipe_purple_close(struct _PurpleConnection *gc);\nGList *sipe_purple_status_types(struct _PurpleAccount *account);\nconst char *sipe_purple_list_icon(struct _PurpleAccount *account,\n\t\t\t\t  struct _PurpleBuddy *buddy);\n\nvoid sipe_purple_get_info(struct _PurpleConnection *gc, const char *who);\nvoid sipe_purple_alias_buddy(struct _PurpleConnection *gc, const char *name,\n\t\t\t     const char *alias);\nvoid sipe_purple_group_rename(struct _PurpleConnection *gc, const char *old_name,\n\t\t\t      struct _PurpleGroup *group, GList *moved_buddies);\nvoid sipe_purple_group_remove(struct _PurpleConnection *gc,\n\t\t\t      struct _PurpleGroup *group);\n\nunsigned int sipe_purple_send_typing(struct _PurpleConnection *gc,\n\t\t\t\t     const char *who, PurpleIMTypingState state);\n\nvoid sipe_purple_add_permit(struct _PurpleConnection *gc, const char *name);\nvoid sipe_purple_add_deny(struct _PurpleConnection *gc, const char *name);\n\ngboolean sipe_purple_initiate_media(struct _PurpleAccount *account,\n\t\t\t\t    const char *who,\n\t\t\t\t    PurpleMediaSessionType type);\nPurpleMediaCaps sipe_purple_get_media_caps(struct _PurpleAccount *account,\n\t\t\t\t\t   const char *who);\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-schedule.c",
    "content": "/**\n * @file sipe-schedule.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2017 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <glib.h>\n\n#include \"version.h\"\n#if PURPLE_VERSION_CHECK(3,0,0)\n#else\n#include \"eventloop.h\"\n#define g_timeout_add(t, f, d)         purple_timeout_add(t, f, d)\n#define g_timeout_add_seconds(t, f, d) purple_timeout_add_seconds(t, f, d)\n#define g_source_remove(t)             purple_timeout_remove(t)\n#endif\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n\nstruct purple_schedule {\n\tgpointer core_data;\n\tguint timeout_handler;\n};\n\nstatic gboolean purple_timeout_execute(gpointer data)\n{\n\tgpointer core_data = ((struct purple_schedule *) data)->core_data;\n\tg_free(data);\n \tsipe_core_schedule_execute(core_data);\n\treturn(FALSE);\n}\n\ngpointer sipe_backend_schedule_seconds(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t       guint timeout,\n\t\t\t\t       gpointer data)\n{\n\tstruct purple_schedule *schedule = g_malloc(sizeof(struct purple_schedule));\n\tschedule->core_data = data;\n\tschedule->timeout_handler = g_timeout_add_seconds(timeout,\n\t\t\t\t\t\t\t  purple_timeout_execute,\n\t\t\t\t\t\t\t  schedule);\n\treturn(schedule);\n}\n\ngpointer sipe_backend_schedule_mseconds(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\tguint timeout,\n\t\t\t\t\tgpointer data)\n{\n\tstruct purple_schedule *schedule = g_malloc(sizeof(struct purple_schedule));\n\tschedule->core_data = data;\n\tschedule->timeout_handler = g_timeout_add(timeout,\n\t\t\t\t\t\t  purple_timeout_execute,\n\t\t\t\t\t\t  schedule);\n\treturn(schedule);\n}\n\nvoid sipe_backend_schedule_cancel(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t  gpointer data)\n{\n\tstruct purple_schedule *schedule = data;\n\tg_source_remove(schedule->timeout_handler);\n\tg_free(schedule);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-search.c",
    "content": "/**\n * @file purple-search.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <string.h>\n\n#include <glib.h>\n\n#include \"notify.h\"\n#include \"request.h\"\n\n#include \"version.h\"\n#if PURPLE_VERSION_CHECK(3,0,0)\n#include \"action.h\"\n#include \"conversations.h\"\n#endif\n\n#include \"sipe-common.h\"\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-nls.h\"\n\n#include \"purple-private.h\"\n\nvoid sipe_backend_search_failed(struct sipe_core_public *sipe_public,\n\t\t\t\tSIPE_UNUSED_PARAMETER struct sipe_backend_search_token *token,\n\t\t\t\tconst gchar *msg)\n{\n\tsipe_backend_notify_error(sipe_public, msg, NULL);\n}\n\nstruct sipe_backend_search_results *sipe_backend_search_results_start(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t\t      SIPE_UNUSED_PARAMETER struct sipe_backend_search_token *token)\n{\n\tPurpleNotifySearchResults *results = purple_notify_searchresults_new();\n\n\tif (results) {\n\t\tPurpleNotifySearchColumn *column;\n\t\tcolumn = purple_notify_searchresults_column_new(_(\"User name\"));\n\t\tpurple_notify_searchresults_column_add(results, column);\n\n\t\tcolumn = purple_notify_searchresults_column_new(_(\"Name\"));\n\t\tpurple_notify_searchresults_column_add(results, column);\n\n\t\tcolumn = purple_notify_searchresults_column_new(_(\"Company\"));\n\t\tpurple_notify_searchresults_column_add(results, column);\n\n\t\tcolumn = purple_notify_searchresults_column_new(_(\"Country\"));\n\t\tpurple_notify_searchresults_column_add(results, column);\n\n\t\tcolumn = purple_notify_searchresults_column_new(_(\"Email\"));\n\t\tpurple_notify_searchresults_column_add(results, column);\n\t}\n\n\treturn((struct sipe_backend_search_results *)results);\n}\n\nvoid sipe_backend_search_results_add(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t     struct sipe_backend_search_results *results,\n\t\t\t\t     const gchar *uri,\n\t\t\t\t     const gchar *name,\n\t\t\t\t     const gchar *company,\n\t\t\t\t     const gchar *country,\n\t\t\t\t     const gchar *email)\n{\n\t\tGList *row = NULL;\n\t\trow = g_list_append(row, g_strdup(uri));\n\t\trow = g_list_append(row, g_strdup(name));\n\t\trow = g_list_append(row, g_strdup(company));\n\t\trow = g_list_append(row, g_strdup(country));\n\t\trow = g_list_append(row, g_strdup(email));\n\t\tpurple_notify_searchresults_row_add((PurpleNotifySearchResults *) results,\n\t\t\t\t\t\t    row);\n}\n\nstatic void searchresults_im_buddy(PurpleConnection *gc,\n\t\t\t\t   GList *row,\n\t\t\t\t   SIPE_UNUSED_PARAMETER void *user_data)\n{\n\tPurpleAccount *acct = purple_connection_get_account(gc);\n\tgchar *id = sip_uri_from_name(g_list_nth_data(row, 0));\n\n#if PURPLE_VERSION_CHECK(3,0,0)\n\tPurpleIMConversation *conv = purple_conversations_find_im_with_account(id,\n\t\t\t\t\t\t\t\t\t       acct);\n\n\tif (conv == NULL)\n\t\tconv = purple_im_conversation_new(acct, id);\n#else\n\tPurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,\n\t\t\t\t\t\t\t\t\t id,\n\t\t\t\t\t\t\t\t\t acct);\n\tif (conv == NULL)\n\t\tconv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, id);\n#endif\n\n\tg_free(id);\n\tpurple_conversation_present((PurpleConversation *) conv);\n}\n\nstatic void searchresults_add_buddy(PurpleConnection *gc,\n\t\t\t\t    GList *row,\n\t\t\t\t    SIPE_UNUSED_PARAMETER void *user_data)\n{\n\tpurple_blist_request_add_buddy(purple_connection_get_account(gc),\n\t\t\t\t       g_list_nth_data(row, 0),\n\t\t\t\t       _(\"Other Contacts\"),\n\t\t\t\t       NULL);\n}\n\n\nvoid sipe_backend_search_results_finalize(struct sipe_core_public *sipe_public,\n\t\t\t\t\t  struct sipe_backend_search_results *results,\n\t\t\t\t\t  const gchar *description,\n\t\t\t\t\t  SIPE_UNUSED_PARAMETER gboolean more)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tPurpleNotifySearchResults *r = (PurpleNotifySearchResults *) results;\n\n\tpurple_notify_searchresults_button_add(r,\n\t\t\t\t\t       PURPLE_NOTIFY_BUTTON_IM,\n\t\t\t\t\t       searchresults_im_buddy);\n\tpurple_notify_searchresults_button_add(r,\n\t\t\t\t\t       PURPLE_NOTIFY_BUTTON_ADD,\n\t\t\t\t\t       searchresults_add_buddy);\n\tpurple_notify_searchresults(purple_private->gc,\n\t\t\t\t    NULL,\n\t\t\t\t    NULL,\n\t\t\t\t    description,\n\t\t\t\t    r,\n\t\t\t\t    NULL,\n\t\t\t\t    NULL);\n\n}\n\nstatic void sipe_purple_find_contact_cb(PurpleConnection *gc,\n\t\t\t\t\tPurpleRequestFields *fields)\n{\n\tGList *entries = purple_request_field_group_get_fields(purple_request_fields_get_groups(fields)->data);\n\tconst gchar *given_name = NULL;\n\tconst gchar *surname    = NULL;\n\tconst gchar *email      = NULL;\n\tconst gchar *sipid      = NULL;\n\tconst gchar *company    = NULL;\n\tconst gchar *country    = NULL;\n\n\twhile (entries) {\n\t\tPurpleRequestField *field = entries->data;\n\t\tconst char *id = purple_request_field_get_id(field);\n\t\tconst char *value = purple_request_field_string_get_value(field);\n\n\t\tSIPE_DEBUG_INFO(\"sipe_purple_find_contact_cb: %s = '%s'\", id, value ? value : \"\");\n\n\t\tif (value && strlen(value)) {\n\t\t\tif (strcmp(id, \"given\") == 0) {\n\t\t\t\tgiven_name = value;\n\t\t\t} else if (strcmp(id, \"surname\") == 0) {\n\t\t\t\tsurname = value;\n\t\t\t} else if (strcmp(id, \"email\") == 0) {\n\t\t\t\temail = value;\n\t\t\t} else if (strcmp(id, \"sipid\") == 0) {\n\t\t\t\tsipid = value;\n\t\t\t} else if (strcmp(id, \"company\") == 0) {\n\t\t\t\tcompany = value;\n\t\t\t} else if (strcmp(id, \"country\") == 0) {\n\t\t\t\tcountry = value;\n\t\t\t}\n\t\t}\n\n\t\tentries = g_list_next(entries);\n\t};\n\n\tsipe_core_buddy_search(PURPLE_GC_TO_SIPE_CORE_PUBLIC,\n\t\t\t       NULL,\n\t\t\t       given_name,\n\t\t\t       surname,\n\t\t\t       email,\n\t\t\t       sipid,\n\t\t\t       company,\n\t\t\t       country);\n}\n\n#if PURPLE_VERSION_CHECK(3,0,0)\nvoid sipe_purple_show_find_contact(PurpleProtocolAction *action)\n{\n\tPurpleConnection *gc = action->connection;\n#else\nvoid sipe_purple_show_find_contact(PurplePluginAction *action)\n{\n\tPurpleConnection *gc = (PurpleConnection *) action->context;\n#endif\n\tPurpleRequestFields *fields;\n\tPurpleRequestFieldGroup *group;\n\tPurpleRequestField *field;\n\n\tfields = purple_request_fields_new();\n\tgroup = purple_request_field_group_new(NULL);\n\tpurple_request_fields_add_group(fields, group);\n\n\tfield = purple_request_field_string_new(\"given\", _(\"First name\"), NULL, FALSE);\n\tpurple_request_field_group_add_field(group, field);\n\tfield = purple_request_field_string_new(\"surname\", _(\"Last name\"), NULL, FALSE);\n\tpurple_request_field_group_add_field(group, field);\n\tfield = purple_request_field_string_new(\"email\", _(\"Email\"), NULL, FALSE);\n\tpurple_request_field_group_add_field(group, field);\n\tfield = purple_request_field_string_new(\"sipid\", _(\"SIP ID\"), NULL, FALSE);\n\tpurple_request_field_group_add_field(group, field);\n\tfield = purple_request_field_string_new(\"company\", _(\"Company\"), NULL, FALSE);\n\tpurple_request_field_group_add_field(group, field);\n\tfield = purple_request_field_string_new(\"country\", _(\"Country\"), NULL, FALSE);\n\tpurple_request_field_group_add_field(group, field);\n\n\tpurple_request_fields(gc,\n\t\t\t      _(\"Search\"),\n\t\t\t      _(\"Search for a contact\"),\n\t\t\t      _(\"Enter the information for the person you wish to find. Empty fields will be ignored.\"),\n\t\t\t      fields,\n\t\t\t      _(\"_Search\"), G_CALLBACK(sipe_purple_find_contact_cb),\n\t\t\t      _(\"_Cancel\"), NULL,\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t      purple_request_cpar_from_connection(gc),\n#else\n\t\t\t      purple_connection_get_account(gc), NULL, NULL,\n#endif\n\t\t\t      gc);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-setting.c",
    "content": "/**\n * @file purple-setting.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n\n#include \"account.h\"\n#include \"connection.h\"\n\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n\n#include \"purple-private.h\"\n\n/**\n * Map sipe_setting values to purple account setting keys\n *\n * This needs to be kept in sync with\n *\n *     api/sipe-backend.h\n *     purple-plugin-common.c:sipe_purple_account_options()\n */\nstatic const gchar * const setting_name[SIPE_SETTING_LAST] = {\n\t\"email_url\",      /* SIPE_SETTING_EMAIL_URL      */\n\t\"email_login\",    /* SIPE_SETTING_EMAIL_LOGIN    */\n\t\"email_password\", /* SIPE_SETTING_EMAIL_PASSWORD */\n\t\"groupchat_user\", /* SIPE_SETTING_GROUPCHAT_USER */\n\t\"rdp_client\",     /* SIPE_SETTING_RDP_CLIENT     */\n\t\"useragent\"       /* SIPE_SETTING_USER_AGENT     */\n};\n\nconst gchar *sipe_backend_setting(struct sipe_core_public *sipe_public,\n\t\t\t\t  sipe_setting type)\n{\n\treturn(purple_account_get_string(purple_connection_get_account(sipe_public->backend_private->gc),\n\t\t\t\t\t setting_name[type], NULL));\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-status.c",
    "content": "/**\n * @file purple-status.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n\n#include \"account.h\"\n#include \"savedstatuses.h\"\n\n#include \"version.h\"\n#if !PURPLE_VERSION_CHECK(3,0,0)\n#include \"eventloop.h\"\n#define g_timeout_add_seconds(t, f, d) purple_timeout_add_seconds(t, f, d)\n#define g_source_remove(t)             purple_timeout_remove(t)\n#endif\n\n\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n\n#include \"purple-private.h\"\n\nguint sipe_backend_status(struct sipe_core_public *sipe_public)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tPurpleStatus *status = purple_account_get_active_status(purple_private->account);\n\tif (!status) return(SIPE_ACTIVITY_UNSET);\n\treturn(sipe_purple_token_to_activity(purple_status_get_id(status)));\n}\n\ngboolean sipe_backend_status_changed(struct sipe_core_public *sipe_public,\n\t\t\t\t     guint activity,\n\t\t\t\t     const gchar *message)\n{\n\tgboolean result = FALSE;\n\n\tif ((activity == SIPE_ACTIVITY_AWAY) && purple_savedstatus_is_idleaway()) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_backend_status_changed: user is already idle-away\");\n\t} else {\n\t\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\t\tPurpleStatus *status = purple_account_get_active_status(purple_private->account);\n\t\tconst gchar *status_id = sipe_purple_activity_to_token(activity);\n\n\t\tresult = !(g_str_equal(status_id, purple_status_get_id(status)) &&\n\t\t\t   sipe_strequal(message,\n\t\t\t\t\t purple_status_get_attr_string(status,\n\t\t\t\t\t\t\t\t       SIPE_PURPLE_STATUS_ATTR_ID_MESSAGE)));\n\t}\n\n\treturn(result);\n}\n\n/**\n * This method motivates Purple's Host (e.g. Pidgin) to update its UI\n * by using standard Purple's means of signals and saved statuses.\n *\n * Thus all UI elements get updated: Status Button with Note, docklet.\n * This is ablolutely important as both our status and note can come\n * inbound (roaming) or be updated programmatically (e.g. based on our\n * calendar data).\n */\nvoid sipe_backend_status_and_note(struct sipe_core_public *sipe_public,\n\t\t\t\t  guint activity,\n\t\t\t\t  const gchar *message)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tPurpleAccount *account = purple_private->account;\n\tconst gchar *status_id = sipe_purple_activity_to_token(activity);\n\tPurpleSavedStatus *saved_status;\n\tconst PurpleStatusType *acct_status_type =\n\t\tpurple_status_type_find_with_id(purple_account_get_status_types(account),\n\t\t\t\t\t\tstatus_id);\n\tPurpleStatusPrimitive primitive = purple_status_type_get_primitive(acct_status_type);\n\n\t/* code adapted from: pidgin/gtkstatusbox.c */\n\tsaved_status = purple_savedstatus_find_transient_by_type_and_message(primitive, message);\n\tif (saved_status) {\n\t\tpurple_savedstatus_set_substatus(saved_status, account, acct_status_type, message);\n\t} else {\n\t\t/* This type+message is unique then create a new transient saved status */\n\t\tGList *entry;\n\t\tGList *active_accts = purple_accounts_get_all_active();\n\n\t\tSIPE_DEBUG_INFO(\"sipe_backend_status_and_note: creating new saved status %s '%s'\",\n\t\t\t\tstatus_id, message ? message : \"(null)\");\n\n\t\tsaved_status = purple_savedstatus_new(NULL, primitive);\n\t\tpurple_savedstatus_set_message(saved_status, message);\n\n\t\tfor (entry = active_accts; entry != NULL; entry = entry->next)\n\t\t\tpurple_savedstatus_set_substatus(saved_status,\n\t\t\t\t\t\t\t (PurpleAccount *) entry->data,\n\t\t\t\t\t\t\t acct_status_type,\n\t\t\t\t\t\t\t message);\n\t\tg_list_free(active_accts);\n\t}\n\n\t/* Set the status for each account */\n\tpurple_private->status_changed_by_core = TRUE;\n\tpurple_savedstatus_activate(saved_status);\n}\n\n/**\n * Work around broken libpurple idle notification\n *\n * (1) user changes the status\n *      sipe_purple_set_status()\n *      -> user changed state\n *\n * (2) client detects that user is idle\n *      sipe_purple_set_status()      [sometimes omitted?!?!?]\n *      sipe_purple_set_idle( != 0 )\n *      -> machine changed state\n *\n * (3) client detects that user is no longer idle\n *      sipe_purple_set_idle(0)\n *      sipe_purple_set_status()\n *      -> user changed state\n *\n * (4) core sends a status change\n *      sipe_backend_status_and_note()\n *      purple_savedstatus_activate()\n *      sipe_purple_set_status()\n *      -> status change must be ignored\n *\n * Cases (1) and (2) can only be differentiated by deferring the update.\n */\nstatic void sipe_purple_status_deferred_update(struct sipe_backend_private *purple_private,\n\t\t\t\t\t       gboolean changed_by_user)\n{\n\tgchar *note = purple_private->deferred_status_note;\n\n\tpurple_private->deferred_status_note    = NULL;\n\tpurple_private->deferred_status_timeout = 0;\n\n\tsipe_core_status_set(purple_private->public,\n\t\t\t     changed_by_user,\n\t\t\t     purple_private->deferred_status_activity,\n\t\t\t     note);\n\tg_free(note);\n}\n\nstatic gboolean sipe_purple_status_timeout(gpointer data)\n{\n\t/* timeout expired -> no idle indication -> state changed by user */\n\tsipe_purple_status_deferred_update(data, TRUE);\n\treturn(FALSE);\n}\n\nvoid sipe_purple_set_status(PurpleAccount *account,\n\t\t\t    PurpleStatus *status)\n{\n\tif (purple_account_get_connection(account) &&\n\t    purple_status_is_active(status)) {\n\t\tstruct sipe_core_public *sipe_public = PURPLE_ACCOUNT_TO_SIPE_CORE_PUBLIC;\n\t\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\t\tconst gchar *status_id = purple_status_get_id(status);\n\t\tguint activity = sipe_purple_token_to_activity(status_id);\n\t\tconst gchar *note = purple_status_get_attr_string(status,\n\t\t\t\t\t\t\t\t  SIPE_PURPLE_STATUS_ATTR_ID_MESSAGE);\n\n\t\tSIPE_DEBUG_INFO(\"sipe_purple_set_status[CB]: '%s'\",\n\t\t\t\tstatus_id);\n\n\t\tif (purple_private->status_changed_by_core) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_purple_set_status[CB]: triggered by core - ignoring\");\n\n\t\t} else if (purple_private->user_is_not_idle) {\n\t\t\tsipe_core_status_set(sipe_public,\n\t\t\t\t\t     TRUE,\n\t\t\t\t\t     activity,\n\t\t\t\t\t     note);\n\n\t\t} else {\n\t\t\tif (purple_private->deferred_status_timeout)\n\t\t\t\tg_source_remove(purple_private->deferred_status_timeout);\n\t\t\tg_free(purple_private->deferred_status_note);\n\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_purple_set_status[CB]: defer status update\");\n\n\t\t\tpurple_private->deferred_status_note     = g_strdup(note);\n\t\t\tpurple_private->deferred_status_activity = activity;\n\t\t\tpurple_private->deferred_status_timeout  = g_timeout_add_seconds(1,\n\t\t\t\t\t\t\t\t\t\t\t sipe_purple_status_timeout,\n\t\t\t\t\t\t\t\t\t\t\t purple_private);\n\t\t}\n\n\t\t/* reset flags */\n\t\tpurple_private->status_changed_by_core = FALSE;\n\t\tpurple_private->user_is_not_idle       = FALSE;\n\t}\n}\n\nvoid sipe_purple_set_idle(PurpleConnection *gc,\n\t\t\t  int interval)\n{\n\tif (gc) {\n\t\tstruct sipe_core_public *sipe_public = PURPLE_GC_TO_SIPE_CORE_PUBLIC;\n\t\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\n\t\tpurple_private->user_is_not_idle = interval == 0;\n\n\t\tSIPE_DEBUG_INFO(\"sipe_purple_set_idle[CB]: user is %sidle\",\n\t\t\t\tpurple_private->user_is_not_idle ? \"not \" : \"\");\n\n\t\tif (!purple_private->user_is_not_idle) {\n\t\t\t/* timeout not expired -> state changed by machine */\n\t\t\tif (purple_private->deferred_status_timeout)\n\t\t\t\tg_source_remove(purple_private->deferred_status_timeout);\n\t\t\tsipe_purple_status_deferred_update(purple_private, FALSE);\n\t\t}\n\t}\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-transport.c",
    "content": "/**\n * @file purple-transport.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <errno.h>\n#include <string.h>\n#include <time.h>\n#ifdef HAVE_UNISTD_H\n#include <unistd.h>\n#endif\n\n#include <glib.h>\n\n#include \"sipe-common.h\"\n\n#include \"connection.h\"\n#include \"eventloop.h\"\n#include \"network.h\"\n#include \"proxy.h\"\n#include \"sslconn.h\"\n\n#include \"version.h\"\n#if PURPLE_VERSION_CHECK(3,0,0)\n#include \"circularbuffer.h\"\n#else\n#include \"circbuffer.h\"\n#define PurpleCircularBuffer PurpleCircBuffer\n#define purple_circular_buffer_append(b, s, n) purple_circ_buffer_append(b, s, n)\n#define purple_circular_buffer_get_max_read(b) purple_circ_buffer_get_max_read(b)\n#define purple_circular_buffer_get_output(b)   b->outptr\n#define purple_circular_buffer_mark_read(b, s) purple_circ_buffer_mark_read(b, s)\n#define purple_circular_buffer_new(s)          purple_circ_buffer_new(s)\n#endif\n\n#ifdef _WIN32\n/* wrappers for write() & friends for socket handling */\n#include \"win32/win32dep.h\"\n#else\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <arpa/inet.h>\n#endif\n\n#include \"purple-private.h\"\n\n#include \"sipe-backend.h\"\n#include \"sipe-core.h\"\n#include \"sipe-nls.h\"\n\nstruct sipe_transport_purple {\n\t/* public part shared with core */\n\tstruct sipe_transport_connection public;\n\n\t/* purple private part */\n\tstruct sipe_backend_private *purple_private;\n\ttransport_connected_cb *connected;\n\ttransport_input_cb *input;\n\ttransport_error_cb *error;\n\tPurpleSslConnection *gsc;\n\tPurpleProxyConnectData *proxy;\n\tPurpleCircularBuffer *transmit_buffer;\n\tguint transmit_handler;\n\tguint receive_handler;\n\tint socket;\n\n\tgboolean is_valid;\n\n\tgchar ip_address[INET6_ADDRSTRLEN]; /* OK for IPv4 too  */\n};\n\n#define PURPLE_TRANSPORT ((struct sipe_transport_purple *) conn)\n#define SIPE_TRANSPORT_CONNECTION ((struct sipe_transport_connection *) transport)\n\n#define BUFFER_SIZE_INCREMENT 4096\n#define FLUSH_MAX_RETRIES 5\n\n\n\n/*****************************************************************************\n *\n * Common transport handling\n *\n *****************************************************************************/\nstatic void transport_common_input(struct sipe_transport_purple *transport)\n{\n\tstruct sipe_transport_connection *conn = SIPE_TRANSPORT_CONNECTION;\n\tgssize readlen, len;\n\tgboolean firstread = TRUE;\n\n\t/* Read all available data from the connection */\n\tdo {\n\t\t/* Increase input buffer size as needed */\n\t\tif (conn->buffer_length < conn->buffer_used + BUFFER_SIZE_INCREMENT) {\n\t\t\tconn->buffer_length += BUFFER_SIZE_INCREMENT;\n\t\t\tconn->buffer = g_realloc(conn->buffer, conn->buffer_length);\n\t\t\tSIPE_DEBUG_INFO(\"transport_input_common: new buffer length %\" G_GSIZE_FORMAT,\n\t\t\t\t\tconn->buffer_length);\n\t\t}\n\n\t\t/* Try to read as much as there is space left in the buffer */\n\t\t/* minus 1 for the string terminator */\n\t\treadlen = conn->buffer_length - conn->buffer_used - 1;\n\t\tlen = transport->gsc ?\n\t\t\t(gssize) purple_ssl_read(transport->gsc,\n\t\t\t\t\t\t conn->buffer + conn->buffer_used,\n\t\t\t\t\t\t readlen) :\n\t\t\tread(transport->socket,\n\t\t\t     conn->buffer + conn->buffer_used,\n\t\t\t     readlen);\n\n\t\tif (len < 0 && errno == EAGAIN) {\n\t\t\t/*\n\t\t\t * Work around rare SSL read deadlock situation\n\t\t\t *\n\t\t\t * When we went around the loop then the previous call\n\t\t\t * to purple_ssl_read() filled the buffer exactly. If\n\t\t\t * it also happened to read all pending bytes then it\n\t\t\t * seems that the next call returns len < 0 with EAGAIN\n\t\t\t * instead of the expected len == 0.\n\t\t\t */\n\t\t\tif (transport->gsc && !firstread) {\n\t\t\t\tSIPE_DEBUG_INFO(\"transport_input_common: SSL read deadlock detected - assuming message is %\" G_GSIZE_FORMAT \" bytes long\", conn->buffer_used);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/* Try again later */\n\t\t\treturn;\n\t\t} else if (len < 0) {\n\t\t\tSIPE_DEBUG_ERROR(\"Read error: %s (%d)\", strerror(errno), errno);\n\t\t\ttransport->error(SIPE_TRANSPORT_CONNECTION, _(\"Read error\"));\n\t\t\treturn;\n\t\t} else if (firstread && (len == 0)) {\n\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"Server has disconnected\");\n\t\t\ttransport->error(SIPE_TRANSPORT_CONNECTION, _(\"Server has disconnected\"));\n\t\t\treturn;\n\t\t}\n\n\t\tconn->buffer_used += len;\n\t\tfirstread = FALSE;\n\n\t/* Equivalence indicates that there is possibly more data to read */\n\t} while (len == readlen);\n\n\tconn->buffer[conn->buffer_used] = '\\0';\n        transport->input(conn);\n}\n\nstatic void transport_ssl_input(gpointer data,\n\t\t\t\tSIPE_UNUSED_PARAMETER PurpleSslConnection *gsc,\n\t\t\t\tSIPE_UNUSED_PARAMETER PurpleInputCondition cond)\n{\n\tstruct sipe_transport_purple *transport = data;\n\n\t/* Ignore spurious \"SSL input\" events after disconnect */\n\tif (transport->is_valid)\n\t\ttransport_common_input(transport);\n}\n\nstatic void transport_tcp_input(gpointer data,\n\t\t\t\tSIPE_UNUSED_PARAMETER gint source,\n\t\t\t\tSIPE_UNUSED_PARAMETER PurpleInputCondition cond)\n{\n\tstruct sipe_transport_purple *transport = data;\n\n\t/* Ignore spurious \"TCP input\" events after disconnect */\n\tif (transport->is_valid)\n\t\ttransport_common_input(transport);\n}\n\nstatic void transport_ssl_connect_failure(SIPE_UNUSED_PARAMETER PurpleSslConnection *gsc,\n\t\t\t\t\t  PurpleSslErrorType error,\n\t\t\t\t\t  gpointer data)\n{\n\tstruct sipe_transport_purple *transport = data;\n\n        /* Ignore spurious \"SSL connect failure\" events after disconnect */\n\tif (transport->is_valid) {\n\t\ttransport->socket = -1;\n\t\ttransport->gsc = NULL;\n\t\ttransport->error(SIPE_TRANSPORT_CONNECTION,\n\t\t\t\t purple_ssl_strerror(error));\n\t\tsipe_backend_transport_disconnect(SIPE_TRANSPORT_CONNECTION);\n\t}\n}\n\nstatic void transport_get_socket_info(struct sipe_transport_purple *transport)\n{\n\t/*\n\t * NOTE: getsockname() on Windows seems to be picky about the buffer\n\t *       location. Use an allocated buffer instead of one on the stack,\n\t */\n\tunion socket_info {\n\t\tstruct sockaddr         sa;     /* to avoid casts */\n\t\tstruct sockaddr_in      sa_in;  /* IPv4 variant   */\n\t\tstruct sockaddr_in6     sa_in6; /* IPv6 variant   */\n\t\tstruct sockaddr_storage unused; /* for alignment  */\n\t} *si = g_new(union socket_info, 1);\n\tsocklen_t si_len = sizeof(*si);\n\tconst void *addr;\n\tguint port;\n\n\t/*\n\t * libpurple only returns IPv4 addresses\n\t *\n\t *    purple_network_get_my_ip(transport->socket);\n\t *\n\t * libpurple returns port 0 on Windows for IPv6 sockets\n\t *\n\t *    purple_network_get_port_from_fd(transport->socket);\n\t *\n\t * Replace them with our own code.\n\t */\n\tif (getsockname(transport->socket, &si->sa, &si_len) < 0) {\n\t\tSIPE_DEBUG_ERROR(\"transport_get_socket_info: %s (%d)\",\n\t\t\t\t strerror(errno), errno);\n\n\t\t/* make sure socket address family is initialized */\n\t\tsi->sa.sa_family = AF_UNSPEC;\n\t}\n\n\tswitch (si->sa.sa_family) {\n\t\tcase AF_INET:\n\t\t\tport = si->sa_in.sin_port;\n\t\t\taddr = &si->sa_in.sin_addr;\n\t\t\tbreak;\n\t\tcase AF_INET6:\n\t\t\tport = si->sa_in6.sin6_port;\n\t\t\taddr = &si->sa_in6.sin6_addr;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tport = htons(0); /* error fallback */\n\t\t\taddr = NULL;\n\t\t\tbreak;\n\t}\n\n\ttransport->public.client_port = ntohs(port);\n\tif ((addr == NULL) ||\n\t    (inet_ntop(si->sa.sa_family, addr,\n\t\t       transport->ip_address,\n\t\t       sizeof(transport->ip_address)) == NULL)) {\n\t\t/* error fallback */\n\t\tstrcpy(transport->ip_address, \"0.0.0.0\");\n\t}\n\tg_free(si);\n\n\tSIPE_DEBUG_INFO(\"transport_get_socket_info: %s:%d(%p)\",\n\t\t\ttransport->ip_address,\n\t\t\ttransport->public.client_port,\n\t\t\ttransport);\n}\n\nstatic void transport_common_connected(struct sipe_transport_purple *transport,\n\t\t\t\t       int fd)\n{\n        /* Ignore spurious \"connected\" events after disconnect */\n\tif (transport->is_valid) {\n\n\t\ttransport->proxy = NULL;\n\n\t\tif (fd < 0) {\n\t\t\ttransport->error(SIPE_TRANSPORT_CONNECTION,\n\t\t\t\t\t _(\"Could not connect\"));\n\t\t\tsipe_backend_transport_disconnect(SIPE_TRANSPORT_CONNECTION);\n\t\t\treturn;\n\t\t}\n\n\t\ttransport->socket = fd;\n\t\ttransport_get_socket_info(transport);\n\n\t\tif (transport->gsc) {\n\t\t\tpurple_ssl_input_add(transport->gsc, transport_ssl_input, transport);\n\t\t} else {\n\t\t\ttransport->receive_handler = purple_input_add(fd,\n\t\t\t\t\t\t\t\t      PURPLE_INPUT_READ,\n\t\t\t\t\t\t\t\t      transport_tcp_input,\n\t\t\t\t\t\t\t\t      transport);\n\t\t}\n\n\t\ttransport->connected(SIPE_TRANSPORT_CONNECTION);\n\t}\n}\n\nstatic void transport_ssl_connected(gpointer data,\n\t\t\t\t    PurpleSslConnection *gsc,\n\t\t\t\t    SIPE_UNUSED_PARAMETER PurpleInputCondition cond)\n{\n\ttransport_common_connected(data, gsc->fd);\n}\n\nstatic void transport_tcp_connected(gpointer data,\n\t\t\t\t    gint source,\n\t\t\t\t    SIPE_UNUSED_PARAMETER const gchar *error_message)\n{\n\ttransport_common_connected(data, source);\n}\n\nstruct sipe_transport_connection *\nsipe_backend_transport_connect(struct sipe_core_public *sipe_public,\n\t\t\t       const sipe_connect_setup *setup)\n{\n\tstruct sipe_transport_purple *transport = g_new0(struct sipe_transport_purple, 1);\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tPurpleConnection *gc = purple_private->gc;\n\tPurpleAccount *account = purple_connection_get_account(gc);\n\n\tSIPE_DEBUG_INFO(\"transport_connect - hostname: %s port: %d\",\n\t\t\tsetup->server_name, setup->server_port);\n\n\ttransport->public.type      = setup->type;\n\ttransport->public.user_data = setup->user_data;\n\ttransport->purple_private   = purple_private;\n\ttransport->connected        = setup->connected;\n\ttransport->input            = setup->input;\n\ttransport->error            = setup->error;\n\ttransport->transmit_buffer  = purple_circular_buffer_new(0);\n\ttransport->is_valid         = TRUE;\n\n\tpurple_private->transports = g_slist_prepend(purple_private->transports,\n\t\t\t\t\t\t     transport);\n\n\tif (setup->type == SIPE_TRANSPORT_TLS) {\n\t\t/* SSL case */\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"using SSL\");\n\n\t\tif ((transport->gsc = purple_ssl_connect(account,\n\t\t\t\t\t\t\t setup->server_name,\n\t\t\t\t\t\t\t setup->server_port,\n\t\t\t\t\t\t\t transport_ssl_connected,\n\t\t\t\t\t\t\t transport_ssl_connect_failure,\n\t\t\t\t\t\t\t transport)) == NULL) {\n\t\t\tsetup->error(SIPE_TRANSPORT_CONNECTION,\n\t\t\t\t     _(\"Could not create SSL context\"));\n\t\t\tsipe_backend_transport_disconnect(SIPE_TRANSPORT_CONNECTION);\n\t\t\treturn(NULL);\n\t\t}\n\t} else if (setup->type == SIPE_TRANSPORT_TCP) {\n\t\t/* TCP case */\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"using TCP\");\n\n\t\t/*\n\t\t * NOTE: during shutdown libpurple calls\n\t\t *\n\t\t *    purple_proxy_connect_cancel_with_handle(gc);\n\t\t *\n\t\t * before our cleanup code. Therefore we can't use \"gc\" as\n\t\t * handle. We are not using it for anything thus NULL is fine.\n\t\t */\n\t\tif ((transport->proxy = purple_proxy_connect(NULL, account,\n\t\t\t\t\t\t\t     setup->server_name,\n\t\t\t\t\t\t\t     setup->server_port,\n\t\t\t\t\t\t\t     transport_tcp_connected,\n\t\t\t\t\t\t\t     transport)) == NULL) {\n\t\t\tsetup->error(SIPE_TRANSPORT_CONNECTION,\n\t\t\t\t     _(\"Could not create socket\"));\n\t\t\tsipe_backend_transport_disconnect(SIPE_TRANSPORT_CONNECTION);\n\t\t\treturn(NULL);\n\t\t}\n\t} else {\n\t\tsetup->error(SIPE_TRANSPORT_CONNECTION,\n\t\t\t     \"This should not happen...\");\n\t\tsipe_backend_transport_disconnect(SIPE_TRANSPORT_CONNECTION);\n\t\treturn(NULL);\n\t}\n\n\treturn(SIPE_TRANSPORT_CONNECTION);\n}\n\nstatic gboolean transport_deferred_destroy(gpointer user_data)\n{\n\t/*\n\t * All pending events on transport have been processed.\n\t * Now it is safe to destroy the data structure.\n\t */\n\tSIPE_DEBUG_INFO(\"transport_deferred_destroy: %p\", user_data);\n\tg_free(user_data);\n\treturn(FALSE);\n}\n\nvoid sipe_backend_transport_disconnect(struct sipe_transport_connection *conn)\n{\n\tstruct sipe_transport_purple *transport = PURPLE_TRANSPORT;\n\tstruct sipe_backend_private *purple_private;\n\n\tif (!transport || !transport->is_valid) return;\n\n\tpurple_private = transport->purple_private;\n\tpurple_private->transports = g_slist_remove(purple_private->transports,\n\t\t\t\t\t\t    transport);\n\n\tif (transport->gsc) {\n\t\tpurple_ssl_close(transport->gsc);\n\t} else if (transport->socket > 0) {\n\t\tclose(transport->socket);\n\t}\n\n\tif (transport->proxy)\n\t\tpurple_proxy_connect_cancel(transport->proxy);\n\n\tif (transport->transmit_handler)\n\t\tpurple_input_remove(transport->transmit_handler);\n\tif (transport->receive_handler)\n\t\tpurple_input_remove(transport->receive_handler);\n\n\tif (transport->transmit_buffer)\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\tg_object_unref(transport->transmit_buffer);\n#else\n\t\tpurple_circ_buffer_destroy(transport->transmit_buffer);\n#endif\n\tg_free(transport->public.buffer);\n\n\t/* defer deletion of transport data structure to idle callback */\n\ttransport->is_valid = FALSE;\n\tg_idle_add(transport_deferred_destroy, transport);\n}\n\ngchar *sipe_backend_transport_ip_address(struct sipe_transport_connection *conn)\n{\n\treturn(g_strdup(PURPLE_TRANSPORT->ip_address));\n}\n\nvoid sipe_purple_transport_close_all(struct sipe_backend_private *purple_private)\n{\n\tGSList *entry;\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_purple_transport_close_all: entered\");\n\twhile ((entry = purple_private->transports) != NULL)\n\t\tsipe_backend_transport_disconnect(entry->data);\n}\n\n/* returns a negative number on write error */\nstatic gssize transport_write(struct sipe_transport_purple *transport)\n{\n\tgsize max_write;\n\n\tmax_write = purple_circular_buffer_get_max_read(transport->transmit_buffer);\n\tif (max_write > 0) {\n\t\tgssize written = transport->gsc ?\n\t\t\t(gssize) purple_ssl_write(transport->gsc,\n\t\t\t\t\t\t  purple_circular_buffer_get_output(transport->transmit_buffer),\n\t\t\t\t\t\t  max_write) :\n\t\t\twrite(transport->socket,\n\t\t\t      purple_circular_buffer_get_output(transport->transmit_buffer),\n\t\t\t      max_write);\n\n\t\tif (written <= 0) {\n\t\t\tif (written == 0 || errno != EAGAIN) {\n\t\t\t\tSIPE_DEBUG_ERROR(\"Write error: %s (%d)\",\n\t\t\t\t\t\t strerror(errno), errno);\n\t\t\t\ttransport->error(SIPE_TRANSPORT_CONNECTION,\n\t\t\t\t\t\t _(\"Write error\"));\n\t\t\t}\n\t\t} else {\n\t\t\tpurple_circular_buffer_mark_read(transport->transmit_buffer,\n\t\t\t\t\t\t\t written);\n\t\t}\n\n\t\treturn written;\n\t} else {\n\t\t/* buffer is empty -> stop sending */\n\t\tpurple_input_remove(transport->transmit_handler);\n\t\ttransport->transmit_handler = 0;\n\t}\n\n\treturn 0;\n}\n\nstatic void transport_canwrite_cb(gpointer data,\n\t\t\t\t  SIPE_UNUSED_PARAMETER gint source,\n\t\t\t\t  SIPE_UNUSED_PARAMETER PurpleInputCondition cond)\n{\n\tstruct sipe_transport_purple *transport = data;\n\n\t/* Ignore spurious \"can write\" events after disconnect */\n\tif (transport->is_valid)\n\t\ttransport_write(data);\n}\n\nvoid sipe_backend_transport_message(struct sipe_transport_connection *conn,\n\t\t\t\t    const gchar *buffer)\n{\n\tstruct sipe_transport_purple *transport = PURPLE_TRANSPORT;\n\n\t/* add packet to circular buffer */\n\tpurple_circular_buffer_append(transport->transmit_buffer,\n\t\t\t\t      buffer, strlen(buffer));\n\n\t/* initiate transmission */\n\tif (!transport->transmit_handler) {\n\t\ttransport->transmit_handler = purple_input_add(transport->socket,\n\t\t\t\t\t\t\t       PURPLE_INPUT_WRITE,\n\t\t\t\t\t\t\t       transport_canwrite_cb,\n\t\t\t\t\t\t\t       transport);\n\t}\n}\n\nvoid sipe_backend_transport_flush(struct sipe_transport_connection *conn)\n{\n\tstruct sipe_transport_purple *transport = PURPLE_TRANSPORT;\n\tgssize written;\n\tint retries = 0;\n\n\twhile ((written = transport_write(transport))) {\n\t\tif (written < 0) {\n\t\t\tif (errno == EAGAIN && retries++ < FLUSH_MAX_RETRIES) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tretries = 0;\n\t}\n\n\tif (written != 0) {\n\t\t/* We couldn't send the whole buffer. Transport is probably\n\t\t * broken. */\n\t\tSIPE_DEBUG_INFO(\"sipe_backend_transport_flush: leaving \"\n\t\t\t\t\"%\" G_GSSIZE_FORMAT \" unsent bytes in buffer.\",\n\t\t\t\tpurple_circular_buffer_get_max_read(\n\t\t\t\t\t\ttransport->transmit_buffer));\n\t}\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/purple-user.c",
    "content": "/**\n * @file purple-user.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n\n#include \"server.h\"\n#include \"request.h\"\n\n#include \"purple-private.h\"\n\n#if PURPLE_VERSION_CHECK(3,0,0)\n#else\n#define purple_serv_got_typing(c, n, t, s)\tserv_got_typing(c, n, t, s)\n#define purple_serv_got_typing_stopped(c, n)\tserv_got_typing_stopped(c, n)\n#define PURPLE_IM_TYPING PURPLE_TYPING\n#endif\n\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n#include \"sipe-nls.h\"\n\n#define SIPE_TYPING_RECV_TIMEOUT 6\n\nvoid sipe_backend_user_feedback_typing(struct sipe_core_public *sipe_public,\n\t\t\t\t       const gchar *from)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tpurple_serv_got_typing(purple_private->gc, from,\n\t\t\t       SIPE_TYPING_RECV_TIMEOUT,\n\t\t\t       PURPLE_IM_TYPING);\n}\n\nvoid sipe_backend_user_feedback_typing_stop(struct sipe_core_public *sipe_public,\n\t\t\t\t\t    const gchar *from)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\tpurple_serv_got_typing_stopped(purple_private->gc, from);\n}\n\nstatic void accept_cb(gpointer key, SIPE_UNUSED_PARAMETER int choice)\n{\n\tsipe_core_user_ask_cb(key, TRUE);\n}\n\nstatic void decline_cb(gpointer key, SIPE_UNUSED_PARAMETER int choice)\n{\n\tsipe_core_user_ask_cb(key, FALSE);\n}\n\nvoid sipe_backend_user_ask(struct sipe_core_public *sipe_public,\n\t\t\t   const gchar *message,\n\t\t\t   const gchar *accept_label,\n\t\t\t   const gchar *decline_label,\n\t\t\t   gpointer key)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\n\tpurple_request_action(key, \"Office Communicator\", message,\n\t\t\t      NULL, 0,\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t      purple_request_cpar_from_account(purple_private->account),\n#else\n\t\t\t      purple_private->account, NULL, NULL,\n#endif\n\t\t\t      key, decline_label ? 2 : 1,\n\t\t\t      accept_label, (PurpleRequestActionCb) accept_cb,\n\t\t\t      decline_label, (PurpleRequestActionCb) decline_cb);\n}\n\nvoid sipe_backend_user_close_ask(gpointer key)\n{\n\tpurple_request_close_with_handle(key);\n}\n\nstatic void ask_choice_accept_cb(gpointer key, PurpleRequestFields *fields)\n{\n\tguint choice_id =\n\t\t\tGPOINTER_TO_INT(purple_request_fields_get_choice(fields, \"choice\"));\n\n\tsipe_core_user_ask_choice_cb(key, choice_id);\n}\n\nstatic void ask_choice_cancel_cb(gpointer key)\n{\n\tsipe_core_user_ask_choice_cb(key, SIPE_CHOICE_CANCELLED);\n}\n\n\nvoid sipe_backend_user_ask_choice(struct sipe_core_public *sipe_public,\n\t\t\t\t  const gchar *message,\n\t\t\t\t  GSList *choices,\n\t\t\t\t  gpointer key)\n{\n\tstruct sipe_backend_private *purple_private = sipe_public->backend_private;\n\n\tPurpleRequestFields *fields = purple_request_fields_new();\n\tPurpleRequestFieldGroup *group = purple_request_field_group_new(NULL);\n\tPurpleRequestField *field =\n\t\t\tpurple_request_field_choice_new(\"choice\", message, 0);\n\n\tguint i;\n\tfor (i = 0; i != g_slist_length(choices); ++i) {\n\t\tpurple_request_field_choice_add(field,\n\t\t\t\t\t\tg_slist_nth_data(choices, i)\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t\t\t\t, GUINT_TO_POINTER(i)\n#endif\n\t\t\t\t\t\t);\n\t}\n\n\tpurple_request_field_group_add_field(group, field);\n\tpurple_request_fields_add_group(fields, group);\n\n\tpurple_request_fields(key, \"Microsoft Lync\",\n\t\t\t      NULL, NULL, fields,\n\t\t\t      _(\"OK\"), (GCallback)ask_choice_accept_cb,\n\t\t\t      _(\"Cancel\"), (GCallback)ask_choice_cancel_cb,\n#if PURPLE_VERSION_CHECK(3,0,0)\n\t\t\t      purple_request_cpar_from_account(purple_private->account),\n#else\n\t\t\t      purple_private->account, NULL, NULL,\n#endif\n\t\t\t      key);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/tests-load.c",
    "content": "/**\n * @file tests-load.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2010 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <stdlib.h>\n#include <stdio.h>\n\n#include <gmodule.h>\n\n/* test that libsipe.so loads succesfully */\nint main(int argc, char *argv[])\n{\n\tint rc = 1;\n\n\t(void) argc;\n\t(void) argv;\n\n\t/* well if this doesn't work, what's the use of a plugin? */\n\tif (g_module_supported()) {\n\t\tgchar *name = g_module_build_path(\".libs\", \"sipe\");\n\t\tGModule *module = g_module_open(name, G_MODULE_BIND_LOCAL);\n\t\tif (module) {\n\t\t\tg_module_close(module);\n\t\t\t/* all OK */\n\t\t\tprintf(\"plugin loaded OK\\n\");\n\t\t\trc = 0;\n\t\t} else {\n\t\t\tfprintf(stderr, \"plugin loaded error: %s\\n\",\n\t\t\t\tg_module_error());\n\t\t}\n\t\tg_free(name);\n\t}\n\treturn(rc);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/purple/tests.c",
    "content": "/**\n * @file tests.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2011 SIPE Project <http://sipe.sourceforge.net/>\n * Copyright (C) 2010 pier11 <pier11@operamail.com>\n * Copyright (C) 2008 Novell, Inc.\n *\n * Implemented with reference to the follow documentation:\n *   - http://davenport.sourceforge.net/ntlm.html\n *   - MS-NLMP: http://msdn.microsoft.com/en-us/library/cc207842.aspx\n *   - MS-SIP : http://msdn.microsoft.com/en-us/library/cc246115.aspx\n *\n * Please use \"make tests\" to build & run them!\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <glib.h>\n\n#include \"version.h\"\n#if !PURPLE_VERSION_CHECK(3,0,0)\n#include \"cipher.h\"\n#endif\n\n#include \"debug.h\"\n#include \"signals.h\"\n\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n\n/* stub for purple-user.c */\nvoid sipe_core_user_ask_cb(SIPE_UNUSED_PARAMETER gpointer key,\n\t\t\t   SIPE_UNUSED_PARAMETER gboolean accepted)\n{\n}\n\ngboolean sip_sec_ntlm_tests(void);\n\nint main()\n{\n\t/* Initialization that libpurple/core.c would normally do */\n\tpurple_signals_init();\n\tpurple_debug_init();\n\tpurple_debug_set_enabled(TRUE);\n#if !PURPLE_VERSION_CHECK(3,0,0)\n\tpurple_ciphers_init();\n#endif\n\n\t/* Run tests */\n\treturn(sip_sec_ntlm_tests() ? 0 : 1);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/telepathy/Makefile.am",
    "content": "SUBDIRS = data\n\nMAINTAINERCLEANFILES = \\\n\tMakefile.in\n\nlibexec_PROGRAMS = telepathy-sipe\n\ntelepathy_sipe_SOURCES = \\\n\ttelepathy-buddy.c \\\n\ttelepathy-connection.c \\\n\ttelepathy-debug.c \\\n\ttelepathy-dnsquery.c \\\n\ttelepathy-main.c \\\n\ttelepathy-private.h \\\n\ttelepathy-protocol.c \\\n\ttelepathy-schedule.c \\\n\ttelepathy-search.c \\\n\ttelepathy-status.c \\\n\ttelepathy-stubs.c \\\n\ttelepathy-tls.c \\\n\ttelepathy-transport.c\n\nAM_CFLAGS = $(st)\n\ntelepathy_sipe_CFLAGS = \\\n\t$(DEBUG_CFLAGS) \\\n\t$(QUALITY_CFLAGS) \\\n\t$(LOCALE_CPPFLAGS) \\\n\t$(TELEPATHY_GLIB_CFLAGS) \\\n\t$(DBUS_GLIB_CFLAGS) \\\n\t$(GIO_CFLAGS) \\\n\t$(GOBJECT_CFLAGS) \\\n\t$(GLIB_CFLAGS) \\\n\t-I$(srcdir)/../api\n\ntelepathy_sipe_LDADD = \\\n\t../core/libsipe_core.la \\\n\t../core/libsipe_core_crypto.la \\\n\t../core/libsipe_core_libxml2.la \\\n\t../core/libsipe_core_mime.la \\\n\t$(GMIME_LIBS) \\\n\t$(LIBXML2_LIBS) \\\n\t$(NSS_LIBS) \\\n\t$(OPENSSL_LIBS) \\\n\t$(TELEPATHY_GLIB_LIBS) \\\n\t$(DBUS_GLIB_LIBS) \\\n\t$(GIO_LIBS) \\\n\t$(GOBJECT_LIBS) \\\n\t$(GLIB_LIBS)\n\nif SIPE_HAVE_APPSHARE_SERVER\ntelepathy_sipe_LDADD += \\\n\t$(FREERDP_SHADOW_LIBS)\nendif\n"
  },
  {
    "path": "src/telepathy/data/Makefile.am",
    "content": "MAINTAINERCLEANFILES = \\\n\tMakefile.in\n\n# D-Bus service file\nservicedir       = $(datadir)/dbus-1/services\nservice_in_files = org.freedesktop.Telepathy.ConnectionManager.sipe.service.in\nservice_DATA     = $(service_in_files:%.service.in=%.service)\nprofiledir       = $(datadir)/telepathy/profiles\nprofile_DATA     = sipe.profile\nEXTRA_DIST       = $(service_in_files) sipe.profile\nCLEANFILES       = $(service_DATA)\n\n# Rule to make the service file with libexecdir expanded\n$(service_DATA): $(service_in_files) Makefile\n\t$(AM_V_GEN)sed -e \"s|\\@libexecdir\\@|$(libexecdir)|\" $< >$@\n\n"
  },
  {
    "path": "src/telepathy/data/org.freedesktop.Telepathy.ConnectionManager.sipe.service.in",
    "content": "[D-BUS Service]\nName=org.freedesktop.Telepathy.ConnectionManager.sipe\nExec=@libexecdir@/telepathy-sipe\n"
  },
  {
    "path": "src/telepathy/data/sipe.profile",
    "content": "<service xmlns=\"http://telepathy.freedesktop.org/wiki/service-profile-v1\"\n         id=\"sipe\"\n         type=\"IM\"\n         manager=\"sipe\"\n         protocol=\"sipe\"\n         icon=\"im-sipe\">\n  <name>Office Communicator</name>\n</service>\n"
  },
  {
    "path": "src/telepathy/telepathy-buddy.c",
    "content": "/**\n * @file telepathy-buddy.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2012-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <string.h>\n\n#include <glib-object.h>\n#include <glib/gstdio.h>\n#include <telepathy-glib/base-connection.h>\n#include <telepathy-glib/base-contact-list.h>\n#include <telepathy-glib/telepathy-glib.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n\n#include \"telepathy-private.h\"\n\n#define SIPE_INFO_FIELD_MAX (SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY + 1)\n\nstruct telepathy_buddy {\n\tconst gchar *uri;   /* borrowed from contact_list->buddies key */\n\tGHashTable *groups; /* key: group name, value: buddy_entry */\n                            /* keys are borrowed from contact_list->groups */\n\tTpHandle handle;\n\t/* includes alias as stored on the server */\n\tgchar *info[SIPE_INFO_FIELD_MAX];\n\tgchar *hash;        /* photo hash */\n\tguint activity;\n};\n\nstruct telepathy_buddy_entry {\n\tstruct telepathy_buddy *buddy; /* pointer to parent */\n\tconst gchar *group;            /* borrowed from contact_list->groups key */\n};\n\nG_BEGIN_DECLS\n/*\n * Contact List class - data structures\n */\ntypedef struct _SipeContactListClass {\n\tTpBaseContactListClass parent_class;\n} SipeContactListClass;\n\ntypedef struct _SipeContactList {\n\tTpBaseContactList parent;\n\n\tTpBaseConnection *connection;\n\tTpHandleRepoIface *contact_repo;\n\tTpHandleSet *contacts;\n\n\tGHashTable *buddies;       /* key: SIP URI,    value: buddy */\n\tGHashTable *buddy_handles; /* key: TpHandle,   value: buddy */\n\tGHashTable *groups;        /* key: group name, value: buddy */\n\n\tgboolean initial_received;\n} SipeContactList;\n\n/*\n * Contact List class - type macros\n */\nstatic GType sipe_contact_list_get_type(void) G_GNUC_CONST;\n#define SIPE_TYPE_CONTACT_LIST \\\n\t(sipe_contact_list_get_type())\n#define SIPE_CONTACT_LIST(obj) \\\n\t(G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_CONTACT_LIST, \\\n\t\t\t\t    SipeContactList))\nG_END_DECLS\n\n/*\n * Contact List class - type definition\n */\nstatic void contact_group_list_iface_init(TpContactGroupListInterface *);\nG_DEFINE_TYPE_WITH_CODE(SipeContactList,\n\t\t\tsipe_contact_list,\n\t\t\tTP_TYPE_BASE_CONTACT_LIST,\n\t\t\tG_IMPLEMENT_INTERFACE (TP_TYPE_CONTACT_GROUP_LIST,\n\t\t\t\t\t       contact_group_list_iface_init);\n)\n\n\n/*\n * Contact List class - instance methods\n */\nstatic TpHandleSet *dup_contacts(TpBaseContactList *contact_list)\n{\n\tSipeContactList *self = SIPE_CONTACT_LIST(contact_list);\n\treturn(tp_handle_set_copy(self->contacts));\n}\n\nstatic void dup_states(SIPE_UNUSED_PARAMETER TpBaseContactList *contact_list,\n\t\t       SIPE_UNUSED_PARAMETER TpHandle contact,\n\t\t       TpSubscriptionState *subscribe,\n\t\t       TpSubscriptionState *publish,\n\t\t       gchar **publish_request)\n{\n\t/* @TODO */\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeContactList::dup_states - NOT IMPLEMENTED\");\n\n\tif (subscribe)\n\t\t*subscribe = TP_SUBSCRIPTION_STATE_YES;\n\tif (publish)\n\t\t*publish = TP_SUBSCRIPTION_STATE_YES;\n\tif (publish_request)\n\t\t*publish_request = g_strdup(\"\");\n}\n\nstatic void sipe_contact_list_constructed(GObject *object)\n{\n\tSipeContactList *self = SIPE_CONTACT_LIST(object);\n\tvoid (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_contact_list_parent_class)->constructed;\n\n\tif (chain_up)\n\t\tchain_up(object);\n\n\tg_object_get(self, \"connection\", &self->connection, NULL);\n\tself->contact_repo = tp_base_connection_get_handles(self->connection,\n\t\t\t\t\t\t\t    TP_HANDLE_TYPE_CONTACT);\n\tself->contacts     = tp_handle_set_new(self->contact_repo);\n}\n\nstatic void sipe_contact_list_dispose(GObject *object)\n{\n\tSipeContactList *self = SIPE_CONTACT_LIST(object);\n\tvoid (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_contact_list_parent_class)->dispose;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeContactList::dispose\");\n\n\ttp_clear_pointer(&self->contacts, tp_handle_set_destroy);\n\ttp_clear_object(&self->connection);\n\t/* NOTE: the order is important due to borrowing of keys! */\n\ttp_clear_pointer(&self->buddy_handles, g_hash_table_unref);\n\ttp_clear_pointer(&self->buddies, g_hash_table_unref);\n\ttp_clear_pointer(&self->groups, g_hash_table_unref);\n\n\tif (chain_up)\n\t\tchain_up(object);\n}\n\n/*\n * Contact List class - type implementation\n */\nstatic void sipe_contact_list_class_init(SipeContactListClass *klass)\n{\n\tGObjectClass *object_class         = G_OBJECT_CLASS(klass);\n\tTpBaseContactListClass *base_class = TP_BASE_CONTACT_LIST_CLASS(klass);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeContactList::class_init\");\n\n\tobject_class->constructed = sipe_contact_list_constructed;\n\tobject_class->dispose     = sipe_contact_list_dispose;\n\n\tbase_class->dup_contacts = dup_contacts;\n\tbase_class->dup_states   = dup_states;\n}\n\nstatic void buddy_free(gpointer data);\nstatic void sipe_contact_list_init(SIPE_UNUSED_PARAMETER SipeContactList *self)\n{\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeContactList::init\");\n\n\tself->buddies       = g_hash_table_new_full(g_str_hash, g_str_equal,\n\t\t\t\t\t\t    g_free, buddy_free);\n\tself->buddy_handles = g_hash_table_new(g_direct_hash, g_direct_equal);\n\tself->groups        = g_hash_table_new_full(g_str_hash, g_str_equal,\n\t\t\t\t\t\t    g_free, NULL);\n\n\tself->initial_received = FALSE;\n}\n\n/*\n * Contact List class - interface implementation\n *\n * Contact groups\n */\nstatic GStrv dup_groups(TpBaseContactList *contact_list)\n{\n\tSipeContactList *self = SIPE_CONTACT_LIST(contact_list);\n\tGPtrArray *groups     = g_ptr_array_sized_new(\n\t\tg_hash_table_size(self->groups) + 1);\n\tGHashTableIter iter;\n\tgpointer name;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeContactList::dup_groups called\");\n\n\tg_hash_table_iter_init(&iter, self->groups);\n\twhile (g_hash_table_iter_next(&iter, &name, NULL))\n\t\tg_ptr_array_add(groups, g_strdup(name));\n\tg_ptr_array_add(groups, NULL);\n\n\treturn((GStrv) g_ptr_array_free(groups, FALSE));\n}\n\nstatic TpHandleSet *dup_group_members(TpBaseContactList *contact_list,\n\t\t\t\t      const gchar *group_name)\n{\n\tSipeContactList *self = SIPE_CONTACT_LIST(contact_list);\n\tTpHandleSet *members  = tp_handle_set_new(self->contact_repo);\n\tGHashTableIter iter;\n\tstruct telepathy_buddy *buddy;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeContactList::dup_group_members called\");\n\n\tg_hash_table_iter_init(&iter, self->buddies);\n\twhile (g_hash_table_iter_next(&iter, NULL, (gpointer) &buddy))\n\t\tif (g_hash_table_lookup(buddy->groups, group_name))\n\t\t\ttp_handle_set_add(members, buddy->handle);\n\n\treturn(members);\n}\n\nstatic GStrv dup_contact_groups(TpBaseContactList *contact_list,\n\t\t\t\tTpHandle contact)\n{\n\tSipeContactList *self         = SIPE_CONTACT_LIST(contact_list);\n\tGPtrArray *groups             = g_ptr_array_sized_new(\n\t\tg_hash_table_size(self->groups) + 1);\n\tstruct telepathy_buddy *buddy = g_hash_table_lookup(self->buddy_handles,\n\t\t\t\t\t\t\t    GUINT_TO_POINTER(contact));\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeContactList::dup_contact_groups called\");\n\n\tif (buddy) {\n\t\tGHashTableIter iter;\n\t\tconst gchar *group_name;\n\n\t\tg_hash_table_iter_init(&iter, buddy->groups);\n\t\twhile (g_hash_table_iter_next(&iter,\n\t\t\t\t\t      (gpointer) &group_name,\n\t\t\t\t\t      NULL))\n\t\t\tg_ptr_array_add(groups, g_strdup(group_name));\n\t}\n\tg_ptr_array_add(groups, NULL);\n\n\treturn((GStrv) g_ptr_array_free(groups, FALSE));\n}\n\nstatic void contact_group_list_iface_init(TpContactGroupListInterface *iface)\n{\n#define IMPLEMENT(x) iface->x = x\n\tIMPLEMENT(dup_groups);\n\tIMPLEMENT(dup_group_members);\n\tIMPLEMENT(dup_contact_groups);\n#undef IMPLEMENT\n}\n\n/* create new contact list object */\nSipeContactList *sipe_telepathy_contact_list_new(TpBaseConnection *connection)\n{\n\treturn(g_object_new(SIPE_TYPE_CONTACT_LIST,\n\t\t\t    \"connection\", connection,\n\t\t\t    NULL));\n}\n\n/* get & set alias for a contact  */\nconst gchar *sipe_telepathy_buddy_get_alias(SipeContactList *contact_list,\n\t\t\t\t\t    TpHandle contact)\n{\n\tstruct telepathy_buddy *buddy = g_hash_table_lookup(contact_list->buddy_handles,\n\t\t\t\t\t\t\t    GUINT_TO_POINTER(contact));\n\tif (!buddy)\n\t\treturn(NULL);\n\treturn(buddy->info[SIPE_BUDDY_INFO_DISPLAY_NAME]);\n}\n\nstatic void update_alias(struct telepathy_buddy *buddy,\n\t\t\t const gchar *alias)\n{\n\tif (buddy) {\n\t\tg_free(buddy->info[SIPE_BUDDY_INFO_DISPLAY_NAME]);\n\t\tbuddy->info[SIPE_BUDDY_INFO_DISPLAY_NAME] = g_strdup(alias);\n\t}\n}\n\nvoid sipe_telepathy_buddy_set_alias(SipeContactList *contact_list,\n\t\t\t\t    const guint contact,\n\t\t\t\t    const gchar *alias)\n{\n\tstruct telepathy_buddy *buddy = g_hash_table_lookup(contact_list->buddy_handles,\n\t\t\t\t\t\t\t    GUINT_TO_POINTER(contact));\n\tupdate_alias(buddy, alias);\n\n\t/* tell core about the alias change */\n\tif (buddy) {\n\t\tstruct sipe_backend_private *telepathy_private = sipe_telepathy_connection_private(G_OBJECT(contact_list->connection));\n\t\tsipe_core_group_set_alias(telepathy_private->public,\n\t\t\t\t\t  buddy->uri,\n\t\t\t\t\t  alias);\n\t}\n}\n\n/* get photo hash for a contact */\nconst gchar *sipe_telepathy_buddy_get_hash(struct _SipeContactList *contact_list,\n\t\t\t\t\t   const guint contact)\n{\n\tstruct telepathy_buddy *buddy = g_hash_table_lookup(contact_list->buddy_handles,\n\t\t\t\t\t\t\t    GUINT_TO_POINTER(contact));\n\tif (!buddy)\n\t\treturn(NULL);\n\treturn(buddy->hash);\n}\n\n/* get presence status for a contact */\nguint sipe_telepathy_buddy_get_presence(SipeContactList *contact_list,\n\t\t\t\t\tconst TpHandle contact)\n{\n\tstruct telepathy_buddy *buddy = g_hash_table_lookup(contact_list->buddy_handles,\n\t\t\t\t\t\t\t    GUINT_TO_POINTER(contact));\n\tif (!buddy)\n\t\treturn(SIPE_ACTIVITY_UNSET);\n\treturn(buddy->activity);\n}\n\n/* @TODO: are other MIME types supported by OCS? */\nstatic const char * mimetypes[] = {\n\t\"image/jpeg\",\n\tNULL\n};\n\n/* @TODO: are these correct or even needed? */\n#define AVATAR_MIN_PX       16\n#define AVATAR_MAX_PX      256\n#define AVATAR_MAX_BYTES 32768\n\nstatic void get_avatar_requirements(TpSvcConnectionInterfaceAvatars *iface,\n\t\t\t\t    DBusGMethodInvocation *context)\n{\n\tTP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED(TP_BASE_CONNECTION(iface),\n\t\t\t\t\t\t  context);\n\n\ttp_svc_connection_interface_avatars_return_from_get_avatar_requirements(\n\t\tcontext,\n\t\tmimetypes,\n\t\tAVATAR_MIN_PX, AVATAR_MIN_PX,\n\t\tAVATAR_MAX_PX, AVATAR_MAX_PX,\n\t\tAVATAR_MAX_BYTES);\n}\n\nvoid sipe_telepathy_avatars_iface_init(gpointer g_iface,\n\t\t\t\t       SIPE_UNUSED_PARAMETER gpointer iface_data)\n{\n\tTpSvcConnectionInterfaceAvatarsClass *klass = g_iface;\n\n#define IMPLEMENT(x) tp_svc_connection_interface_avatars_implement_##x( \\\n\t\tklass, x)\n\tIMPLEMENT(get_avatar_requirements);\n\t/* Information is provided by server: can't implement\n\t   IMPLEMENT(get_avatar_tokens);\n\t   IMPLEMENT(get_known_avatar_tokens);\n\t   IMPLEMENT(request_avatar);\n\t   IMPLEMENT(request_avatars);\n\t   IMPLEMENT(set_avatar);\n\t   IMPLEMENT(clear_avatar); */\n#undef IMPLEMENT\n}\n\nstatic const gchar *const sipe_to_vcard_field[SIPE_INFO_FIELD_MAX] = {\n/* SIPE_BUDDY_INFO_DISPLAY_NAME          */ \"fn\",\n/* SIPE_BUDDY_INFO_JOB_TITLE             */ \"title\",\n/* SIPE_BUDDY_INFO_CITY                  */ NULL,\n/* SIPE_BUDDY_INFO_STATE                 */ NULL,\n/* SIPE_BUDDY_INFO_OFFICE                */ NULL,\n/* SIPE_BUDDY_INFO_DEPARTMENT            */ NULL,\n/* SIPE_BUDDY_INFO_COUNTRY               */ NULL,\n/* SIPE_BUDDY_INFO_WORK_PHONE            */ \"tel\",\n/* SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY    */ NULL,\n/* SIPE_BUDDY_INFO_COMPANY               */ \"org\",\n/* SIPE_BUDDY_INFO_EMAIL                 */ \"email\",\n/* SIPE_BUDDY_INFO_SITE                  */ NULL,\n/* SIPE_BUDDY_INFO_ZIPCODE               */ NULL,\n/* SIPE_BUDDY_INFO_STREET                */ NULL,\n/* SIPE_BUDDY_INFO_MOBILE_PHONE          */ NULL,\n/* SIPE_BUDDY_INFO_MOBILE_PHONE_DISPLAY  */ NULL,\n/* SIPE_BUDDY_INFO_HOME_PHONE            */ NULL,\n/* SIPE_BUDDY_INFO_HOME_PHONE_DISPLAY    */ NULL,\n/* SIPE_BUDDY_INFO_OTHER_PHONE           */ NULL,\n/* SIPE_BUDDY_INFO_OTHER_PHONE_DISPLAY   */ NULL,\n/* SIPE_BUDDY_INFO_CUSTOM1_PHONE         */ NULL,\n/* SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY */ NULL,\n};\n\nstatic GPtrArray *convert_contact_info(struct telepathy_buddy *buddy)\n{\n\tGPtrArray *info = NULL;\n\n\tif (buddy) {\n\t\tguint i;\n\n\t\tinfo = dbus_g_type_specialized_construct(\n\t\t\tTP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST);\n\n\t\tfor (i = 0; i < SIPE_INFO_FIELD_MAX; i++) {\n\t\t\tconst gchar *name  = sipe_to_vcard_field[i];\n\t\t\tconst gchar *value = buddy->info[i];\n\n\t\t\tif (name && value) {\n\t\t\t\tconst gchar *const field_values[2] = { value, NULL };\n\n\t\t\t\tSIPE_DEBUG_INFO(\"SipeContactInfo::convert_contact_info: %s: (%2d)%s = '%s'\",\n\t\t\t\t\t\tbuddy->uri, i, name, value);\n\n\t\t\t\tg_ptr_array_add(info,\n\t\t\t\t\t\ttp_value_array_build(3,\n\t\t\t\t\t\t\t\t     G_TYPE_STRING, name,\n\t\t\t\t\t\t\t\t     G_TYPE_STRV,   NULL,\n\t\t\t\t\t\t\t\t     G_TYPE_STRV,   field_values,\n\t\t\t\t\t\t\t\t     G_TYPE_INVALID));\n\t\t\t}\n\t\t}\n\t}\n\n\treturn(info);\n}\n\nstatic void get_contact_info(TpSvcConnectionInterfaceContactInfo *iface,\n\t\t\t     const GArray *contacts,\n\t\t\t     DBusGMethodInvocation *context)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_telepathy_connection_private(G_OBJECT(iface));\n\tGHashTable *buddies     = telepathy_private->contact_list->buddy_handles;\n\tTpBaseConnection *base  = TP_BASE_CONNECTION(iface);\n\tTpHandleRepoIface *repo = tp_base_connection_get_handles(base,\n\t\t\t\t\t\t\t\t TP_HANDLE_TYPE_CONTACT);\n\tGError *error           = NULL;\n\tGHashTable *infos;\n\tguint i;\n\n\tTP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED(base, context);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeContactInfo::get_contact_info called\");\n\n\tif (!tp_handles_are_valid(repo, contacts, FALSE, &error)) {\n\t\tdbus_g_method_return_error(context, error);\n\t\tg_error_free(error);\n\t\treturn;\n\t}\n\n\tinfos = dbus_g_type_specialized_construct(TP_HASH_TYPE_CONTACT_INFO_MAP);\n\n\tfor (i = 0; i < contacts->len; i++) {\n\t\tTpHandle contact = g_array_index(contacts, TpHandle, i);\n\t\tstruct telepathy_buddy *buddy = g_hash_table_lookup(buddies,\n\t\t\t\t\t\t\t\t    GUINT_TO_POINTER(contact));\n\t\tGPtrArray *info  = convert_contact_info(buddy);\n\n\t\tif (info)\n\t\t\tg_hash_table_insert(infos,\n\t\t\t\t\t    GUINT_TO_POINTER(contact),\n\t\t\t\t\t    info);\n\t}\n\n\ttp_svc_connection_interface_contact_info_return_from_get_contact_info(context,\n\t\t\t\t\t\t\t\t\t      infos);\n\tg_boxed_free(TP_HASH_TYPE_CONTACT_INFO_MAP, infos);\n}\n\nstatic void request_contact_info(TpSvcConnectionInterfaceContactInfo *iface,\n\t\t\t\t guint contact,\n\t\t\t\t DBusGMethodInvocation *context)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_telepathy_connection_private(G_OBJECT(iface));\n\tstruct telepathy_buddy *buddy = g_hash_table_lookup(telepathy_private->contact_list->buddy_handles,\n\t\t\t\t\t\t\t    GUINT_TO_POINTER(contact));\n\tTpBaseConnection *base  = TP_BASE_CONNECTION(iface);\n\tTpHandleRepoIface *repo = tp_base_connection_get_handles(base,\n\t\t\t\t\t\t\t\t TP_HANDLE_TYPE_CONTACT);\n\tGError *error           = NULL;\n\tGPtrArray *info;\n\n\tTP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED(base, context);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeContactInfo::request_contact_info called\");\n\n\tif (!tp_handle_is_valid(repo, contact, &error)) {\n\t\tdbus_g_method_return_error(context, error);\n\t\tg_error_free(error);\n\t\treturn;\n\t}\n\n\tinfo  = convert_contact_info(buddy);\n\tif (!info) {\n\t\tdbus_g_method_return_error(context, error);\n\t\tif (error)\n\t\t\tg_error_free(error);\n\t\treturn;\n\t}\n\n\ttp_svc_connection_interface_contact_info_return_from_request_contact_info(context,\n\t\t\t\t\t\t\t\t\t\t  info);\n\tg_boxed_free(TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST, info);\n}\n\nvoid sipe_telepathy_contact_info_iface_init(gpointer g_iface,\n\t\t\t\t\t    SIPE_UNUSED_PARAMETER gpointer iface_data)\n{\n\tTpSvcConnectionInterfaceContactInfoClass *klass = g_iface;\n\n#define IMPLEMENT(x) tp_svc_connection_interface_contact_info_implement_##x( \\\n\t\tklass, x)\n\tIMPLEMENT(get_contact_info);\n\t/* Information is provided by the server: can't implement\n\t   IMPLEMENT(refresh_contact_info); */\n\tIMPLEMENT(request_contact_info);\n\t/* Information is provided by the server: can't implement\n\t   IMPLEMENT(set_contact_info); */\n#undef IMPLEMENT\n}\n\nGPtrArray *sipe_telepathy_contact_info_fields(void)\n{\n\tGPtrArray *fields = dbus_g_type_specialized_construct(TP_ARRAY_TYPE_FIELD_SPECS);\n\tguint i;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeContactInfo::contact_info_fields called\");\n\n\tfor (i = 0; i <= SIPE_BUDDY_INFO_CUSTOM1_PHONE_DISPLAY; i++) {\n\t\tconst gchar *vcard_name       = sipe_to_vcard_field[i];\n\t\tGValueArray *va;\n\n\t\t/* unsupported field */\n\t\tif (!vcard_name)\n\t\t\tcontinue;\n\n\t\tva = tp_value_array_build(4,\n\t\t\t\t\t  G_TYPE_STRING, vcard_name,\n\t\t\t\t\t  G_TYPE_STRV,   NULL,\n\t\t\t\t\t  G_TYPE_UINT,   0, /* tp_flags  */\n\t\t\t\t\t  G_TYPE_UINT,   1, /* max_times */\n\t\t\t\t\t  G_TYPE_INVALID);\n\t\tg_ptr_array_add (fields, va);\n\t}\n\n\treturn(fields);\n}\n\n/* TpDBusPropertiesMixinPropImpl is a broken typedef */\ngpointer sipe_telepathy_contact_info_props(void)\n{\n\tstatic TpDBusPropertiesMixinPropImpl props[] = {\n\t\t{\n\t\t\t.name        = \"ContactInfoFlags\",\n\t\t\t.getter_data = GUINT_TO_POINTER(0),\n\t\t\t/* @TODO .getter_data = GUINT_TO_POINTER(TP_CONTACT_INFO_FLAG_CAN_SET), */\n\t\t\t.setter_data = NULL,\n\t\t},\n\t\t{\n\t\t\t.name        = \"SupportedFields\",\n\t\t\t.getter_data = NULL,\n\t\t\t.setter_data = NULL,\n\t\t},\n\t\t{\n\t\t\t.name        = NULL\n\t\t}\n\t};\n\treturn(props);\n}\n\n/*\n * Backend adaptor functions\n */\nsipe_backend_buddy sipe_backend_buddy_find(struct sipe_core_public *sipe_public,\n\t\t\t\t\t   const gchar *buddy_name,\n\t\t\t\t\t   const gchar *group_name)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_public->backend_private;\n\tstruct telepathy_buddy *buddy                  = g_hash_table_lookup(telepathy_private->contact_list->buddies,\n\t\t\t\t\t\t\t\t\t     buddy_name);\n\tif (!buddy)\n\t\treturn(NULL);\n\n\tif (group_name) {\n\t\treturn(g_hash_table_lookup(buddy->groups, group_name));\n\t} else {\n\t\t/* just return the first entry */\n\t\tGHashTableIter iter;\n\t\tgpointer value = NULL;\n\t\tg_hash_table_iter_init(&iter, buddy->groups);\n\t\t/* make Coverity happy: as buddy != NULL this can't fail */\n\t\t(void) g_hash_table_iter_next(&iter, NULL, &value);\n\t\treturn(value);\n\t}\n}\n\nstatic GSList *buddy_add_all(struct telepathy_buddy *buddy, GSList *list)\n{\n\tGHashTableIter iter;\n\tstruct telepathy_buddy_entry *buddy_entry;\n\n\tif (!buddy)\n\t\treturn(list);\n\n\tg_hash_table_iter_init(&iter, buddy->groups);\n\twhile (g_hash_table_iter_next(&iter, NULL, (gpointer) &buddy_entry))\n\t\tlist = g_slist_prepend(list, buddy_entry);\n\n\treturn(list);\n}\n\nGSList *sipe_backend_buddy_find_all(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t    const gchar *buddy_name,\n\t\t\t\t    const gchar *group_name)\n{\n\tGSList *result = NULL;\n\n\t/* NOTE: group_name != NULL not implemented in purple either */\n\tif (!group_name) {\n\t\tstruct sipe_backend_private *telepathy_private = sipe_public->backend_private;\n\t\tGHashTable *buddies                            = telepathy_private->contact_list->buddies;\n\n\t\tif (buddy_name) {\n\t\t\tresult = buddy_add_all(g_hash_table_lookup(buddies,\n\t\t\t\t\t\t\t\t   buddy_name),\n\t\t\t\t\t       result);\n\t\t} else {\n\t\t\tGHashTableIter biter;\n\t\t\tstruct telepathy_buddy *buddy;\n\n\t\t\tg_hash_table_iter_init(&biter, telepathy_private->contact_list->buddies);\n\t\t\twhile (g_hash_table_iter_next(&biter, NULL, (gpointer) &buddy))\n\t\t\t\tresult = buddy_add_all(buddy, result);\n\t\t}\n\t}\n\n\treturn(result);\n}\n\ngchar *sipe_backend_buddy_get_name(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t   const sipe_backend_buddy who)\n{\n\treturn(g_strdup(((struct telepathy_buddy_entry *) who)->buddy->uri));\n}\n\ngchar *sipe_backend_buddy_get_alias(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t    const sipe_backend_buddy who)\n{\n\treturn(g_strdup(((struct telepathy_buddy_entry *) who)->buddy->info[SIPE_BUDDY_INFO_DISPLAY_NAME]));\n}\n\ngchar *sipe_backend_buddy_get_server_alias(struct sipe_core_public *sipe_public,\n\t\t\t\t\t   const sipe_backend_buddy who)\n{\n\t/* server alias is the same as alias */\n\treturn(sipe_backend_buddy_get_alias(sipe_public, who));\n}\n\ngchar *sipe_backend_buddy_get_local_alias(struct sipe_core_public *sipe_public,\n\t\t\t\t\t  const sipe_backend_buddy who)\n{\n\t/* server alias is the same as alias */\n\treturn(sipe_backend_buddy_get_alias(sipe_public, who));\n}\n\ngchar *sipe_backend_buddy_get_group_name(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t const sipe_backend_buddy who)\n{\n\treturn(g_strdup(((struct telepathy_buddy_entry *) who)->group));\n}\n\ngchar *sipe_backend_buddy_get_string(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t     sipe_backend_buddy who,\n\t\t\t\t     const sipe_buddy_info_fields key)\n{\n\tstruct telepathy_buddy_entry *buddy_entry = who;\n\tstruct telepathy_buddy *buddy             = buddy_entry->buddy;\n\n\tif (key >= SIPE_INFO_FIELD_MAX)\n\t\treturn(NULL);\n\treturn(g_strdup(buddy->info[key]));\n}\n\nvoid sipe_backend_buddy_set_string(struct sipe_core_public *sipe_public,\n\t\t\t\t   sipe_backend_buddy who,\n\t\t\t\t   const sipe_buddy_info_fields key,\n\t\t\t\t   const gchar *val)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_public->backend_private;\n\tSipeContactList *contact_list                  = telepathy_private->contact_list;\n\tstruct telepathy_buddy_entry *buddy_entry      = who;\n\tstruct telepathy_buddy *buddy                  = buddy_entry->buddy;\n\n\tif (key >= SIPE_INFO_FIELD_MAX)\n\t\treturn;\n\n\tSIPE_DEBUG_INFO(\"sipe_backend_buddy_set_string: %s replacing info %d: %s -> %s\",\n\t\t\tbuddy->uri, key,\n\t\t\tbuddy->info[key] ? buddy->info[key]: \"<UNDEFINED>\",\n\t\t\tval);\n\n\tg_free(buddy->info[key]);\n\tbuddy->info[key] = g_strdup(val);\n\n\tif (contact_list->initial_received) {\n\t\t/* @TODO: emit signal? */\n\t}\n}\n\nvoid sipe_backend_buddy_refresh_properties(struct sipe_core_public *sipe_public,\n\t\t\t\t\t   const gchar *uri)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_public->backend_private;\n\tstruct telepathy_buddy *buddy                  = g_hash_table_lookup(telepathy_private->contact_list->buddies,\n\t\t\t\t\t\t\t\t\t     uri);\n\tGPtrArray *info                                = convert_contact_info(buddy);\n\n\tif (info) {\n\t\ttp_svc_connection_interface_contact_info_emit_contact_info_changed(telepathy_private->connection,\n\t\t\t\t\t\t\t\t\t\t   buddy->handle,\n\t\t\t\t\t\t\t\t\t\t   info);\n\t\tg_boxed_free(TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST, info);\n\t}\n}\n\nguint sipe_backend_buddy_get_status(struct sipe_core_public *sipe_public,\n\t\t\t\t    const gchar *uri)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_public->backend_private;\n\tstruct telepathy_buddy *buddy                  = g_hash_table_lookup(telepathy_private->contact_list->buddies,\n\t\t\t\t\t\t\t\t\t     uri);\n\n\tif (!buddy)\n\t\treturn(SIPE_ACTIVITY_UNSET);\n\treturn(buddy->activity);\n}\n\nvoid sipe_backend_buddy_set_alias(struct sipe_core_public *sipe_public,\n\t\t\t\t  const sipe_backend_buddy who,\n\t\t\t\t  const gchar *alias)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_public->backend_private;\n\tSipeContactList *contact_list                  = telepathy_private->contact_list;\n\tstruct telepathy_buddy_entry *buddy_entry      = who;\n\tstruct telepathy_buddy *buddy                  = buddy_entry->buddy;\n\n\tupdate_alias(buddy, alias);\n\n\tif (contact_list->initial_received) {\n\t\tSIPE_DEBUG_INFO(\"sipe_backend_buddy_set_alias: %s changed to '%s'\",\n\t\t\t\tbuddy->uri, alias);\n\t\tsipe_telepathy_connection_alias_updated(contact_list->connection,\n\t\t\t\t\t\t        buddy->handle,\n\t\t\t\t\t\t\talias);\n\t}\n}\n\nvoid sipe_backend_buddy_set_server_alias(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t SIPE_UNUSED_PARAMETER const sipe_backend_buddy who,\n\t\t\t\t\t SIPE_UNUSED_PARAMETER const gchar *alias)\n{\n\t/* server alias is the same as alias. Ignore this */\n}\n\nvoid sipe_backend_buddy_list_processing_finish(struct sipe_core_public *sipe_public)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_public->backend_private;\n\tSipeContactList *contact_list                  = telepathy_private->contact_list;\n\n\tif (!contact_list->initial_received) {\n\t\t/* we can only call this once */\n\t\tcontact_list->initial_received = TRUE;\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_backend_buddy_list_processing_finish called\");\n\t\ttp_base_contact_list_set_list_received(TP_BASE_CONTACT_LIST(contact_list));\n\t}\n}\n\nstatic void buddy_free(gpointer data)\n{\n\tstruct telepathy_buddy *buddy = data;\n\tguint i;\n\tg_hash_table_destroy(buddy->groups);\n\tfor (i = 0; i < SIPE_INFO_FIELD_MAX; i++)\n\t\tg_free(buddy->info[i]);\n\tg_free(buddy->hash);\n\tg_free(buddy);\n}\n\nsipe_backend_buddy sipe_backend_buddy_add(struct sipe_core_public *sipe_public,\n\t\t\t\t\t  const gchar *name,\n\t\t\t\t\t  const gchar *alias,\n\t\t\t\t\t  const gchar *group_name)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_public->backend_private;\n\tSipeContactList *contact_list                  = telepathy_private->contact_list;\n\tconst gchar *group                             = g_hash_table_lookup(contact_list->groups,\n\t\t\t\t\t\t\t\t\t     group_name);\n\tstruct telepathy_buddy *buddy                  = g_hash_table_lookup(contact_list->buddies,\n\t\t\t\t\t\t\t\t\t     name);\n\tstruct telepathy_buddy_entry *buddy_entry;\n\n\tif (!group)\n\t\treturn(NULL);\n\n\tif (!buddy) {\n\t\tbuddy           = g_new0(struct telepathy_buddy, 1);\n\t\tbuddy->uri      = g_strdup(name); /* reused as key */\n\t\tbuddy->groups   = g_hash_table_new_full(g_str_hash, g_str_equal,\n\t\t\t\t\t\t\tNULL, g_free);\n\t\tbuddy->info[SIPE_BUDDY_INFO_DISPLAY_NAME] = g_strdup(alias);\n\t\tbuddy->hash     = NULL;\n\t\tbuddy->activity = SIPE_ACTIVITY_OFFLINE;\n\t\tbuddy->handle   = tp_handle_ensure(contact_list->contact_repo,\n\t\t\t\t\t\t   buddy->uri, NULL, NULL);\n\t\ttp_handle_set_add(contact_list->contacts, buddy->handle);\n\t\tg_hash_table_insert(contact_list->buddies,\n\t\t\t\t    (gchar *) buddy->uri, /* owned by hash table */\n\t\t\t\t    buddy);\n\t\tg_hash_table_insert(contact_list->buddy_handles,\n\t\t\t\t    GUINT_TO_POINTER(buddy->handle),\n\t\t\t\t    buddy);\n\t}\n\n\tbuddy_entry = g_hash_table_lookup(buddy->groups, group);\n\tif (!buddy_entry) {\n\t\tbuddy_entry        = g_new0(struct telepathy_buddy_entry, 1);\n\t\tbuddy_entry->buddy = buddy;\n\t\tbuddy_entry->group = group;\n\t\tg_hash_table_insert(buddy->groups,\n\t\t\t\t    (gchar *) group, /* key is borrowed */\n\t\t\t\t    buddy_entry);\n\t}\n\n\tif (contact_list->initial_received) {\n\t\t/* @TODO: emit signal? */\n\t}\n\n\treturn(buddy_entry);\n}\n\nvoid sipe_backend_buddy_remove(struct sipe_core_public *sipe_public,\n\t\t\t       const sipe_backend_buddy who)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_public->backend_private;\n\tSipeContactList *contact_list                  = telepathy_private->contact_list;\n\tstruct telepathy_buddy_entry *remove_entry     = who;\n\tstruct telepathy_buddy       *buddy            = remove_entry->buddy;\n\n\tg_hash_table_remove(buddy->groups,\n\t\t\t    remove_entry->group);\n\t/* remove_entry is invalid */\n\n\tif (g_hash_table_size(buddy->groups) == 0) {\n\t\t/* removed from last group -> drop this buddy */\n\t\ttp_handle_set_remove(contact_list->contacts,\n\t\t\t\t     buddy->handle);\n\t\tg_hash_table_remove(contact_list->buddy_handles,\n\t\t\t\t    GUINT_TO_POINTER(buddy->handle));\n\t\tg_hash_table_remove(contact_list->buddies,\n\t\t\t\t    buddy->uri);\n\n\t}\n\n\tif (contact_list->initial_received) {\n\t\t/* @TODO: emit signal? */\n\t}\n}\n\nvoid sipe_backend_buddy_set_status(struct sipe_core_public *sipe_public,\n\t\t\t\t   const gchar *uri,\n\t\t\t\t   guint activity,\n\t                           SIPE_UNUSED_PARAMETER time_t last_active)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_public->backend_private;\n\tSipeContactList *contact_list                  = telepathy_private->contact_list;\n\tstruct telepathy_buddy *buddy                  = g_hash_table_lookup(contact_list->buddies,\n\t\t\t\t\t\t\t\t\t     uri);\n\tTpPresenceStatus *status;\n\n\tif (!buddy)\n\t\treturn;\n\tbuddy->activity = activity;\n\n\tSIPE_DEBUG_INFO(\"sipe_backend_buddy_set_status: %s to %d\", uri, activity);\n\n\t/* emit status update signal */\n\tstatus = tp_presence_status_new(activity, NULL);\n\ttp_presence_mixin_emit_one_presence_update(G_OBJECT(telepathy_private->connection),\n\t\t\t\t\t\t   buddy->handle, status);\n\ttp_presence_status_free(status);\n}\n\ngboolean sipe_backend_uses_photo(void)\n{\n\treturn(TRUE);\n}\n\nstatic void buddy_photo_updated(struct sipe_backend_private *telepathy_private,\n\t\t\t\tstruct telepathy_buddy *buddy,\n\t\t\t\tconst gchar *photo,\n\t\t\t\tgsize photo_len)\n{\n\tGArray *array = g_array_new(FALSE, FALSE, sizeof(gchar));\n\n\tSIPE_DEBUG_INFO(\"buddy_photo_updated: %s (%\" G_GSIZE_FORMAT \")\",\n\t\t\tbuddy->uri, photo_len);\n\n\tg_array_append_vals(array, photo, photo_len);\n\n\ttp_svc_connection_interface_avatars_emit_avatar_updated(telepathy_private->connection,\n\t\t\t\t\t\t\t\tbuddy->handle,\n\t\t\t\t\t\t\t\tbuddy->hash);\n\ttp_svc_connection_interface_avatars_emit_avatar_retrieved(telepathy_private->connection,\n\t\t\t\t\t\t\t\t  buddy->handle,\n\t\t\t\t\t\t\t\t  buddy->hash,\n\t\t\t\t\t\t\t\t  array,\n\t\t\t\t\t\t\t\t  /* @TODO: is this correct? */\n\t\t\t\t\t\t\t\t  \"image/jpeg\");\n\tg_array_unref(array);\n}\n\nvoid sipe_backend_buddy_set_photo(struct sipe_core_public *sipe_public,\n\t\t\t\t  const gchar *uri,\n\t\t\t\t  gpointer image_data,\n\t\t\t\t  gsize image_len,\n\t\t\t\t  const gchar *photo_hash)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_public->backend_private;\n\tstruct telepathy_buddy *buddy                  = g_hash_table_lookup(telepathy_private->contact_list->buddies,\n\t\t\t\t\t\t\t\t\t     uri);\n\n\tif (buddy) {\n\t\tgchar *hash_file = g_build_filename(telepathy_private->cache_dir,\n\t\t\t\t\t\t    uri,\n\t\t\t\t\t\t    NULL);\n\n\t\t/* does this buddy already have a photo? -> delete it */\n\t\tif (buddy->hash) {\n\t\t\tchar *photo_file = g_build_filename(telepathy_private->cache_dir,\n\t\t\t\t\t\t\t    buddy->hash,\n\t\t\t\t\t\t\t    NULL);\n\t\t\t(void) g_remove(photo_file);\n\t\t\tg_free(photo_file);\n\t\t\tg_free(buddy->hash);\n\t\t\tbuddy->hash = NULL;\n\t\t}\n\n\t\t/* update hash file */\n\t\tif (g_file_set_contents(hash_file,\n\t\t\t\t\tphoto_hash,\n\t\t\t\t\tstrlen(photo_hash),\n\t\t\t\t\tNULL)) {\n\t\t\tgchar *photo_file = g_build_filename(telepathy_private->cache_dir,\n\t\t\t\t\t\t\t     photo_hash,\n\t\t\t\t\t\t\t     NULL);\n\t\t\tbuddy->hash = g_strdup(photo_hash);\n\t\t\tg_file_set_contents(photo_file,\n\t\t\t\t\t    image_data,\n\t\t\t\t\t    image_len,\n\t\t\t\t\t    NULL);\n\n\t\t\tbuddy_photo_updated(telepathy_private,\n\t\t\t\t\t    buddy,\n\t\t\t\t\t    image_data,\n\t\t\t\t\t    image_len);\n\n\t\t\tg_free(photo_file);\n\t\t}\n\n\t\tg_free(hash_file);\n\t}\n\n\tg_free(image_data);\n}\n\nconst gchar *sipe_backend_buddy_get_photo_hash(struct sipe_core_public *sipe_public,\n\t\t\t\t\t       const gchar *uri)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_public->backend_private;\n\tstruct telepathy_buddy *buddy                  = g_hash_table_lookup(telepathy_private->contact_list->buddies,\n\t\t\t\t\t\t\t\t\t     uri);\n\n\tif (!buddy)\n\t\treturn(NULL);\n\n\tif (!buddy->hash) {\n\t\tgchar *hash_file = g_build_filename(telepathy_private->cache_dir,\n\t\t\t\t\t\t    uri,\n\t\t\t\t\t\t    NULL);\n\t\t/* returned memory is owned & freed by buddy */\n\t\tif (g_file_get_contents(hash_file, &buddy->hash, NULL, NULL)) {\n\t\t\tgchar *photo_file = g_build_filename(telepathy_private->cache_dir,\n\t\t\t\t\t\t\t    buddy->hash,\n\t\t\t\t\t\t\t    NULL);\n\t\t\tgchar *image_data = NULL;\n\t\t\tgsize image_len;\n\n\t\t\tif (g_file_get_contents(photo_file,\n\t\t\t\t\t\t&image_data,\n\t\t\t\t\t\t&image_len,\n\t\t\t\t\t\tNULL))\n\t\t\t\tbuddy_photo_updated(telepathy_private,\n\t\t\t\t\t\t    buddy,\n\t\t\t\t\t\t    image_data,\n\t\t\t\t\t\t    image_len);\n\t\t\tg_free(image_data);\n\t\t\tg_free(photo_file);\n\t\t}\n\t\tg_free(hash_file);\n\t}\n\n\treturn(buddy->hash);\n}\n\ngboolean sipe_backend_buddy_group_add(struct sipe_core_public *sipe_public,\n\t\t\t\t      const gchar *group_name)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_public->backend_private;\n\tSipeContactList *contact_list                  = telepathy_private->contact_list;\n\tgchar *group                                   = g_hash_table_lookup(contact_list->groups,\n\t\t\t\t\t\t\t\t\t     group_name);\n\n\tif (!group) {\n\t\tgroup = g_strdup(group_name);\n\t\tg_hash_table_insert(contact_list->groups, group, group);\n\t\ttp_base_contact_list_groups_created(TP_BASE_CONTACT_LIST(contact_list),\n\t\t\t\t\t\t    &group_name,\n\t\t\t\t\t\t    1);\n\t}\n\n\treturn(group != NULL);\n}\n\nvoid sipe_backend_buddy_group_remove(struct sipe_core_public *sipe_public,\n\t\t\t\t     const gchar *group_name)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_public->backend_private;\n\tSipeContactList *contact_list                  = telepathy_private->contact_list;\n\n\tg_hash_table_remove(contact_list->groups, group_name);\n\n\tif (contact_list->initial_received) {\n\t\t/* @TODO: emit signal? */\n\t}\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/telepathy/telepathy-connection.c",
    "content": "/**\n * @file telepathy-connection.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2012-2017 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <string.h>\n#include <sys/stat.h>\n\n#include <glib-object.h>\n#include <glib/gstdio.h>\n#include <telepathy-glib/base-connection.h>\n#include <telepathy-glib/base-protocol.h>\n#include <telepathy-glib/contacts-mixin.h>\n#include <telepathy-glib/handle-repo-dynamic.h>\n#include <telepathy-glib/presence-mixin.h>\n#include <telepathy-glib/simple-password-manager.h>\n#include <telepathy-glib/telepathy-glib.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n\n#include \"telepathy-private.h\"\n\nG_BEGIN_DECLS\n/*\n * Connection class - data structures\n */\ntypedef struct _SipeConnectionClass {\n\tTpBaseConnectionClass parent_class;\n\tTpDBusPropertiesMixinClass properties_mixin;\n\tTpContactsMixinClass contacts_mixin;\n\tTpPresenceMixinClass presence_mixin;\n} SipeConnectionClass;\n\ntypedef struct _SipeConnection {\n\tTpBaseConnection parent;\n\tTpContactsMixinClass contacts_mixin;\n\tTpPresenceMixin presence_mixin;\n\n\t/* channel managers */\n\tTpSimplePasswordManager *password_manager;\n\tstruct _SipeContactList *contact_list;\n\tstruct _SipeTLSManager  *tls_manager;\n\n\tstruct sipe_backend_private private;\n\tgchar *account;\n\tgchar *login;\n\tgchar *password;\n\tgchar *server;\n\tgchar *port;\n\tguint  transport;\n\tguint  authentication_type;\n\tgchar *user_agent;\n\tgchar *authentication;\n\tgboolean sso;\n\tgboolean dont_publish;\n\tgboolean allow_web_photo;\n\tgboolean is_disconnecting;\n\n\tGPtrArray *contact_info_fields;\n} SipeConnection;\n\n#define SIPE_PUBLIC_TO_CONNECTION sipe_public->backend_private->connection\n\n/*\n * Connection class - type macros\n */\nstatic GType sipe_connection_get_type(void) G_GNUC_CONST;\n#define SIPE_TYPE_CONNECTION \\\n\t(sipe_connection_get_type())\n#define SIPE_CONNECTION(obj) \\\n\t(G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_CONNECTION, \\\n\t\t\t\t    SipeConnection))\nG_END_DECLS\n\n/*\n * Connection class - type definition\n */\nstatic void init_aliasing (gpointer, gpointer);\nG_DEFINE_TYPE_WITH_CODE(SipeConnection,\n\t\t\tsipe_connection,\n\t\t\tTP_TYPE_BASE_CONNECTION,\n\t\t\tG_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING,\n\t\t\t\t\t      init_aliasing);\n\t\t\tG_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_AVATARS,\n\t\t\t\t\t      sipe_telepathy_avatars_iface_init);\n\t\t\tG_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACTS,\n\t\t\t\t\t      tp_contacts_mixin_iface_init);\n\t\t\tG_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_GROUPS,\n\t\t\t\t\t      tp_base_contact_list_mixin_groups_iface_init);\n\t\t\tG_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_INFO,\n\t\t\t\t\t      sipe_telepathy_contact_info_iface_init);\n\t\t\tG_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_LIST,\n\t\t\t\t\t      tp_base_contact_list_mixin_list_iface_init);\n\t\t\tG_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_PRESENCE,\n\t\t\t\t\t      tp_presence_mixin_iface_init);\n\t\t\tG_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_SIMPLE_PRESENCE,\n\t\t\t\t\t      tp_presence_mixin_simple_presence_iface_init);\n\t\t\tG_IMPLEMENT_INTERFACE(TP_TYPE_SVC_DBUS_PROPERTIES,\n\t\t\t\t\t      tp_dbus_properties_mixin_iface_init);\n)\n\n\n/*\n * Connection class - instance methods\n */\nstatic gchar *normalize_contact(SIPE_UNUSED_PARAMETER TpHandleRepoIface *repo,\n\t\t\t\tconst gchar *id,\n\t\t\t\tSIPE_UNUSED_PARAMETER gpointer context,\n\t\t\t\tGError **error)\n{\n\treturn(sipe_telepathy_protocol_normalize_contact(NULL, id, error));\n}\n\nstatic void create_handle_repos(SIPE_UNUSED_PARAMETER TpBaseConnection *conn,\n\t\t\t\tTpHandleRepoIface *repos[NUM_TP_HANDLE_TYPES])\n{\n\trepos[TP_HANDLE_TYPE_CONTACT] = tp_dynamic_handle_repo_new(TP_HANDLE_TYPE_CONTACT,\n\t\t\t\t\t\t\t\t   normalize_contact,\n\t\t\t\t\t\t\t\t   NULL);\n}\n\nstatic gboolean connect_to_core(SipeConnection *self,\n\t\t\t\tGError **error)\n{\n\tstruct sipe_core_public *sipe_public;\n\tconst gchar *errmsg;\n\n\tsipe_public = sipe_core_allocate(self->account,\n\t\t\t\t\t self->sso,\n\t\t\t\t\t self->login,\n\t\t\t\t\t self->password,\n\t\t\t\t\t NULL, /* @TODO: email     */\n\t\t\t\t\t NULL, /* @TODO: email_url */\n\t\t\t\t\t &errmsg);\n\n\tSIPE_DEBUG_INFO(\"connect_to_core: created %p\", sipe_public);\n\n\tif (sipe_public) {\n\t\tstruct sipe_backend_private *telepathy_private = &self->private;\n\n\t\t/* initialize backend private data */\n\t\tsipe_public->backend_private    = telepathy_private;\n\t\ttelepathy_private->public       = sipe_public;\n\t\ttelepathy_private->contact_list = self->contact_list;\n\t\ttelepathy_private->connection   = self;\n\t\ttelepathy_private->activity     = SIPE_ACTIVITY_UNSET;\n\t\ttelepathy_private->cache_dir    = g_build_path(G_DIR_SEPARATOR_S,\n\t\t\t\t\t\t\t       g_get_user_cache_dir(),\n\t\t\t\t\t\t\t       \"telepathy\",\n\t\t\t\t\t\t\t       \"sipe\",\n\t\t\t\t\t\t\t       self->account,\n\t\t\t\t\t\t\t       NULL);\n\t\ttelepathy_private->message      = NULL;\n\t\ttelepathy_private->tls_manager  = self->tls_manager;\n\t\ttelepathy_private->transport    = NULL;\n\n\t\t/* make sure cache directory exists */\n\t\tif (!g_file_test(telepathy_private->cache_dir,\n\t\t\t\t G_FILE_TEST_IS_DIR) &&\n\t\t    (g_mkdir_with_parents(telepathy_private->cache_dir,\n\t\t\t\t\t  S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)\n\t\t     == 0))\n\t\t\tSIPE_DEBUG_INFO(\"connect_to_core: created cache directory %s\",\n\t\t\t\t\ttelepathy_private->cache_dir);\n\n\t\tSIPE_CORE_FLAG_UNSET(DONT_PUBLISH);\n\t\tif (self->dont_publish)\n\t\t\tSIPE_CORE_FLAG_SET(DONT_PUBLISH);\n\t\tSIPE_CORE_FLAG_UNSET(ALLOW_WEB_PHOTO);\n\t\tif (self->allow_web_photo)\n\t\t\tSIPE_CORE_FLAG_SET(ALLOW_WEB_PHOTO);\n\n\t\tsipe_core_transport_sip_connect(sipe_public,\n\t\t\t\t\t\tself->transport,\n\t\t\t\t\t\tself->authentication_type,\n\t\t\t\t\t\tself->server,\n\t\t\t\t\t\tself->port);\n\n\t\treturn(TRUE);\n\t} else {\n\t\tg_set_error_literal(error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,\n\t\t\t\t    errmsg);\n\t\treturn(FALSE);\n\t}\n}\n\nstatic void password_manager_cb(GObject *source,\n\t\t\t\tGAsyncResult *result,\n\t\t\t\tgpointer data)\n{\n\tSipeConnection   *self  = data;\n\tTpBaseConnection *base  = TP_BASE_CONNECTION(self);\n\tGError *error           = NULL;\n\tconst GString *password = tp_simple_password_manager_prompt_finish(\n\t\tTP_SIMPLE_PASSWORD_MANAGER(source),\n\t\tresult,\n\t\t&error);\n\n\tif (password == NULL) {\n\t\tSIPE_DEBUG_ERROR(\"password_manager_cb: failed: %s\",\n\t\t\t\t error ? error->message : \"UNKNOWN\");\n\n\t\tif (base->status != TP_CONNECTION_STATUS_DISCONNECTED) {\n\t\t\ttp_base_connection_disconnect_with_dbus_error(base,\n\t\t\t\t\t\t\t\t      error ? tp_error_get_dbus_name(error->code) : \"\",\n\t\t\t\t\t\t\t\t      NULL,\n\t\t\t\t\t\t\t\t      TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED);\n\t\t}\n\t\tif (error)\n\t\t\tg_error_free(error);\n\t} else {\n\n\t\tg_free(self->password);\n\t\tself->password = g_strdup(password->str);\n\n\t\tif (!connect_to_core(self, &error)) {\n\t\t\tif (base->status != TP_CONNECTION_STATUS_DISCONNECTED) {\n\t\t\t\ttp_base_connection_disconnect_with_dbus_error(base,\n\t\t\t\t\t\t\t\t\t      tp_error_get_dbus_name(error->code),\n\t\t\t\t\t\t\t\t\t      NULL,\n\t\t\t\t\t\t\t\t\t      TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED);\n\t\t\t}\n\t\t\tg_error_free(error);\n\t\t}\n\t}\n}\n\nstatic gboolean start_connecting(TpBaseConnection *base,\n\t\t\t\t GError **error)\n{\n\tSipeConnection *self = SIPE_CONNECTION(base);\n\tgboolean        rc   = TRUE;\n\tgchar          *uri  = sipe_telepathy_protocol_normalize_contact(NULL,\n\t\t\t\t\t\t\t\t\t self->account,\n\t\t\t\t\t\t\t\t\t error);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeConnection::start_connecting\");\n\n\t/* set up mandatory self-handle */\n\tif (uri) {\n\t\tbase->self_handle = tp_handle_ensure(tp_base_connection_get_handles(base,\n\t\t\t\t\t\t\t\t\t\t    TP_HANDLE_TYPE_CONTACT),\n\t\t\t\t\t\t     uri,\n\t\t\t\t\t\t     NULL,\n\t\t\t\t\t\t     error);\n\t\tg_free(uri);\n\t\tif (!base->self_handle) {\n\t\t\tSIPE_DEBUG_ERROR(\"SipeConnection::start_connecting: self handle creation failed: %s\",\n\t\t\t\t\t (*error)->message);\n\t\t\treturn(FALSE);\n\t\t}\n\t} else {\n\t\tSIPE_DEBUG_ERROR(\"SipeConnection::start_connecting: %s\",\n\t\t\t\t (*error)->message);\n\t\treturn(FALSE);\n\t}\n\n\ttp_base_connection_change_status(base, TP_CONNECTION_STATUS_CONNECTING,\n\t\t\t\t\t TP_CONNECTION_STATUS_REASON_REQUESTED);\n\n\t/* map option list to flags - default is automatic */\n\tself->authentication_type = SIPE_AUTHENTICATION_TYPE_AUTOMATIC;\n\tif (sipe_strequal(self->authentication, \"ntlm\")) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"start_connecting: NTLM selected\");\n\t\tself->authentication_type = SIPE_AUTHENTICATION_TYPE_NTLM;\n\t} else\n#ifdef HAVE_GSSAPI_GSSAPI_H\n\tif (sipe_strequal(self->authentication, \"krb5\")) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"start_connecting: KRB5 selected\");\n\t\tself->authentication_type = SIPE_AUTHENTICATION_TYPE_KERBEROS;\n\t} else\n#endif\n\tif (sipe_strequal(self->authentication, \"tls-dsk\")) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"start_connecting: TLS-DSK selected\");\n\t\tself->authentication_type = SIPE_AUTHENTICATION_TYPE_TLS_DSK;\n\t}\n\n\t/* Only ask for a password when required */\n\tif (!sipe_core_transport_sip_requires_password(self->authentication_type,\n\t\t\t\t\t\t       self->sso) ||\n\t    (self->password && strlen(self->password)))\n\t\trc = connect_to_core(self, error);\n\telse {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeConnection::start_connecting: requesting password from user\");\n\t\ttp_simple_password_manager_prompt_async(self->password_manager,\n\t\t\t\t\t\t\tpassword_manager_cb,\n\t\t\t\t\t\t\tself);\n\t}\n\n\treturn(rc);\n}\n\nstatic gboolean disconnect_from_core(gpointer data)\n{\n\tTpBaseConnection *base                         = data;\n\tSipeConnection *self                           = SIPE_CONNECTION(base);\n\tstruct sipe_backend_private *telepathy_private = &self->private;\n\tstruct sipe_core_public *sipe_public           = telepathy_private->public;\n\n\tSIPE_DEBUG_INFO(\"disconnect_from_core: %p\", sipe_public);\n\n\tif (sipe_public)\n\t\tsipe_core_deallocate(sipe_public);\n\ttelepathy_private->public    = NULL;\n\ttelepathy_private->transport = NULL;\n\n\tg_free(telepathy_private->message);\n\ttelepathy_private->message   = NULL;\n\n\tg_free(telepathy_private->cache_dir);\n\ttelepathy_private->cache_dir = NULL;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"disconnect_from_core: core deallocated\");\n\n\t/* now it is OK to destroy the connection object */\n\ttp_base_connection_finish_shutdown(base);\n\n\treturn(FALSE);\n}\n\nstatic void shut_down(TpBaseConnection *base)\n{\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeConnection::shut_down\");\n\n\t/* this can be called synchronously, defer destruction */\n\tg_idle_add(disconnect_from_core, base);\n}\n\nstatic GPtrArray *create_channel_managers(TpBaseConnection *base)\n{\n\tSipeConnection *self = SIPE_CONNECTION(base);\n\tGPtrArray *channel_managers = g_ptr_array_new();\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeConnection::create_channel_managers\");\n\n\tself->contact_list = sipe_telepathy_contact_list_new(base);\n\tg_ptr_array_add(channel_managers, self->contact_list);\n\n\tself->password_manager = tp_simple_password_manager_new(base);\n\tg_ptr_array_add(channel_managers, self->password_manager);\n\n\tg_ptr_array_add(channel_managers, sipe_telepathy_search_new(base));\n\n\tself->tls_manager = sipe_telepathy_tls_new(base);\n\tg_ptr_array_add(channel_managers, self->tls_manager);\n\n\treturn(channel_managers);\n}\n\nstatic void aliasing_fill_contact_attributes(GObject *object,\n\t\t\t\t\t     const GArray *contacts,\n\t\t\t\t\t     GHashTable *attributes)\n{\n\tSipeConnection *self = SIPE_CONNECTION(object);\n\tguint i;\n\n\tfor (i = 0; i < contacts->len; i++) {\n\t\tTpHandle contact = g_array_index(contacts, guint, i);\n\n\t\ttp_contacts_mixin_set_contact_attribute(attributes,\n\t\t\t\t\t\t\tcontact,\n\t\t\t\t\t\t\tTP_TOKEN_CONNECTION_INTERFACE_ALIASING_ALIAS,\n\t\t\t\t\t\t\ttp_g_value_slice_new_string(\n\t\t\t\t\t\t\t\tsipe_telepathy_buddy_get_alias(self->contact_list,\n\t\t\t\t\t\t\t\t\t\t\t       contact)));\n\t}\n}\n\nstatic void avatars_fill_contact_attributes(GObject *object,\n\t\t\t\t\t    const GArray *contacts,\n\t\t\t\t\t    GHashTable *attributes)\n{\n\tSipeConnection *self = SIPE_CONNECTION(object);\n\tguint i;\n\n\tfor (i = 0; i < contacts->len; i++) {\n\t\tTpHandle contact = g_array_index(contacts, guint, i);\n\t\tconst gchar *hash = sipe_telepathy_buddy_get_hash(self->contact_list,\n\t\t\t\t\t\t\t\t  contact);\n\n\t\tif (!hash) hash = \"\";\n\t\ttp_contacts_mixin_set_contact_attribute(attributes,\n\t\t\t\t\t\t\tcontact,\n\t\t\t\t\t\t\tTP_IFACE_CONNECTION_INTERFACE_AVATARS\"/token\",\n\t\t\t\t\t\t\ttp_g_value_slice_new_string(hash));\n\t}\n}\n\nstatic void contact_info_properties_getter(GObject *object,\n\t\t\t\t\t   SIPE_UNUSED_PARAMETER GQuark interface,\n\t\t\t\t\t   GQuark name,\n\t\t\t\t\t   GValue *value,\n\t\t\t\t\t   gpointer getter_data)\n{\n\tGQuark fields = g_quark_from_static_string(\"SupportedFields\");\n\n\tif (name == fields)\n\t\tg_value_set_boxed(value,\n\t\t\t\t  SIPE_CONNECTION(object)->contact_info_fields);\n\telse\n\t\tg_value_set_uint(value,\n\t\t\t\t GPOINTER_TO_UINT(getter_data));\n}\n\nstatic void sipe_connection_constructed(GObject *object)\n{\n\tSipeConnection *self   = SIPE_CONNECTION(object);\n\tTpBaseConnection *base = TP_BASE_CONNECTION(object);\n\tvoid (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_connection_parent_class)->constructed;\n\n\tif (chain_up)\n\t\tchain_up(object);\n\n\ttp_contacts_mixin_init(object,\n\t\t\t       G_STRUCT_OFFSET(SipeConnection, contacts_mixin));\n\ttp_base_connection_register_with_contacts_mixin(base);\n\n\ttp_base_contact_list_mixin_register_with_contacts_mixin(base);\n\n\ttp_contacts_mixin_add_contact_attributes_iface(object,\n\t\t\t\t\t\t       TP_IFACE_CONNECTION_INTERFACE_ALIASING,\n\t\t\t\t\t\t       aliasing_fill_contact_attributes);\n\ttp_contacts_mixin_add_contact_attributes_iface(object,\n\t\t\t\t\t\t       TP_IFACE_CONNECTION_INTERFACE_AVATARS,\n\t\t\t\t\t\t       avatars_fill_contact_attributes);\n\n\ttp_presence_mixin_init(object,\n\t\t\t       G_STRUCT_OFFSET(SipeConnection,\n\t\t\t\t\t       presence_mixin));\n\ttp_presence_mixin_simple_presence_register_with_contacts_mixin(object);\n\n\tself->contact_info_fields = sipe_telepathy_contact_info_fields();\n}\n\nstatic void sipe_connection_finalize(GObject *object)\n{\n\tSipeConnection *self = SIPE_CONNECTION(object);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeConnection::finalize\");\n\n\ttp_contacts_mixin_finalize(object);\n\ttp_presence_mixin_finalize(object);\n\tg_boxed_free(TP_ARRAY_TYPE_FIELD_SPECS, self->contact_info_fields);\n\n\tg_free(self->authentication);\n\tg_free(self->user_agent);\n\tg_free(self->port);\n\tg_free(self->server);\n\tg_free(self->password);\n\tg_free(self->login);\n\tg_free(self->account);\n\n\tG_OBJECT_CLASS(sipe_connection_parent_class)->finalize(object);\n}\n\n/*\n * Connection class - type implementation\n */\nstatic const gchar *interfaces_always_present[] = {\n\t/* @TODO */\n\tTP_IFACE_CONNECTION_INTERFACE_ALIASING,\n\tTP_IFACE_CONNECTION_INTERFACE_AVATARS,\n\tTP_IFACE_CONNECTION_INTERFACE_CONTACT_GROUPS,\n\tTP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO,\n\tTP_IFACE_CONNECTION_INTERFACE_CONTACT_LIST,\n\tTP_IFACE_CONNECTION_INTERFACE_CONTACTS,\n\tTP_IFACE_CONNECTION_INTERFACE_PRESENCE,\n\tTP_IFACE_CONNECTION_INTERFACE_REQUESTS,\n\tTP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE,\n\tNULL\n};\n\nstatic void sipe_connection_class_init(SipeConnectionClass *klass)\n{\n\tGObjectClass *object_class = G_OBJECT_CLASS(klass);\n\tTpBaseConnectionClass *base_class = TP_BASE_CONNECTION_CLASS(klass);\n\tstatic TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {\n\t\t{\n\t\t\t/* 0 */\n\t\t\t.name   = TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO,\n\t\t\t.getter = contact_info_properties_getter,\n\t\t\t.setter = NULL,\n\t\t},\n\t\t{\n\t\t\t/* LAST! */\n\t\t\t.name   = NULL,\n\t\t}\n\t};\n\n\t/* initalize non-constant fields */\n\tprop_interfaces[0].props = sipe_telepathy_contact_info_props();\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeConnection::class_init\");\n\n\tobject_class->constructed = sipe_connection_constructed;\n\tobject_class->finalize    = sipe_connection_finalize;\n\n\tbase_class->create_handle_repos     = create_handle_repos;\n\tbase_class->start_connecting        = start_connecting;\n\tbase_class->shut_down               = shut_down;\n\tbase_class->create_channel_managers = create_channel_managers;\n\n\tbase_class->interfaces_always_present = interfaces_always_present;\n\n\tklass->properties_mixin.interfaces = prop_interfaces;\n\ttp_dbus_properties_mixin_class_init(object_class,\n\t\t\t\t\t    G_STRUCT_OFFSET(SipeConnectionClass,\n\t\t\t\t\t\t\t    properties_mixin));\n\ttp_contacts_mixin_class_init(object_class,\n\t\t\t\t     G_STRUCT_OFFSET(SipeConnectionClass,\n\t\t\t\t\t\t     contacts_mixin));\n\tsipe_telepathy_status_init(object_class,\n\t\t\t\t   G_STRUCT_OFFSET(SipeConnectionClass,\n\t\t\t\t\t\t   presence_mixin));\n\ttp_presence_mixin_simple_presence_init_dbus_properties(object_class);\n\ttp_base_contact_list_mixin_class_init(base_class);\n}\n\nstatic void sipe_connection_init(SIPE_UNUSED_PARAMETER SipeConnection *self)\n{\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeConnection::init\");\n}\n\n/*\n * Connection class - interface implementation\n *\n * Contact aliases\n */\nstatic void get_alias_flags(TpSvcConnectionInterfaceAliasing *aliasing,\n\t\t\t    DBusGMethodInvocation *context)\n{\n\tTpBaseConnection *base = TP_BASE_CONNECTION(aliasing);\n\n\tTP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED(base, context);\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeConnection::get_alias_flags called\");\n\n\ttp_svc_connection_interface_aliasing_return_from_get_alias_flags(context,\n\t\t\t\t\t\t\t\t\t TP_CONNECTION_ALIAS_FLAG_USER_SET);\n}\n\nstatic void get_aliases(TpSvcConnectionInterfaceAliasing *aliasing,\n\t\t\tconst GArray *contacts,\n\t\t\tDBusGMethodInvocation *context)\n{\n\tSipeConnection *self            = SIPE_CONNECTION(aliasing);\n\tTpBaseConnection *base          = TP_BASE_CONNECTION(aliasing);\n\tTpHandleRepoIface *contact_repo = tp_base_connection_get_handles(base,\n\t\t\t\t\t\t\t\t\t TP_HANDLE_TYPE_CONTACT);\n\tGError *error                   = NULL;\n\tGHashTable *result;\n\tguint i;\n\n\tTP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED(base, context);\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeConnection::get_aliases called\");\n\n\tif (!tp_handles_are_valid(contact_repo, contacts, FALSE, &error)) {\n\t\tdbus_g_method_return_error(context, error);\n\t\tg_error_free(error);\n\t\treturn;\n\t}\n\n\tresult = g_hash_table_new(g_direct_hash, g_direct_equal);\n\n\tfor (i = 0; i < contacts->len; i++) {\n\t\tTpHandle contact   = g_array_index(contacts, TpHandle, i);\n\t\tconst gchar *alias = sipe_telepathy_buddy_get_alias(self->contact_list,\n\t\t\t\t\t\t\t\t    contact);\n\t\tg_hash_table_insert(result,\n\t\t\t\t    GUINT_TO_POINTER(contact),\n\t\t\t\t    (gchar *) alias);\n\t}\n\n\ttp_svc_connection_interface_aliasing_return_from_get_aliases(context,\n\t\t\t\t\t\t\t\t     result);\n\tg_hash_table_unref(result);\n}\n\nstatic void request_aliases(TpSvcConnectionInterfaceAliasing *aliasing,\n\t\t\t    const GArray *contacts,\n\t\t\t    DBusGMethodInvocation *context)\n{\n\tSipeConnection *self            = SIPE_CONNECTION(aliasing);\n\tTpBaseConnection *base          = TP_BASE_CONNECTION(aliasing);\n\tTpHandleRepoIface *contact_repo = tp_base_connection_get_handles(base,\n\t\t\t\t\t\t\t\t\t TP_HANDLE_TYPE_CONTACT);\n\tGError *error                   = NULL;\n\tGPtrArray *result;\n\tgchar **strings;\n\tguint i;\n\n\tTP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED(base, context);\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeConnection::request_aliases called\");\n\n\tif (!tp_handles_are_valid(contact_repo, contacts, FALSE, &error)) {\n\t\tdbus_g_method_return_error(context, error);\n\t\tg_error_free(error);\n\t\treturn;\n\t}\n\n\tresult = g_ptr_array_sized_new(contacts->len + 1);\n\n\tfor (i = 0; i < contacts->len; i++) {\n\t\tTpHandle contact   = g_array_index(contacts, TpHandle, i);\n\t\tconst gchar *alias = sipe_telepathy_buddy_get_alias(self->contact_list,\n\t\t\t\t\t\t\t\t    contact);\n\t\tg_ptr_array_add(result, (gchar *) alias);\n\t}\n\n\tg_ptr_array_add(result, NULL);\n\tstrings = (gchar **) g_ptr_array_free(result, FALSE);\n\n\ttp_svc_connection_interface_aliasing_return_from_request_aliases(context,\n\t\t\t\t\t\t\t\t\t (const gchar **) strings);\n\tg_free(strings);\n}\n\nstatic void set_aliases(TpSvcConnectionInterfaceAliasing *aliasing,\n\t\t\tGHashTable *aliases,\n\t\t\tDBusGMethodInvocation *context)\n{\n\tSipeConnection *self            = SIPE_CONNECTION(aliasing);\n\tTpBaseConnection *base          = TP_BASE_CONNECTION(aliasing);\n\tTpHandleRepoIface *contact_repo = tp_base_connection_get_handles(base,\n\t\t\t\t\t\t\t\t\t TP_HANDLE_TYPE_CONTACT);\n\tGHashTableIter iter;\n\tgpointer key, value;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeConnection::set_aliases called\");\n\n\tg_hash_table_iter_init(&iter, aliases);\n\n\twhile (g_hash_table_iter_next(&iter, &key, NULL)) {\n\t\tGError *error = NULL;\n\n\t\tif (!tp_handle_is_valid(contact_repo,\n\t\t\t\t\tGPOINTER_TO_UINT(key),\n\t\t\t\t\t&error)) {\n\t\t\tdbus_g_method_return_error(context, error);\n\t\t\tg_error_free(error);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tg_hash_table_iter_init(&iter, aliases);\n\n\twhile (g_hash_table_iter_next(&iter, &key, &value)) {\n\t\tsipe_telepathy_buddy_set_alias(self->contact_list,\n\t\t\t\t\t       GPOINTER_TO_UINT(key),\n\t\t\t\t\t       value);\n\t}\n\n\ttp_svc_connection_interface_aliasing_return_from_set_aliases(context);\n}\n\nstatic void init_aliasing(gpointer iface,\n\t\t\t  SIPE_UNUSED_PARAMETER gpointer iface_data)\n{\n\tTpSvcConnectionInterfaceAliasingClass *klass = iface;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeConnection::init_aliasing called\");\n\n\ttp_svc_connection_interface_aliasing_implement_get_alias_flags(klass, get_alias_flags);\n\ttp_svc_connection_interface_aliasing_implement_request_aliases(klass, request_aliases);\n\ttp_svc_connection_interface_aliasing_implement_get_aliases(klass, get_aliases);\n\ttp_svc_connection_interface_aliasing_implement_set_aliases(klass, set_aliases);\n}\n\n/* create new connection object */\nTpBaseConnection *sipe_telepathy_connection_new(TpBaseProtocol *protocol,\n\t\t\t\t\t\tGHashTable *params,\n\t\t\t\t\t\tSIPE_UNUSED_PARAMETER GError **error)\n{\n\tSipeConnection *conn = g_object_new(SIPE_TYPE_CONNECTION,\n\t\t\t\t\t    \"protocol\", tp_base_protocol_get_name(protocol),\n\t\t\t\t\t    NULL);\n\tconst gchar *value;\n\tguint port;\n\tgboolean boolean_value;\n\tgboolean valid;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"sipe_telepathy_connection_new\");\n\n\t/* initialize private fields */\n\tconn->is_disconnecting = FALSE;\n\n\t/* account is required field */\n\tconn->account = g_strdup(tp_asv_get_string(params, \"account\"));\n\n\t/* if login is not specified, account value will be used in connect_to_core */\n\tvalue = tp_asv_get_string(params, \"login\");\n\tif (value && strlen(value))\n\t\tconn->login = g_strdup(value);\n\telse\n\t\tconn->login = NULL;\n\n\t/* password */\n\tvalue = tp_asv_get_string(params, \"password\");\n\tif (value && strlen(value))\n\t\tconn->password = g_strdup(value);\n\telse\n\t\tconn->password = NULL;\n\n\t/* server name */\n\tvalue = tp_asv_get_string(params, \"server\");\n\tif (value && strlen(value))\n\t\tconn->server = g_strdup(value);\n\telse\n\t\tconn->server = NULL;\n\n\t/* server port: core expects a string */\n\tport = tp_asv_get_uint32(params, \"port\", &valid);\n\tif (valid)\n\t\tconn->port = g_strdup_printf(\"%d\", port);\n\telse\n\t\tconn->port = NULL;\n\n\t/* transport type */\n\tvalue = tp_asv_get_string(params, \"transport\");\n\tif (sipe_strequal(value, \"auto\")) {\n\t\tconn->transport = conn->server ?\n\t\t\tSIPE_TRANSPORT_TLS : SIPE_TRANSPORT_AUTO;\n\t} else if (sipe_strequal(value, \"tls\")) {\n\t\tconn->transport = SIPE_TRANSPORT_TLS;\n\t} else {\n\t\tconn->transport = SIPE_TRANSPORT_TCP;\n\t}\n\n\t/* User-Agent: override */\n\tvalue = tp_asv_get_string(params, \"useragent\");\n\tif (value && strlen(value))\n\t\tconn->user_agent = g_strdup(value);\n\telse\n\t\tconn->user_agent = NULL;\n\n\t/* authentication type */\n\tvalue = tp_asv_get_string(params, \"authentication\");\n\tif (value && strlen(value) && strcmp(value, \"ntlm\"))\n\t\tconn->authentication = g_strdup(value);\n\telse\n\t\tconn->authentication = NULL; /* NTLM is default */\n\n\t/* Single Sign-On */\n\tboolean_value = tp_asv_get_boolean(params, \"single-sign-on\", &valid);\n\tif (valid)\n\t\tconn->sso = boolean_value;\n\telse\n\t\tconn->sso = FALSE;\n\n\t/* Don't publish my calendar information */\n\tboolean_value = tp_asv_get_boolean(params, \"don't-publish-calendar\", &valid);\n\tif (valid)\n\t\tconn->dont_publish = boolean_value;\n\telse\n\t\tconn->dont_publish = FALSE;\n\n\t/* Allow insecure download of buddy icons from web */\n\tboolean_value = tp_asv_get_boolean(params, \"allow-web-photo\", &valid);\n\tif (valid)\n\t\tconn->allow_web_photo = boolean_value;\n\telse\n\t\tconn->allow_web_photo = FALSE;\n\n\treturn(TP_BASE_CONNECTION(conn));\n}\n\nvoid sipe_telepathy_connection_alias_updated(TpBaseConnection *connection,\n\t\t\t\t\t     guint contact,\n\t\t\t\t\t     const gchar *alias)\n{\n\tGPtrArray *aliases = g_ptr_array_sized_new(1);\n\tGValueArray *pair  = g_value_array_new(2);\n\n\tg_value_array_append(pair, NULL);\n\tg_value_array_append(pair, NULL);\n\tg_value_init(pair->values + 0, G_TYPE_UINT);\n\tg_value_init(pair->values + 1, G_TYPE_STRING);\n\tg_value_set_uint(pair->values + 0, contact);\n\tg_value_set_string(pair->values + 1, alias);\n\tg_ptr_array_add(aliases, pair);\n\n\ttp_svc_connection_interface_aliasing_emit_aliases_changed(SIPE_CONNECTION(connection),\n\t\t\t\t\t\t\t\t  aliases);\n\n\tg_ptr_array_unref(aliases);\n\tg_value_array_free(pair);\n}\n\nstruct sipe_backend_private *sipe_telepathy_connection_private(GObject *object)\n{\n\tSipeConnection *self = SIPE_CONNECTION(object);\n\t/* connected to core already? */\n\tif (self->private.public)\n\t\treturn(&self->private);\n\telse\n\t\treturn(NULL);\n}\n\n/*\n * Backend adaptor functions\n */\nvoid sipe_backend_connection_completed(struct sipe_core_public *sipe_public)\n{\n\tSipeConnection *self   = SIPE_PUBLIC_TO_CONNECTION;\n\tTpBaseConnection *base = TP_BASE_CONNECTION(self);\n\n\t/* we are only allowed to do this once */\n\tif (base->status != TP_CONNECTION_STATUS_CONNECTED)\n\t\ttp_base_connection_change_status(base,\n\t\t\t\t\t\t TP_CONNECTION_STATUS_CONNECTED,\n\t\t\t\t\t\t TP_CONNECTION_STATUS_REASON_REQUESTED);\n}\n\nvoid sipe_backend_connection_error(struct sipe_core_public *sipe_public,\n\t\t\t\t   sipe_connection_error error,\n\t\t\t\t   const gchar *msg)\n{\n\tSipeConnection *self   = SIPE_PUBLIC_TO_CONNECTION;\n\tTpBaseConnection *base = TP_BASE_CONNECTION(self);\n\tGHashTable *details    = tp_asv_new(\"server-message\", G_TYPE_STRING, msg,\n\t\t\t\t\t    NULL);\n\tTpConnectionStatusReason reason;\n\tconst gchar *name;\n\n\tself->is_disconnecting = TRUE;\n\n\tswitch (error) {\n\tcase SIPE_CONNECTION_ERROR_NETWORK:\n\t\treason = TP_CONNECTION_STATUS_REASON_NETWORK_ERROR;\n\t\tif (base->status == TP_CONNECTION_STATUS_CONNECTING)\n\t\t\tname = TP_ERROR_STR_CONNECTION_FAILED;\n\t\telse\n\t\t\tname = TP_ERROR_STR_CONNECTION_LOST;\n\t\tbreak;\n\n\tcase SIPE_CONNECTION_ERROR_INVALID_USERNAME:\n\tcase SIPE_CONNECTION_ERROR_INVALID_SETTINGS:\n\tcase SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED:\n\tcase SIPE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE:\n\t\t/* copied from haze code. I agree there should be better ones */\n\t\treason = TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED;\n\t\tname   = TP_ERROR_STR_AUTHENTICATION_FAILED;\n\t\tbreak;\n\n\tdefault:\n\t\treason = TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED;\n\t\tname   = TP_ERROR_STR_DISCONNECTED;\n\t\tbreak;\n\t}\n\n\tSIPE_DEBUG_ERROR(\"sipe_backend_connection_error: %s (%s)\", name, msg);\n\ttp_base_connection_disconnect_with_dbus_error(base,\n\t\t\t\t\t\t      name,\n\t\t\t\t\t\t      details,\n\t\t\t\t\t\t      reason);\n\tg_hash_table_unref(details);\n}\n\ngboolean sipe_backend_connection_is_disconnecting(struct sipe_core_public *sipe_public)\n{\n\tSipeConnection *self = SIPE_PUBLIC_TO_CONNECTION;\n\n\t/* disconnect was requested or transport was already disconnected */\n\treturn(self->is_disconnecting ||\n\t       self->private.transport == NULL);\n}\n\ngboolean sipe_backend_connection_is_valid(struct sipe_core_public *sipe_public)\n{\n\treturn(!sipe_backend_connection_is_disconnecting(sipe_public));\n}\n\nconst gchar *sipe_backend_setting(struct sipe_core_public *sipe_public,\n\t\t\t\t  sipe_setting type)\n{\n\tSipeConnection *self = SIPE_PUBLIC_TO_CONNECTION;\n\tconst gchar *value;\n\n\tswitch (type) {\n\tcase SIPE_SETTING_USER_AGENT:\n\t\tvalue = self->user_agent;\n\t\tbreak;\n\tdefault:\n\t\t/* @TODO: update when settings are implemented */\n\t\tvalue = NULL;\n\t\tbreak;\n\t}\n\n\treturn(value);\n}\n\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/telepathy/telepathy-debug.c",
    "content": "/**\n * @file telepathy-debug.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2012-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n ******************************************************************************\n *\n * How to collect debugging information\n *\n * Run the connection manager from the command line like this:\n *\n *    $ G_MESSAGES_DEBUG=\"all\" SIPE_PERSIST=1 \\\n *      SIPE_DEBUG=[space separated keyword list \\\n *      [SIPE_UNSAFE_DEBUG=1] [SIPE_TIMING=1] [SIPE_LOGFILE=\"...\"] \\\n *      telepathy-sipe\n *\n * G_MESSAGES_DEBUG=all: make debug & informational messages visible\n *\n * SIPE_PERSISTS=1     : keep the CM running permanently,\n *                       [otherwise the one installed in the system will\n *                       be started automatically by D-Bus when needed]\n *\n * SIPE_DEBUG=...      :\n *    all        - enable all sipe & telepathy-glib messages\n *    sipe       - enable only sipe messages\n *    \"sipe ...\" - enable sipe and some telepathy-glib messages\n *\n * SIPE_UNSAFE_DEBUG=1 : enable unsafe debugging output, i.e. include the\n *                       content of protocol messages which may reveal\n *                       secret information, like passwords.\n *                       [usually required to be able to debug issues]\n *\n * SIPE_TIMING=1       : enable time stamps\n *                       [recommended for any usable log file]\n *\n * SIPE_LOGFILE=\"...\"  : redirect output to this file\n *                       [prepend file name with \"+\" to enable append mode]\n *\n ******************************************************************************\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdarg.h>\n\n#include <glib.h>\n#include <telepathy-glib/debug-sender.h>\n#include <telepathy-glib/telepathy-glib.h>\n\n#include \"sipe-backend.h\"\n\n#include \"telepathy-private.h\"\n\n#define SIPE_TELEPATHY_DEBUG 1\n\nstatic TpDebugSender *debug;\nstatic guint          flags  = 0;\nstatic gboolean       unsafe = FALSE;\n\nvoid sipe_telepathy_debug_init(void)\n{\n\tstatic const GDebugKey keys[] = {\n\t\t/* This simulates pidgin's --debug flag, i.e. we only see\n\t\t * output from SIPE if this is set.\n\t\t *\n\t\t *  @TODO: we could make this more finely grained, i.e.\n\t\t *         which levels should be visible\n\t\t */\n\t\t{ \"sipe\", SIPE_TELEPATHY_DEBUG },\n\t};\n\tconst gchar *env_flags = g_getenv(\"SIPE_DEBUG\");\n\n\t/* Telepathy debugger */\n\tdebug = tp_debug_sender_dup();\n\n\t/* divert g_log_default_handler() output to a logfile */\n\ttp_debug_divert_messages(g_getenv(\"SIPE_LOGFILE\"));\n\n\t/* sipe & telepathy-glib debugging flags */\n\tif (env_flags) flags |= g_parse_debug_string(env_flags, keys, 1);\n\ttp_debug_set_flags(env_flags);\n\n\t/* enable unsafe debug output */\n\tif (g_getenv(\"SIPE_UNSAFE_DEBUG\"))\n\t\tunsafe = TRUE;\n\n\t/* add time stamps to debug output */\n\tif (g_getenv(\"SIPE_TIMING\"))\n\t\tg_log_set_default_handler(tp_debug_timestamped_log_handler, NULL);\n\n\t/* enable test mode */\n\tif (g_getenv(\"SIPE_PERSIST\"))\n\t\ttp_debug_set_persistent(TRUE);\n}\n\nvoid sipe_telepathy_debug_finalize(void)\n{\n\tg_object_unref(debug);\n}\n\nstatic const GLogLevelFlags debug_level_mapping[] = {\n\tG_LOG_LEVEL_DEBUG,    /* SIPE_LOG_LEVEL_INFO      */\n\tG_LOG_LEVEL_WARNING,  /* SIPE_LOG_LEVEL_WARNING   */\n\tG_LOG_LEVEL_CRITICAL, /* SIPE_LOG_LEVEL_ERROR     */\n\tG_LOG_LEVEL_DEBUG,    /* SIPE_DEBUG_LEVEL_INFO    */\n\tG_LOG_LEVEL_WARNING,  /* SIPE_DEBUG_LEVEL_WARNING */\n\tG_LOG_LEVEL_CRITICAL, /* SIPE_DEBUG_LEVEL_ERROR   */\n};\n\nvoid sipe_backend_debug_literal(sipe_debug_level level,\n\t\t\t\tconst gchar *msg)\n{\n\tif ((level < SIPE_DEBUG_LEVEL_LOWEST) || (flags & SIPE_TELEPATHY_DEBUG)) {\n\t\tGLogLevelFlags g_level = debug_level_mapping[level];\n\t\tg_log(SIPE_TELEPATHY_DOMAIN, g_level, \"%s\", msg);\n\t\ttp_debug_sender_add_message(debug, NULL,\n\t\t\t\t\t    SIPE_TELEPATHY_DOMAIN,\n\t\t\t\t\t    g_level,\n\t\t\t\t\t    msg);\n\t}\n}\n\nvoid sipe_backend_debug(sipe_debug_level level,\n\t\t\tconst gchar *format,\n\t\t\t...)\n{\n\tva_list ap;\n\n\tva_start(ap, format);\n\tif ((level < SIPE_DEBUG_LEVEL_LOWEST) || (flags & SIPE_TELEPATHY_DEBUG)) {\n\t\tgchar *msg = g_strdup_vprintf(format, ap);\n\t\tsipe_backend_debug_literal(level, msg);\n\t\tg_free(msg);\n\t}\n\tva_end(ap);\n}\n\ngboolean sipe_backend_debug_enabled(void)\n{\n\treturn((flags & SIPE_TELEPATHY_DEBUG) && unsafe);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/telepathy/telepathy-dnsquery.c",
    "content": "/**\n * @file telepathy-dnsquery.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2012-2017 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <glib.h>\n#include <gio/gio.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n\nstruct sipe_dns_query {\n\tsipe_dns_resolved_cb  callback;\n\tgpointer\t      extradata;\n\tguint                 port;\n\tGCancellable         *cancel;\n};\n\nstatic void dns_srv_response(GObject *resolver,\n\t\t\t     GAsyncResult *result,\n\t\t\t     gpointer data)\n{\n\tGError *error  = NULL;\n\tGList *targets = g_resolver_lookup_service_finish(G_RESOLVER(resolver),\n\t\t\t\t\t\t\t  result,\n\t\t\t\t\t\t\t  &error);\n\tstruct sipe_dns_query *query = data;\n\n\tif (targets) {\n\t\tGSrvTarget *target = targets->data;\n\t\tquery->callback(query->extradata,\n\t\t\t\tg_srv_target_get_hostname(target),\n\t\t\t\tg_srv_target_get_port(target));\n\t\tg_resolver_free_targets(targets);\n\t} else {\n\t\tSIPE_DEBUG_INFO(\"dns_srv_response: failed: %s\",\n\t\t\t\terror ? error->message : \"UNKNOWN\");\n\t\tif (error)\n\t\t\tg_error_free(error);\n\t\tif (query->callback)\n\t\t\tquery->callback(query->extradata, NULL, 0);\n\t}\n\tg_object_unref(query->cancel);\n\tg_free(query);\n}\n\nstruct sipe_dns_query *sipe_backend_dns_query_srv(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t  const gchar *protocol,\n\t\t\t\t\t\t  const gchar *transport,\n\t\t\t\t\t\t  const gchar *domain,\n\t\t\t\t\t\t  sipe_dns_resolved_cb callback,\n\t\t\t\t\t\t  gpointer data)\n{\n\tstruct sipe_dns_query *query = g_new0(struct sipe_dns_query, 1);\n\tGResolver *resolver          = g_resolver_get_default();\n\n\tSIPE_DEBUG_INFO(\"sipe_backend_dns_query_srv: %s/%s/%s\",\n\t\t\tprotocol, transport, domain);\n\n\tquery->callback  = callback;\n\tquery->extradata = data;\n\tquery->cancel    = g_cancellable_new();\n\tg_resolver_lookup_service_async(resolver,\n\t\t\t\t\tprotocol, transport, domain,\n\t\t\t\t\tquery->cancel,\n\t\t\t\t\tdns_srv_response,\n\t\t\t\t\tquery);\n\n\tg_object_unref(resolver);\n\treturn(query);\n}\n\nstatic void dns_a_response(GObject *resolver,\n\t\t\t   GAsyncResult *result,\n\t\t\t   gpointer data)\n{\n\tGError *error    = NULL;\n\tGList *addresses = g_resolver_lookup_by_name_finish(G_RESOLVER(resolver),\n\t\t\t\t\t\t\t    result,\n\t\t\t\t\t\t\t    &error);\n\tstruct sipe_dns_query *query = data;\n\n\tif (addresses) {\n\t\tGInetAddress *address  = addresses->data;\n\t\tgchar        *ipstr    = g_inet_address_to_string(address);\n\t\tquery->callback(query->extradata, ipstr, query->port);\n\t\tg_free(ipstr);\n\t\tg_resolver_free_addresses(addresses);\n\t} else {\n\t\tSIPE_DEBUG_INFO(\"dns_a_response: failed: %s\",\n\t\t\t\terror ? error->message : \"UNKNOWN\");\n\t\tif (error)\n\t\t\tg_error_free(error);\n\t\tif (query->callback)\n\t\t\tquery->callback(query->extradata, NULL, 0);\n\t}\n\tg_object_unref(query->cancel);\n\tg_free(query);\n}\n\nstruct sipe_dns_query *sipe_backend_dns_query_a(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t\tconst gchar *hostname,\n\t\t\t\t\t\tguint port,\n\t\t\t\t\t\tsipe_dns_resolved_cb callback,\n\t\t\t\t\t\tgpointer data)\n{\n\tstruct sipe_dns_query *query = g_new0(struct sipe_dns_query, 1);\n\tGResolver *resolver          = g_resolver_get_default();\n\n\tSIPE_DEBUG_INFO(\"sipe_backend_dns_query_a: %s\", hostname);\n\n\tquery->callback  = callback;\n\tquery->extradata = data;\n\tquery->port      = port;\n\tquery->cancel    = g_cancellable_new();\n\tg_resolver_lookup_by_name_async(resolver,\n\t\t\t\t\thostname,\n\t\t\t\t\tquery->cancel,\n\t\t\t\t\tdns_a_response,\n\t\t\t\t\tquery);\n\n\tg_object_unref(resolver);\n\treturn(query);\n}\n\nvoid sipe_backend_dns_query_cancel(struct sipe_dns_query *query)\n{\n\t/* callback is invalid now, do no longer call! */\n\tquery->callback = NULL;\n\tg_cancellable_cancel(query->cancel);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/telepathy/telepathy-main.c",
    "content": "/**\n * @file telepathy-main.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2012-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib-object.h>\n#include <telepathy-glib/base-connection-manager.h>\n#include <telepathy-glib/run.h>\n#include <telepathy-glib/telepathy-glib.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n\n#include \"telepathy-private.h\"\n\n#if TP_VERSION_MIN_REQUIRED < TP_VERSION_0_24\n#error telepathy-glib >= 0.24.0 is required to build SIPE\n#endif\n\nG_BEGIN_DECLS\n/*\n * Connection manager class - data structures\n */\ntypedef struct _SipeConnectionManagerClass {\n\tTpBaseConnectionManagerClass parent_class;\n} SipeConnectionManagerClass;\n\ntypedef struct _SipeConnectionManager {\n\tTpBaseConnectionManager parent;\n} SipeConnectionManager;\n\n/*\n * Connection manager class - type macros\n */\nstatic GType sipe_connection_manager_get_type(void) G_GNUC_CONST;\n#define SIPE_TYPE_CONNECTION_MANAGER \\\n\t(sipe_connection_manager_get_type())\n#define SIPE_CONNECTION_MANAGER(obj) \\\n\t(G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_CONNECTION_MANAGER, \\\n\t\t\t\t    SipeConnectionManager))\nG_END_DECLS\n\n/*\n * Connection manager class - type definition\n */\nG_DEFINE_TYPE(SipeConnectionManager,\n\t      sipe_connection_manager,\n\t      TP_TYPE_BASE_CONNECTION_MANAGER)\n\n/*\n * Connection manager class - instance methods\n */\nstatic void sipe_connection_manager_constructed(GObject *object)\n{\n\tSipeConnectionManager *self   = SIPE_CONNECTION_MANAGER(object);\n\tTpBaseConnectionManager *base = (TpBaseConnectionManager *) self;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeConnectionManager::constructed\");\n\n\t/* always chain up to the parent constructor first */\n\tG_OBJECT_CLASS(sipe_connection_manager_parent_class)->constructed(object);\n\n\tsipe_telepathy_protocol_init(base);\n}\n\n/*\n * Connection manager class - type implementation\n */\nstatic void sipe_connection_manager_class_init(SipeConnectionManagerClass *klass)\n{\n\tGObjectClass *object_class               = G_OBJECT_CLASS(klass);\n\tTpBaseConnectionManagerClass *base_class = (TpBaseConnectionManagerClass *)klass;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeConnectionManager::class_init\");\n\n\tobject_class->constructed   = sipe_connection_manager_constructed;\n\n\tbase_class->new_connection  = NULL;\n\tbase_class->cm_dbus_name    = SIPE_TELEPATHY_DOMAIN;\n\tbase_class->protocol_params = NULL;\n}\n\nstatic void sipe_connection_manager_init(SIPE_UNUSED_PARAMETER SipeConnectionManager *self)\n{\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeConnectionManager::init\");\n}\n\n\n/*\n * Entry point\n */\nstatic TpBaseConnectionManager *construct_cm(void)\n{\n\treturn((TpBaseConnectionManager *)\n\t       g_object_new(SIPE_TYPE_CONNECTION_MANAGER, NULL));\n}\n\nint main(int argc, char *argv[])\n{\n\tint rc;\n\n\tg_type_init();\n\tsipe_telepathy_debug_init();\n\tsipe_core_init(LOCALEDIR);\n\n\tSIPE_DEBUG_INFO(\"main: initializing - version %s\", PACKAGE_VERSION);\n\n\trc = tp_run_connection_manager(SIPE_TELEPATHY_DOMAIN,\n\t\t\t\t       PACKAGE_VERSION,\n\t\t\t\t       construct_cm,\n\t\t\t\t       argc,\n\t\t\t\t       argv);\n\n\tsipe_core_destroy();\n\tsipe_telepathy_debug_finalize();\n\treturn(rc);\n}\n\ngchar *sipe_backend_version(void)\n{\n\t/*\n\t * @TODO: this is the version of telepathy-glib we have compiled this\n\t *        code against, not the version of \"telepathy\" which is\n\t *        currently running. How to get this? Is it even possible?\n\t *\n\t * requires telepathy-glib >= 0.19\n\treturn(g_strdup_printf(\"telepathy-glib/%d.%d.%d\",\n\t\t\t       TP_MAJOR_VERSION, TP_MINOR_VERSION, TP_MICRO_VERSION));\n\t*/\n\treturn(g_strdup(\"Telepathy\"));\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/telepathy/telepathy-private.h",
    "content": "/**\n * @file telepathy-private.h\n *\n * pidgin-sipe\n *\n * Copyright (C) 2012-2016 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/* Forward declarations */\nstruct _GObject;\nstruct _GObjectClass;\nstruct _GTlsCertificate;\nstruct _SipeConnection;\nstruct _SipeContactList;\nstruct _SipeTLSManager;\nstruct _TpBaseConnection;\nstruct _TpBaseConnectionManager;\nstruct _TpBaseProtocol;\nstruct sipe_tls_info;\nstruct sipe_transport_telepathy;\n\n/* constants */\n#define SIPE_TELEPATHY_DOMAIN \"sipe\"\n\nstruct sipe_backend_private {\n\tstruct sipe_core_public *public;\n\n\t/* buddies */\n\tstruct _SipeContactList *contact_list;\n\n\t/* connection */\n\tstruct _SipeConnection *connection;\n\n\t/* photo */\n\tgchar *cache_dir;\n\n\t/* status */\n\tguint activity;\n\tgchar *message;\n\n\t/* TLS certificate verification */\n\tstruct _SipeTLSManager *tls_manager;\n\n\t/* transport */\n\tstruct sipe_transport_telepathy *transport;\n};\n\n/* buddy */\nstruct _SipeContactList *sipe_telepathy_contact_list_new(struct _TpBaseConnection *connection);\nconst gchar *sipe_telepathy_buddy_get_alias(struct _SipeContactList *contact_list,\n\t\t\t\t\t    const guint contact);\nvoid sipe_telepathy_buddy_set_alias(struct _SipeContactList *contact_list,\n\t\t\t\t    const guint contact,\n\t\t\t\t    const gchar *alias);\nconst gchar *sipe_telepathy_buddy_get_hash(struct _SipeContactList *contact_list,\n\t\t\t\t\t   const guint contact);\nguint sipe_telepathy_buddy_get_presence(struct _SipeContactList *contact_list,\n\t\t\t\t\tguint contact);\nvoid sipe_telepathy_avatars_iface_init(gpointer g_iface,\n\t\t\t\t       gpointer iface_data);\nvoid sipe_telepathy_contact_info_iface_init(gpointer g_iface,\n\t\t\t\t\t    gpointer iface_data);\nGPtrArray *sipe_telepathy_contact_info_fields(void);\n/* TpDBusPropertiesMixinPropImpl is a broken typedef */\ngpointer sipe_telepathy_contact_info_props(void);\n\n/* connection */\nstruct _TpBaseConnection *sipe_telepathy_connection_new(struct _TpBaseProtocol *protocol,\n\t\t\t\t\t\t\tGHashTable *params,\n\t\t\t\t\t\t\tGError **error);\nvoid sipe_telepathy_connection_alias_updated(struct _TpBaseConnection *connection,\n\t\t\t\t\t     guint contact,\n\t\t\t\t\t     const gchar *alias);\nstruct sipe_backend_private *sipe_telepathy_connection_private(GObject *object);\n\n/* debugging */\nvoid sipe_telepathy_debug_init(void);\nvoid sipe_telepathy_debug_finalize(void);\n\n/* protocol */\nvoid sipe_telepathy_protocol_init(struct _TpBaseConnectionManager *cm);\ngchar *sipe_telepathy_protocol_normalize_contact(struct _TpBaseProtocol *self,\n\t\t\t\t\t\t const gchar *contact,\n\t\t\t\t\t\t GError **error);\n\n/* contact search */\nGType sipe_search_manager_get_type(void);\n#define SIPE_TYPE_SEARCH_MANAGER (sipe_search_manager_get_type())\nstruct _GObject *sipe_telepathy_search_new(struct _TpBaseConnection *connection);\n\n/* status */\nvoid sipe_telepathy_status_init(struct _GObjectClass *object_class,\n\t\t\t\tgsize struct_offset);\n\n/* TLS certificate verification */\nstruct _SipeTLSManager *sipe_telepathy_tls_new(struct _TpBaseConnection *connection);\nstruct sipe_tls_info *sipe_telepathy_tls_info_new(const gchar *hostname,\n\t\t\t\t\t\t  struct _GTlsCertificate *certificate);\nvoid sipe_telepathy_tls_info_free(struct sipe_tls_info *tls_info);\nvoid sipe_telepathy_tls_verify_async(struct _GObject *connection,\n\t\t\t\t     struct sipe_tls_info *tls_info,\n\t\t\t\t     GAsyncReadyCallback callback,\n\t\t\t\t     gpointer user_data);\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/telepathy/telepathy-protocol.c",
    "content": "/**\n * @file telepathy-protocol.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2012-2017 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <string.h>\n\n#include <dbus/dbus-protocol.h>\n#include <glib-object.h>\n#include <telepathy-glib/base-connection-manager.h>\n#include <telepathy-glib/base-protocol.h>\n#include <telepathy-glib/simple-password-manager.h>\n#include <telepathy-glib/telepathy-glib.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n#include \"sipe-nls.h\"\n\n#include \"telepathy-private.h\"\n\nG_BEGIN_DECLS\n/*\n * Protocol class - data structures\n */\ntypedef struct _SipeProtocolClass {\n\tTpBaseProtocolClass parent_class;\n} SipeProtocolClass;\n\ntypedef struct _SipeProtocol {\n\tTpBaseProtocol parent;\n} SipeProtocol;\n\n/*\n * Protocol class - type macros\n */\nstatic GType sipe_protocol_get_type(void) G_GNUC_CONST;\n#define SIPE_TYPE_PROTOCOL \\\n\t(sipe_protocol_get_type())\n#define SIPE_PROTOCOL(obj) \\\n\t(G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_PROTOCOL, \\\n\t\t\t\t    SipeProtocol))\nG_END_DECLS\n\n/*\n * Protocol class - type definition\n */\nG_DEFINE_TYPE(SipeProtocol,\n\t      sipe_protocol,\n\t      TP_TYPE_BASE_PROTOCOL)\n\n/*\n * Protocol class - instance methods\n */\n/*\n * @TODO: parameter filtering doesn't seem to work: these functions aren't\n *        called at all - why?\n */\nstatic gboolean parameter_filter_account(SIPE_UNUSED_PARAMETER const TpCMParamSpec *paramspec,\n\t\t\t\t\t GValue *value,\n\t\t\t\t\t GError **error)\n{\n\tconst gchar *str = g_value_get_string(value);\n\n\tif ((str == NULL) ||\n\t    (strchr(str, '@') == NULL)) {\n\t\tg_set_error(error, TP_ERROR, TP_ERROR_INVALID_HANDLE,\n\t\t\t    _(\"User name should be a valid SIP URI\\nExample: user@company.com\"));\n\t\treturn(FALSE);\n\t}\n\treturn(TRUE);\n}\n\nstatic const TpCMParamSpec *get_parameters(SIPE_UNUSED_PARAMETER TpBaseProtocol *self)\n{\n/* ISO C99 Designated Initializers silences -Wmissing-field-initializers */\n#define SIPE_PROTOCOL_PARAMETER(_name, _dtype, _gtype, _flags, _default, _filter) \\\n\t{                                  \\\n\t\t.name        = (_name),    \\\n\t\t.dtype       = (_dtype),   \\\n\t\t.gtype       = (_gtype),   \\\n\t\t.flags       = (_flags),   \\\n\t\t.def         = (_default), \\\n\t\t.offset      = 0,          \\\n\t\t.filter      = (_filter),  \\\n\t\t.filter_data = NULL,       \\\n\t\t.setter_data = NULL,       \\\n\t}\n\n\tstatic const TpCMParamSpec sipe_parameters[] = {\n\t\tSIPE_PROTOCOL_PARAMETER(\"account\",\n\t\t\t\t\tDBUS_TYPE_STRING_AS_STRING,\n\t\t\t\t\tG_TYPE_STRING,\n\t\t\t\t\tTP_CONN_MGR_PARAM_FLAG_REQUIRED,\n\t\t\t\t\tNULL,\n\t\t\t\t\tparameter_filter_account),\n\t\tSIPE_PROTOCOL_PARAMETER(\"login\",\n\t\t\t\t\tDBUS_TYPE_STRING_AS_STRING,\n\t\t\t\t\tG_TYPE_STRING,\n\t\t\t\t\t0,\n\t\t\t\t\tNULL,\n\t\t\t\t\tNULL /* can be empty */),\n\t\tSIPE_PROTOCOL_PARAMETER(\"password\",\n\t\t\t\t\tDBUS_TYPE_STRING_AS_STRING,\n\t\t\t\t\tG_TYPE_STRING,\n\t\t\t\t\tTP_CONN_MGR_PARAM_FLAG_SECRET,\n\t\t\t\t\tNULL,\n\t\t\t\t\tNULL /* can be empty */),\n\t\tSIPE_PROTOCOL_PARAMETER(\"server\",\n\t\t\t\t\tDBUS_TYPE_STRING_AS_STRING,\n\t\t\t\t\tG_TYPE_STRING,\n\t\t\t\t\t0,\n\t\t\t\t\tNULL,\n\t\t\t\t\tNULL /* can be empty */),\n\t\tSIPE_PROTOCOL_PARAMETER(\"port\",\n\t\t\t\t\tDBUS_TYPE_UINT16_AS_STRING,\n\t\t\t\t\tG_TYPE_UINT,\n\t\t\t\t\tTP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT,\n\t\t\t\t\tGUINT_TO_POINTER(0),\n\t\t\t\t\tNULL),\n\t\t/* @TODO: this should be combo auto/ssl/tcp */\n\t\tSIPE_PROTOCOL_PARAMETER(\"transport\",\n\t\t\t\t\tDBUS_TYPE_STRING_AS_STRING,\n\t\t\t\t\tG_TYPE_STRING,\n\t\t\t\t\tTP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT,\n\t\t\t\t\t\"auto\",\n\t\t\t\t\ttp_cm_param_filter_string_nonempty),\n\t\tSIPE_PROTOCOL_PARAMETER(\"useragent\",\n\t\t\t\t\tDBUS_TYPE_STRING_AS_STRING,\n\t\t\t\t\tG_TYPE_STRING,\n\t\t\t\t\t0,\n\t\t\t\t\tNULL,\n\t\t\t\t\tNULL /* can be empty */),\n\t\t/* @TODO: this should be combo auto/ntlm/krb5/tls-dsk */\n\t\tSIPE_PROTOCOL_PARAMETER(\"authentication\",\n\t\t\t\t\tDBUS_TYPE_STRING_AS_STRING,\n\t\t\t\t\tG_TYPE_STRING,\n\t\t\t\t\tTP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT,\n\t\t\t\t\t\"auto\",\n\t\t\t\t\ttp_cm_param_filter_string_nonempty),\n\t\tSIPE_PROTOCOL_PARAMETER(\"single-sign-on\",\n\t\t\t\t\tDBUS_TYPE_BOOLEAN_AS_STRING,\n\t\t\t\t\tG_TYPE_BOOLEAN,\n\t\t\t\t\tTP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT,\n\t\t\t\t\tGINT_TO_POINTER(FALSE),\n\t\t\t\t\tNULL),\n\t\tSIPE_PROTOCOL_PARAMETER(\"don't-publish-calendar\",\n\t\t\t\t\tDBUS_TYPE_BOOLEAN_AS_STRING,\n\t\t\t\t\tG_TYPE_BOOLEAN,\n\t\t\t\t\tTP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT,\n\t\t\t\t\tGINT_TO_POINTER(FALSE),\n\t\t\t\t\tNULL),\n\t\tSIPE_PROTOCOL_PARAMETER(\"allow-web-photo\",\n\t\t\t\t\tDBUS_TYPE_BOOLEAN_AS_STRING,\n\t\t\t\t\tG_TYPE_BOOLEAN,\n\t\t\t\t\tTP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT,\n\t\t\t\t\tGINT_TO_POINTER(FALSE),\n\t\t\t\t\tNULL),\n\t\tSIPE_PROTOCOL_PARAMETER(NULL, NULL, 0, 0, NULL, NULL)\n\t};\n\n\treturn(sipe_parameters);\n}\n\n/* non-static, because it is re-used by connection object */\ngchar *sipe_telepathy_protocol_normalize_contact(SIPE_UNUSED_PARAMETER TpBaseProtocol *self,\n\t\t\t\t\t\t const gchar *contact,\n\t\t\t\t\t\t GError **error)\n{\n\tgchar *uri = sip_uri_if_valid(contact);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeProtocol::normalize_contact\");\n\n\tif (!uri)\n\t\tg_set_error(error, TP_ERROR, TP_ERROR_INVALID_HANDLE,\n\t\t\t    _(\"User name should be a valid SIP URI\\nExample: user@company.com\"));\n\treturn(uri);\n}\n\nstatic gchar *identify_account(SIPE_UNUSED_PARAMETER TpBaseProtocol *self,\n\t\t\t       GHashTable *asv,\n\t\t\t       SIPE_UNUSED_PARAMETER GError **error)\n{\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeProtocol::identify_account\");\n\n\treturn(g_strdup(tp_asv_get_string(asv, \"account\")));\n}\n\nstatic GStrv get_interfaces(SIPE_UNUSED_PARAMETER TpBaseProtocol *base)\n{\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeProtocol::get_interfaces\");\n\n\treturn(g_new0(gchar *, 1));\n}\n\nstatic void get_connection_details(SIPE_UNUSED_PARAMETER TpBaseProtocol *self,\n\t\t\t\t   GStrv *connection_interfaces,\n\t\t\t\t   GType **channel_managers,\n\t\t\t\t   gchar **icon_name,\n\t\t\t\t   gchar **english_name,\n\t\t\t\t   gchar **vcard_field)\n{\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeProtocol::get_connection_details\");\n\n\tif (connection_interfaces) {\n\t\tstatic const gchar * const interfaces[] = {\n\t\t\t/* @TODO */\n\t\t\tNULL\n\t\t};\n\t\t*connection_interfaces = g_strdupv((GStrv) interfaces);\n\t}\n\tif (channel_managers) {\n\t\tGType types[] = {\n\t\t\t/* @TODO */\n\t\t\tTP_TYPE_SIMPLE_PASSWORD_MANAGER,\n\t\t\tSIPE_TYPE_SEARCH_MANAGER,\n\t\t\tG_TYPE_INVALID\n\t\t};\n\t\t*channel_managers = g_memdup(types, sizeof(types));\n\t}\n\tif (icon_name)\n\t\t*icon_name    = g_strdup(\"im-\" SIPE_TELEPATHY_DOMAIN);\n\tif (english_name)\n\t\t*english_name = g_strdup(\"Office Communicator\");\n\tif (vcard_field)\n\t\t*vcard_field  = g_strdup(\"x-\" SIPE_TELEPATHY_DOMAIN);\n}\n\nstatic GStrv dup_authentication_types(SIPE_UNUSED_PARAMETER TpBaseProtocol *self)\n{\n\tstatic const gchar * const types[] = {\n\t\t/* @TODO */\n\t\tNULL\n\t};\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeProtocol::dup_authentication_types\");\n\n\treturn(g_strdupv((GStrv) types));\n}\n\n/*\n * Protocol class - type implementation\n */\nstatic void sipe_protocol_class_init(SipeProtocolClass *klass)\n{\n\tTpBaseProtocolClass *base_class = TP_BASE_PROTOCOL_CLASS(klass);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeProtocol::class_init\");\n\n\tbase_class->get_parameters           = get_parameters;\n\tbase_class->new_connection           = sipe_telepathy_connection_new;\n\tbase_class->normalize_contact        = sipe_telepathy_protocol_normalize_contact;\n\tbase_class->identify_account         = identify_account;\n\tbase_class->get_interfaces           = get_interfaces;\n\tbase_class->get_connection_details   = get_connection_details;\n\tbase_class->dup_authentication_types = dup_authentication_types;\n}\n\nstatic void sipe_protocol_init(SIPE_UNUSED_PARAMETER SipeProtocol *self)\n{\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeProtocol::init\");\n}\n\n/* add protocol to connection manager */\nvoid sipe_telepathy_protocol_init(TpBaseConnectionManager *cm)\n{\n\tTpBaseProtocol *protocol = g_object_new(SIPE_TYPE_PROTOCOL,\n\t\t\t\t\t\t\"name\", SIPE_TELEPATHY_DOMAIN,\n\t\t\t\t\t\tNULL);\n\ttp_base_connection_manager_add_protocol(cm, protocol);\n\tg_object_unref(protocol);\n}\n\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/telepathy/telepathy-schedule.c",
    "content": "/**\n * @file telepathy-schedule.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2012 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <glib.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n\nstatic gboolean timeout_execute(gpointer data)\n{\n\tsipe_core_schedule_execute(data);\n\treturn(FALSE);\n}\n\ngpointer sipe_backend_schedule_seconds(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t       guint timeout,\n\t\t\t\t       gpointer data)\n{\n\treturn(GUINT_TO_POINTER(g_timeout_add_seconds(timeout, timeout_execute, data)));\n}\n\ngpointer sipe_backend_schedule_mseconds(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\tguint timeout,\n\t\t\t\t\tgpointer data)\n{\n\treturn(GUINT_TO_POINTER(g_timeout_add(timeout, timeout_execute, data)));\n}\n\nvoid sipe_backend_schedule_cancel(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t  gpointer data)\n{\n\tg_source_remove(GPOINTER_TO_UINT(data));\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/telepathy/telepathy-search.c",
    "content": "/**\n * @file telepathy-search.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2012-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <string.h>\n\n#include <glib-object.h>\n#include <telepathy-glib/svc-channel.h>\n#include <telepathy-glib/telepathy-glib.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n\n#include \"telepathy-private.h\"\n\n/* vCard/Telepathy search field names */\n#define SIPE_TELEPATHY_SEARCH_KEY_FIRST    \"x-n-given\"\n#define SIPE_TELEPATHY_SEARCH_KEY_LAST     \"x-n-family\"\n#define SIPE_TELEPATHY_SEARCH_KEY_EMAIL    \"email\"\n#define SIPE_TELEPATHY_SEARCH_KEY_COMPANY  \"x-org-name\"\n#define SIPE_TELEPATHY_SEARCH_KEY_COUNTRY  \"x-adr-country\"\n#define SIPE_TELEPATHY_SEARCH_KEY_FULLNAME \"fn\"\n#define SIPE_TELEPATHY_SEARCH_KEY_BLOB     \"\" /* one big search box */\n\nG_BEGIN_DECLS\n/*\n * Search Manager class - data structures\n */\ntypedef struct _SipeSearchManagerClass {\n\tGObjectClass parent_class;\n} SipeSearchManagerClass;\n\ntypedef struct _SipeSearchManager {\n\tGObject parent;\n\n\tGObject *connection;\n\n\tGHashTable *channels;\n} SipeSearchManager;\n\n/*\n * Search Manager class - type macros\n */\n/* telepathy-private.h: #define SIPE_TYPE_SEARCH_MANAGER ... */\n#define SIPE_SEARCH_MANAGER(obj) \\\n\t(G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_SEARCH_MANAGER, \\\n\t\t\t\t    SipeSearchManager))\n\n/*\n * Search Channel class - data structures\n */\ntypedef struct _SipeSearchChannelClass {\n\tTpBaseChannelClass parent_class;\n} SipeSearchChannelClass;\n\ntypedef struct _SipeSearchChannel {\n        TpBaseChannel parent;\n\n\tGObject *connection;\n\tGHashTable *results;\n\tTpChannelContactSearchState state;\n} SipeSearchChannel;\n\n/*\n * Search Channel class - type macros\n */\nstatic GType sipe_search_channel_get_type(void) G_GNUC_CONST;\n#define SIPE_TYPE_SEARCH_CHANNEL \\\n\t(sipe_search_channel_get_type())\n#define SIPE_SEARCH_CHANNEL(obj) \\\n\t(G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_SEARCH_CHANNEL, \\\n\t\t\t\t    SipeSearchChannel))\nG_END_DECLS\n\n/*\n * Search Manager class - type definition\n */\nstatic void channel_manager_iface_init(gpointer, gpointer);\nG_DEFINE_TYPE_WITH_CODE(SipeSearchManager,\n\t\t\tsipe_search_manager,\n\t\t\tG_TYPE_OBJECT,\n\t\t\tG_IMPLEMENT_INTERFACE(TP_TYPE_CHANNEL_MANAGER,\n\t\t\t\t\t      channel_manager_iface_init);\n)\n\n/*\n * Search Manager class - type definition\n */\nstatic void contact_search_iface_init(gpointer, gpointer);\nG_DEFINE_TYPE_WITH_CODE(SipeSearchChannel,\n\t\t\tsipe_search_channel,\n\t\t\tTP_TYPE_BASE_CHANNEL,\n\t\t\tG_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CHANNEL_TYPE_CONTACT_SEARCH,\n\t\t\t\t\t      contact_search_iface_init);\n)\n\n/*\n * Search Manager class - instance methods\n */\nstatic void sipe_search_manager_constructed(GObject *object)\n{\n\tSipeSearchManager *self     = SIPE_SEARCH_MANAGER(object);\n\tvoid (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_search_manager_parent_class)->constructed;\n\n\tif (chain_up)\n\t\tchain_up(object);\n\n\tself->channels = g_hash_table_new(g_direct_hash, g_direct_equal);\n}\n\nstatic void sipe_search_manager_dispose(GObject *object)\n{\n\tSipeSearchManager *self     = SIPE_SEARCH_MANAGER(object);\n\tvoid (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_search_manager_parent_class)->constructed;\n\n\ttp_clear_pointer(&self->channels, g_hash_table_unref);\n\ttp_clear_object(&self->connection);\n\n\tif (chain_up)\n\t\tchain_up(object);\n}\n\n/*\n * Search Manager class - type implementation\n */\nstatic void sipe_search_manager_class_init(SipeSearchManagerClass *klass)\n{\n\tGObjectClass *object_class = G_OBJECT_CLASS(klass);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeSearchManager::class_init\");\n\n\tobject_class->constructed  = sipe_search_manager_constructed;\n\tobject_class->dispose      = sipe_search_manager_dispose;\n}\n\nstatic void sipe_search_manager_init(SIPE_UNUSED_PARAMETER SipeSearchManager *self)\n{\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeSearchManager::init\");\n}\n\n/*\n * Search Manager class - interface implementation\n *\n * Channel Manager\n */\nstatic void foreach_channel(TpChannelManager *manager,\n\t\t\t    TpExportableChannelFunc func,\n\t\t\t    gpointer user_data)\n{\n\tSipeSearchManager *self = SIPE_SEARCH_MANAGER(manager);\n\tGHashTableIter iter;\n\tgpointer chan;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeSearchManager::foreach_channel\");\n\n\tg_hash_table_iter_init(&iter, self->channels);\n\twhile (g_hash_table_iter_next(&iter, &chan, NULL))\n\t\tfunc(chan, user_data);\n}\n\nstatic void type_foreach_channel_class(GType type,\n\t\t\t\t       TpChannelManagerTypeChannelClassFunc func,\n\t\t\t\t       gpointer user_data)\n{\n\tstatic const gchar *const no_props[] = {\n\t\tNULL\n\t};\n\tGHashTable *table = g_hash_table_new_full(g_str_hash, g_str_equal,\n\t\t\t\t\t\t  NULL,\n\t\t\t\t\t\t  (GDestroyNotify) tp_g_value_slice_free);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeSearchManager::type_foreach_channel_class\");\n\n\tg_hash_table_insert(table,\n\t\t\t    TP_IFACE_CHANNEL \".ChannelType\",\n\t\t\t    tp_g_value_slice_new_string(TP_IFACE_CHANNEL_TYPE_CONTACT_SEARCH));\n\tfunc(type, table, no_props, user_data);\n\tg_hash_table_unref(table);\n}\n\nstatic void search_channel_closed_cb(SipeSearchChannel *channel,\n\t\t\t\t     SipeSearchManager *self)\n{\n\tSIPE_DEBUG_INFO(\"SipeSearchManager::search_channel_close_cb: %p\", channel);\n\ttp_channel_manager_emit_channel_closed_for_object(self,\n\t\t\t\t\t\t\t  (TpExportableChannel *) channel);\n\tg_hash_table_remove(self->channels, channel);\n}\n\nstatic GObject *search_channel_new(GObject *connection);\nstatic gboolean create_channel(TpChannelManager *manager,\n\t\t\t       gpointer request_token,\n\t\t\t       GHashTable *request_properties)\n{\n\tSipeSearchManager *self = SIPE_SEARCH_MANAGER(manager);\n\tGObject *channel;\n\tGSList *request_tokens;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeSearchManager::create_channel\");\n\n\tif (tp_strdiff(tp_asv_get_string(request_properties,\n\t\t\t\t\t TP_IFACE_CHANNEL \".ChannelType\"),\n\t\t       TP_IFACE_CHANNEL_TYPE_CONTACT_SEARCH))\n\t\treturn(FALSE);\n\n\t/* create new search channel */\n\tchannel = search_channel_new(self->connection);\n\tg_hash_table_insert(self->channels, channel, NULL);\n\tg_signal_connect(channel,\n\t\t\t \"closed\",\n\t\t\t (GCallback) search_channel_closed_cb,\n\t\t\t self);\n\n\t/* publish new channel */\n\trequest_tokens = g_slist_prepend(NULL, request_token);\n\ttp_channel_manager_emit_new_channel(self,\n\t\t\t\t\t    TP_EXPORTABLE_CHANNEL(channel),\n\t\t\t\t\t    request_tokens);\n\tg_slist_free(request_tokens);\n\n\treturn(TRUE);\n}\n\nstatic void channel_manager_iface_init(gpointer g_iface,\n\t\t\t\t       SIPE_UNUSED_PARAMETER gpointer iface_data)\n{\n\tTpChannelManagerIface *iface = g_iface;\n\n#define IMPLEMENT(x, y) iface->x = y\n\tIMPLEMENT(foreach_channel,            foreach_channel);\n\tIMPLEMENT(type_foreach_channel_class, type_foreach_channel_class);\n\tIMPLEMENT(create_channel,             create_channel);\n\tIMPLEMENT(request_channel,            create_channel);\n\t/* Ensuring these channels doesn't really make much sense. */\n\tIMPLEMENT(ensure_channel,             NULL);\n#undef IMPLEMENT\n}\n\n/* create new search manager object */\nGObject *sipe_telepathy_search_new(TpBaseConnection *connection)\n{\n\tSipeSearchManager *self = g_object_new(SIPE_TYPE_SEARCH_MANAGER, NULL);\n\tself->connection = g_object_ref(G_OBJECT(connection));\n\treturn(G_OBJECT(self));\n}\n\n/*\n * Search Channel class - instance methods\n */\nenum {\n\tCHANNEL_PROP_SEARCH_KEYS = 1,\n\tCHANNEL_LAST_PROP\n};\n\nstatic void get_property(GObject *object,\n\t\t\t guint property_id,\n\t\t\t GValue *value,\n\t\t\t GParamSpec *pspec)\n{\n\tswitch (property_id)\n\t{\n\tcase CHANNEL_PROP_SEARCH_KEYS: {\n\t\t/* vCard/Telepathy search field names */\n\t\tstatic const gchar *search_keys[] = {\n\t\t\tSIPE_TELEPATHY_SEARCH_KEY_FIRST,\n\t\t\tSIPE_TELEPATHY_SEARCH_KEY_LAST,\n\t\t\tSIPE_TELEPATHY_SEARCH_KEY_EMAIL,\n\t\t\tSIPE_TELEPATHY_SEARCH_KEY_COMPANY,\n\t\t\tSIPE_TELEPATHY_SEARCH_KEY_COUNTRY,\n\t\t\tSIPE_TELEPATHY_SEARCH_KEY_FULLNAME,\n\t\t\tSIPE_TELEPATHY_SEARCH_KEY_BLOB,\n\t\t\tNULL\n\t\t};\n\t\tg_value_set_boxed(value, search_keys);\n\t}\n\t\tbreak;\n\tdefault:\n\t\tG_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);\n\t\tbreak;\n\t}\n}\n\nstatic void fill_immutable_properties(TpBaseChannel *channel,\n\t\t\t\t      GHashTable *properties)\n{\n\tTP_BASE_CHANNEL_CLASS(sipe_search_channel_parent_class)->fill_immutable_properties(channel,\n\t\t\t\t\t\t\t\t\t\t\t   properties);\n\ttp_dbus_properties_mixin_fill_properties_hash(G_OBJECT(channel),\n\t\t\t\t\t\t      properties,\n\t\t\t\t\t\t      TP_IFACE_CHANNEL_TYPE_CONTACT_SEARCH, \"AvailableSearchKeys\",\n\t\t\t\t\t\t      NULL);\n}\n\nstatic gchar *get_object_path_suffix(TpBaseChannel *base)\n{\n\treturn(g_strdup_printf (\"SearchChannel_%p\", base));\n}\n\nstatic GPtrArray *get_interfaces(TpBaseChannel *self)\n{\n\tGPtrArray *interfaces = TP_BASE_CHANNEL_CLASS(sipe_search_channel_parent_class)->get_interfaces(self);\n\treturn(interfaces);\n}\n\nstatic void sipe_search_channel_constructed(GObject *object)\n{\n\tSipeSearchChannel *self     = SIPE_SEARCH_CHANNEL(object);\n\tvoid (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_search_channel_parent_class)->constructed;\n\n\tif (chain_up)\n\t\tchain_up(object);\n\n\tself->results = NULL;\n}\n\nstatic void sipe_search_channel_finalize(GObject *object)\n{\n\tSipeSearchChannel *self = SIPE_SEARCH_CHANNEL(object);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeSearchChannel::finalize\");\n\n\tif (self->results)\n\t\tg_hash_table_unref(self->results);\n\n\tG_OBJECT_CLASS(sipe_search_channel_parent_class)->finalize(object);\n}\n\n/*\n * Search Channel class - type implementation\n */\nstatic void sipe_search_channel_class_init(SipeSearchChannelClass *klass)\n{\n\tstatic TpDBusPropertiesMixinPropImpl props[] = {\n\t\t{\n\t\t\t.name        = \"AvailableSearchKeys\",\n\t\t\t.getter_data = \"available-search-keys\",\n\t\t\t.setter_data = NULL\n\t\t},\n\t\t{\n\t\t\t.name        = NULL\n\t\t}\n\t};\n\tGObjectClass *object_class     = G_OBJECT_CLASS(klass);\n\tTpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS(klass);\n\tGParamSpec *ps;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeSearchChannel::class_init\");\n\n\tobject_class->constructed      = sipe_search_channel_constructed;\n\tobject_class->finalize         = sipe_search_channel_finalize;\n\tobject_class->get_property     = get_property;\n\n\tbase_class->channel_type       = TP_IFACE_CHANNEL_TYPE_CONTACT_SEARCH;\n\tbase_class->target_handle_type = TP_HANDLE_TYPE_NONE;\n\tbase_class->fill_immutable_properties = fill_immutable_properties;\n\tbase_class->get_object_path_suffix    = get_object_path_suffix;\n\tbase_class->interfaces         = NULL;\n\tbase_class->get_interfaces     = get_interfaces;\n\tbase_class->close              = tp_base_channel_destroyed;\n\n\tps = g_param_spec_boxed(\"available-search-keys\",\n\t\t\t\t\"Available search keys\",\n\t\t\t\t\"The set of search keys supported by this channel\",\n\t\t\t\tG_TYPE_STRV,\n\t\t\t\tG_PARAM_READABLE | G_PARAM_STATIC_STRINGS);\n\tg_object_class_install_property(object_class,\n\t\t\t\t\tCHANNEL_PROP_SEARCH_KEYS,\n\t\t\t\t\tps);\n\n\ttp_dbus_properties_mixin_implement_interface(object_class,\n\t\t\t\t\t\t     TP_IFACE_QUARK_CHANNEL_TYPE_CONTACT_SEARCH,\n\t\t\t\t\t\t     tp_dbus_properties_mixin_getter_gobject_properties,\n\t\t\t\t\t\t     NULL,\n\t\t\t\t\t\t     props);\n}\n\nstatic void sipe_search_channel_init(SIPE_UNUSED_PARAMETER SipeSearchChannel *self)\n{\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeSearchChannel::init\");\n}\n\n/*\n * Search Channel class - interface implementation\n *\n * Contact search\n */\nstatic void search_channel_state(SipeSearchChannel *self,\n\t\t\t\t TpChannelContactSearchState new_state,\n\t\t\t\t const gchar *msg)\n{\n\tGHashTable *details = tp_asv_new(NULL, NULL);\n\n\tif (msg)\n\t\ttp_asv_set_string(details, \"debug-message\", msg);\n\ttp_svc_channel_type_contact_search_emit_search_state_changed(self,\n\t\t\t\t\t\t\t\t     new_state,\n\t\t\t\t\t\t\t\t     msg ? msg : \"\",\n\t\t\t\t\t\t\t\t     details);\n\tg_hash_table_unref(details);\n\tself->state = new_state;\n}\n\nstatic void search_channel_search(TpSvcChannelTypeContactSearch *channel,\n\t\t\t\t  GHashTable *terms,\n\t\t\t\t  DBusGMethodInvocation *context)\n{\n\tSipeSearchChannel *self = SIPE_SEARCH_CHANNEL(channel);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeSearchChannel::search\");\n\n\tif (self->state == TP_CHANNEL_CONTACT_SEARCH_STATE_NOT_STARTED) {\n\t\tconst gchar *first   = g_hash_table_lookup(terms,\n\t\t\t\t\t\t\t  SIPE_TELEPATHY_SEARCH_KEY_FIRST);\n\t\tconst gchar *last    = g_hash_table_lookup(terms,\n\t\t\t\t\t\t\t   SIPE_TELEPATHY_SEARCH_KEY_LAST);\n\t\tconst gchar *email   = g_hash_table_lookup(terms,\n\t\t\t\t\t\t\t   SIPE_TELEPATHY_SEARCH_KEY_EMAIL);\n\t\tconst gchar *company = g_hash_table_lookup(terms,\n\t\t\t\t\t\t\t   SIPE_TELEPATHY_SEARCH_KEY_COMPANY);\n\t\tconst gchar *country = g_hash_table_lookup(terms,\n\t\t\t\t\t\t\t   SIPE_TELEPATHY_SEARCH_KEY_COUNTRY);\n\t\tstruct sipe_backend_private *telepathy_private = sipe_telepathy_connection_private(self->connection);\n\t\tgchar **split = NULL;\n\n\t\t/* did the requester honor our \"AvailableSearchKeys\"? */\n\t\tif (!(first || last || email || company || country)) {\n\t\t\tconst gchar *alternative = g_hash_table_lookup(terms,\n\t\t\t\t\t\t\t\t       SIPE_TELEPATHY_SEARCH_KEY_FULLNAME);\n\n\t\t\t/* No. Did he give a full name instead? */\n\t\t\tif (alternative) {\n\t\t\t\tSIPE_DEBUG_INFO(\"SipeSearchChannel::search: full name given: '%s'\",\n\t\t\t\t\t\talternative);\n\n\t\t\t\t/* assume:\n\t\t\t\t *  - one word  -> first name\n\t\t\t\t *  - two words -> first & last name\n\t\t\t\t */\n\t\t\t\tsplit = g_strsplit(alternative, \" \", 3);\n\t\t\t\tif (split[0]) {\n\t\t\t\t\tfirst = split[0];\n\t\t\t\t\tif (split[1])\n\t\t\t\t\t\tlast = split[1];\n\t\t\t\t}\n\n\t\t\t/* No. Did he give a \"on big search box\" instead? */\n\t\t\t} else if ((alternative = g_hash_table_lookup(terms,\n\t\t\t\t\t\t\t\t      SIPE_TELEPATHY_SEARCH_KEY_BLOB))\n\t\t\t\t   != NULL) {\n\n\t\t\t\tSIPE_DEBUG_INFO(\"SipeSearchChannel::search: one big search box given: '%s'\",\n\t\t\t\t\t\talternative);\n\t\t\t\t/* assume:\n\t\t\t\t *  - one word with '@' -> email\n\t\t\t\t *  - one word          -> first name\n\t\t\t\t *  - two words         -> first & last name\n\t\t\t\t */\n\t\t\t\tsplit = g_strsplit(alternative, \" \", 3);\n\t\t\t\tif (split[0]) {\n\t\t\t\t\tif (strchr(split[0], '@')) {\n\t\t\t\t\t\temail = split[0];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfirst = split[0];\n\t\t\t\t\t\tif (split[1])\n\t\t\t\t\t\t\tlast = split[1];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else\n\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"SipeSearchChannel::search: no valid terms found\");\n\t\t}\n\n\t\tsipe_core_buddy_search(telepathy_private->public,\n\t\t\t\t       (struct sipe_backend_search_token *) self,\n\t\t\t\t       first, last, email, NULL, company, country);\n\t\tg_strfreev(split);\n\n\t\t/* only switch to \"in progress\" if the above didn't fail */\n\t\tif (self->state == TP_CHANNEL_CONTACT_SEARCH_STATE_NOT_STARTED)\n\t\t\tsearch_channel_state(self,\n\t\t\t\t\t     TP_CHANNEL_CONTACT_SEARCH_STATE_IN_PROGRESS,\n\t\t\t\t\t     NULL);\n\n\t\ttp_svc_channel_type_contact_search_return_from_search(context);\n\t} else {\n\t\tGError *error = g_error_new(TP_ERROR, TP_ERROR_NOT_AVAILABLE,\n\t\t\t\t\t    \"invalid search state\");\n\t\tdbus_g_method_return_error(context, error);\n\t\tg_error_free(error);\n\t}\n}\n\nstatic void contact_search_iface_init(gpointer g_iface,\n\t\t\t\t      SIPE_UNUSED_PARAMETER gpointer iface_data)\n{\n\tTpSvcChannelTypeContactSearchClass *klass = g_iface;\n\n#define IMPLEMENT(x) tp_svc_channel_type_contact_search_implement_##x( \\\n\t\tklass, search_channel_##x)\n\tIMPLEMENT(search);\n\t/* we don't support stopping a search */\n#undef IMPLEMENT\n}\n\n/* create new search channel object */\nstatic GObject *search_channel_new(GObject *connection)\n{\n\t/* property \"connection\" required by TpBaseChannel */\n\tSipeSearchChannel *self = g_object_new(SIPE_TYPE_SEARCH_CHANNEL,\n\t\t\t\t\t       \"connection\", connection,\n\t\t\t\t\t       NULL);\n\n\tself->connection = g_object_ref(connection);\n\tself->state      = TP_CHANNEL_CONTACT_SEARCH_STATE_NOT_STARTED;\n\n\ttp_base_channel_register(TP_BASE_CHANNEL(self));\n\n\treturn(G_OBJECT(self));\n}\n\n/*\n * Backend adaptor functions\n */\nvoid sipe_backend_search_failed(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\tstruct sipe_backend_search_token *token,\n\t\t\t\tconst gchar *msg)\n{\n\tSIPE_DEBUG_INFO(\"sipe_backend_search_failed: %s\", msg);\n\tsearch_channel_state(SIPE_SEARCH_CHANNEL(token),\n\t\t\t     TP_CHANNEL_CONTACT_SEARCH_STATE_FAILED,\n\t\t\t     msg);\n}\n\nstatic void free_info(GPtrArray *info)\n{\n\tg_boxed_free(TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST, info);\n}\n\nstruct sipe_backend_search_results *sipe_backend_search_results_start(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t\t      struct sipe_backend_search_token *token)\n{\n\tSipeSearchChannel *self = SIPE_SEARCH_CHANNEL(token);\n\n\tself->results = g_hash_table_new_full(g_str_hash, g_str_equal,\n\t\t\t\t\t      g_free,\n\t\t\t\t\t      (GDestroyNotify) free_info);\n\n\treturn((struct sipe_backend_search_results *) self);\n}\n\n/* adds: the Contact_Info_Field (field_name, [], values) */\nstatic void add_search_result(GPtrArray *info,\n\t\t\t      const gchar *field_name,\n\t\t\t      const gchar *field_value)\n{\n\tif (field_value) {\n\t\tstatic const gchar **empty = { NULL };\n\t\tGValueArray *field         = g_value_array_new(3);\n\t\tconst gchar *components[]  = { field_value, NULL };\n\t\tGValue *value;\n\n\t\tSIPE_DEBUG_INFO(\"add_search_result: %s = '%s'\",\n\t\t\t\tfield_name, field_value);\n\n\t\tg_value_array_append(field, NULL);\n\t\tvalue = g_value_array_get_nth(field, 0);\n\t\tg_value_init(value, G_TYPE_STRING);\n\t\tg_value_set_static_string(value, field_name);\n\n\t\tg_value_array_append(field, NULL);\n\t\tvalue = g_value_array_get_nth(field, 1);\n\t\tg_value_init(value, G_TYPE_STRV);\n\t\tg_value_set_static_boxed(value, empty);\n\n\t\tg_value_array_append(field, NULL);\n\t\tvalue = g_value_array_get_nth(field, 2);\n\t\tg_value_init(value, G_TYPE_STRV);\n\t\tg_value_set_boxed(value, components);\n\n\t\tg_ptr_array_add(info, field);\n\t}\n}\n\nvoid sipe_backend_search_results_add(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t     struct sipe_backend_search_results *results,\n\t\t\t\t     const gchar *uri,\n\t\t\t\t     const gchar *name,\n\t\t\t\t     const gchar *company,\n\t\t\t\t     const gchar *country,\n\t\t\t\t     const gchar *email)\n{\n\tSipeSearchChannel *self = SIPE_SEARCH_CHANNEL(results);\n\tGPtrArray *info         = g_ptr_array_new();\n\n\tadd_search_result(info, SIPE_TELEPATHY_SEARCH_KEY_FULLNAME, name);\n\tadd_search_result(info, SIPE_TELEPATHY_SEARCH_KEY_COMPANY,  company);\n\tadd_search_result(info, SIPE_TELEPATHY_SEARCH_KEY_COUNTRY,  country);\n\tadd_search_result(info, SIPE_TELEPATHY_SEARCH_KEY_EMAIL,    email);\n\n\tg_hash_table_insert(self->results, g_strdup(uri), info);\n}\n\nvoid sipe_backend_search_results_finalize(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t  struct sipe_backend_search_results *results,\n\t\t\t\t\t  SIPE_UNUSED_PARAMETER const gchar *description,\n\t\t\t\t\t  SIPE_UNUSED_PARAMETER gboolean more)\n{\n\tSipeSearchChannel *self = SIPE_SEARCH_CHANNEL(results);\n\n\ttp_svc_channel_type_contact_search_emit_search_result_received(self,\n\t\t\t\t\t\t\t\t       self->results);\n\tsearch_channel_state(self,\n\t\t\t     TP_CHANNEL_CONTACT_SEARCH_STATE_COMPLETED,\n\t\t\t     NULL);\n}\n\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/telepathy/telepathy-status.c",
    "content": "/**\n * @file telepathy-status.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2012-2019 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib-object.h>\n#include <telepathy-glib/base-connection.h>\n#include <telepathy-glib/telepathy-glib.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n\n#include \"telepathy-private.h\"\n\nstatic const TpPresenceStatusOptionalArgumentSpec args[] = {\n\t{ .name = \"message\", .dtype = \"s\"  },\n\t{ .name = NULL,      .dtype = NULL }\n};\n\n/* Sipe core activity <-> Telepathy status mapping */\n#define SIPE_TELEPATHY_STATUS(_name, _type, _self, _args) \\\n\t{                                      \\\n\t\t.name               = (_name), \\\n\t\t.presence_type      = (_type), \\\n\t\t.self               = (_self), \\\n\t\t.optional_arguments = (_args), \\\n\t}\n#define SIPE_TELEPATHY_STATUS_NONE(_name, _type, _self) \\\n\tSIPE_TELEPATHY_STATUS(_name, _type, _self, NULL)\n#define SIPE_TELEPATHY_STATUS_MESSAGE(_name, _type, _self) \\\n\tSIPE_TELEPATHY_STATUS(_name, _type, _self, args)\nstatic const TpPresenceStatusSpec statuses[SIPE_ACTIVITY_NUM_TYPES + 1] = {\n/* SIPE_ACTIVITY_UNSET       */ SIPE_TELEPATHY_STATUS_NONE(   \"unset\",           TP_CONNECTION_PRESENCE_TYPE_UNSET,         FALSE),\n/* SIPE_ACTIVITY_AVAILABLE   */ SIPE_TELEPATHY_STATUS_MESSAGE(\"available\",       TP_CONNECTION_PRESENCE_TYPE_AVAILABLE,     TRUE),\n/* SIPE_ACTIVITY_ONLINE      */ SIPE_TELEPATHY_STATUS_MESSAGE(\"online\",          TP_CONNECTION_PRESENCE_TYPE_AVAILABLE,     TRUE),\n/* SIPE_ACTIVITY_INACTIVE    */ SIPE_TELEPATHY_STATUS_MESSAGE(\"idle\",            TP_CONNECTION_PRESENCE_TYPE_AWAY,          TRUE),\n/* SIPE_ACTIVITY_BUSY        */ SIPE_TELEPATHY_STATUS_MESSAGE(\"busy\",            TP_CONNECTION_PRESENCE_TYPE_BUSY,          TRUE),\n/* SIPE_ACTIVITY_BUSYIDLE    */ SIPE_TELEPATHY_STATUS_MESSAGE(\"busyidle\",        TP_CONNECTION_PRESENCE_TYPE_BUSY,          TRUE),\n/* SIPE_ACTIVITY_DND         */ SIPE_TELEPATHY_STATUS_MESSAGE(\"do-not-disturb\",  TP_CONNECTION_PRESENCE_TYPE_BUSY,          TRUE),\n/* SIPE_ACTIVITY_BRB         */ SIPE_TELEPATHY_STATUS_MESSAGE(\"be-right-back\",   TP_CONNECTION_PRESENCE_TYPE_AWAY,          TRUE),\n/* SIPE_ACTIVITY_AWAY        */ SIPE_TELEPATHY_STATUS_MESSAGE(\"away\",            TP_CONNECTION_PRESENCE_TYPE_AWAY,          TRUE),\n/* SIPE_ACTIVITY_LUNCH       */ SIPE_TELEPATHY_STATUS_MESSAGE(\"out-to-lunch\",    TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY, TRUE),\n/* SIPE_ACTIVITY_INVISIBLE   */ SIPE_TELEPATHY_STATUS_NONE(   \"invisible\",       TP_CONNECTION_PRESENCE_TYPE_HIDDEN,        TRUE),\n/* SIPE_ACTIVITY_OFFLINE     */ SIPE_TELEPATHY_STATUS_NONE(   \"offline\",         TP_CONNECTION_PRESENCE_TYPE_OFFLINE,       FALSE),\n/* SIPE_ACTIVITY_ON_PHONE    */ SIPE_TELEPATHY_STATUS_MESSAGE(\"on-the-phone\",    TP_CONNECTION_PRESENCE_TYPE_BUSY,          TRUE),\n/* SIPE_ACTIVITY_IN_CONF     */ SIPE_TELEPATHY_STATUS_MESSAGE(\"in-a-conference\", TP_CONNECTION_PRESENCE_TYPE_BUSY,          TRUE),\n/* SIPE_ACTIVITY_IN_MEETING  */ SIPE_TELEPATHY_STATUS_MESSAGE(\"in-a-meeting\",    TP_CONNECTION_PRESENCE_TYPE_BUSY,          TRUE),\n/* SIPE_ACTIVITY_OOF         */ SIPE_TELEPATHY_STATUS_MESSAGE(\"out-of-office\",   TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY, TRUE),\n/* SIPE_ACTIVITY_URGENT_ONLY */ SIPE_TELEPATHY_STATUS_MESSAGE(\"urgent-interruptions-only\", TP_CONNECTION_PRESENCE_TYPE_BUSY, TRUE),\n/* end-of-array indicator    */ SIPE_TELEPATHY_STATUS_NONE(   NULL,              0,                                         FALSE)\n};\n\nstatic gboolean status_available(SIPE_UNUSED_PARAMETER GObject *object,\n\t\t\t\t guint index)\n{\n\t/*\n\t * @TODO: what is this function supposed to do?\n\t *  - TRUE: index is one of the \"user is available\" statuses?\n\t *  - TRUE: index is a valid status?\n\t */\n\treturn(statuses[index].name != NULL);\n}\n\nstatic GHashTable *get_contact_statuses(GObject *object,\n\t\t\t\t\tconst GArray *contacts,\n\t\t\t\t\tSIPE_UNUSED_PARAMETER GError **error)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_telepathy_connection_private(object);\n\tTpBaseConnection *base = TP_BASE_CONNECTION(object);\n\tGHashTable *status_table = g_hash_table_new(g_direct_hash,\n\t\t\t\t\t\t    g_direct_equal);\n\tguint i;\n\n\tfor (i = 0; i < contacts->len; i++) {\n\t\tTpHandle contact = g_array_index(contacts, guint, i);\n\t\tguint activity;\n\t\tGHashTable *parameters;\n\n\t\t/* we get our own status from the connection, and everyone\n\t\t *  else's status from the contact lists */\n\t\tif (contact == tp_base_connection_get_self_handle(base)) {\n\t\t\tactivity = telepathy_private->activity;\n\t\t} else {\n\t\t\t/* @TODO */\n\t\t\tactivity = sipe_telepathy_buddy_get_presence(telepathy_private->contact_list,\n\t\t\t\t\t\t\t\t     contact);\n\t\t}\n\n\t\tparameters = g_hash_table_new_full(g_str_hash,\n\t\t\t\t\t\t   g_str_equal,\n\t\t\t\t\t\t   NULL,\n\t\t\t\t\t\t   (GDestroyNotify) tp_g_value_slice_free);\n\t\tg_hash_table_insert(status_table,\n\t\t\t\t    GUINT_TO_POINTER(contact),\n\t\t\t\t    tp_presence_status_new(activity,\n\t\t\t\t\t\t\t   parameters));\n\t\tg_hash_table_unref(parameters);\n\t}\n\n\treturn(status_table);\n}\n\nstatic void update_status(struct sipe_backend_private *telepathy_private,\n\t\t\t  guint activity,\n\t\t\t  const gchar *message,\n\t\t\t  const TpPresenceStatus *status,\n\t\t\t  gboolean outgoing)\n{\n\tGObject *connection = G_OBJECT(telepathy_private->connection);\n\tGHashTable *presences;\n\n\t/* update internal status */\n\ttelepathy_private->activity = activity;\n\tg_free(telepathy_private->message);\n\ttelepathy_private->message  = NULL;\n\tif (message)\n\t\ttelepathy_private->message = g_strdup(message);\n\n\t/* outgoing status update */\n\tif (outgoing)\n\t\tsipe_core_status_set(telepathy_private->public,\n\t\t\t\t     TRUE,\n\t\t\t\t     activity,\n\t\t\t\t     message);\n\n\t/* emit status update signal */\n\tpresences = g_hash_table_new(g_direct_hash, g_direct_equal);\n\tg_hash_table_insert(presences,\n\t\t\t    GUINT_TO_POINTER(tp_base_connection_get_self_handle(TP_BASE_CONNECTION(connection))),\n\t\t\t    (gpointer) status);\n\ttp_presence_mixin_emit_presence_update(connection, presences);\n\tg_hash_table_unref(presences);\n}\n\nstatic gboolean set_own_status(GObject *object,\n\t\t\t       const TpPresenceStatus *status,\n\t\t\t       SIPE_UNUSED_PARAMETER GError **error)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_telepathy_connection_private(object);\n\tguint activity                                 = SIPE_ACTIVITY_AVAILABLE;\n\tconst gchar *message                           = NULL;\n\n\tif (!telepathy_private)\n\t\treturn(FALSE);\n\n\tif (status) {\n\t\tactivity = status->index;\n\n\t\tif (status->optional_arguments)\n\t\t\tmessage = tp_asv_get_string(status->optional_arguments,\n\t\t\t\t\t\t    \"message\");\n\t}\n\n\tSIPE_DEBUG_INFO(\"set_own_status: %d '%s'\", activity,\n\t\t\tmessage ? message : \"(none)\");\n\tupdate_status(telepathy_private, activity, message, status, TRUE);\n\n\n\treturn(TRUE);\n}\n\nvoid sipe_telepathy_status_init(GObjectClass *object_class,\n\t\t\t\tgsize struct_offset)\n{\n\ttp_presence_mixin_class_init(object_class,\n\t\t\t\t     struct_offset,\n\t\t\t\t     status_available,\n\t\t\t\t     get_contact_statuses,\n\t\t\t\t     set_own_status,\n\t\t\t\t     statuses);\n}\n\n\n/*\n * Backend adaptor functions\n */\nguint sipe_backend_status(struct sipe_core_public *sipe_public)\n{\n\treturn(sipe_public->backend_private->activity);\n}\n\ngboolean sipe_backend_status_changed(struct sipe_core_public *sipe_public,\n\t\t\t\t     guint activity,\n\t\t\t\t     const gchar *message)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_public->backend_private;\n\n\tif ((activity == telepathy_private->activity) &&\n\t    sipe_strequal(message, telepathy_private->message))\n\t\treturn(FALSE);\n\n\treturn(TRUE);\n}\n\n/*\n * This is used by:\n *\n *    - incoming status updates (roaming)\n *    - induced status updates (calendar)\n */\nvoid sipe_backend_status_and_note(struct sipe_core_public *sipe_public,\n\t\t\t\t  guint activity,\n\t\t\t\t  const gchar *message)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_public->backend_private;\n\tGHashTable *optional = NULL;\n\tTpPresenceStatus *status;\n\n\tif (message)\n\t\toptional = tp_asv_new(\"message\", G_TYPE_STRING, message,\n\t\t\t\t      NULL);\n\n\tstatus = tp_presence_status_new(activity, optional);\n\tif (optional)\n\t\tg_hash_table_unref(optional);\n\n\tupdate_status(telepathy_private, activity, message, status, FALSE);\n\ttp_presence_status_free(status);\n}\n\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/telepathy/telepathy-stubs.c",
    "content": "/**\n * @file telepathy-stubs.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2012-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n/*\n * Stubs for all unimplemented backend functions, because\n *\n *    - feature is not yet implemented, or\n *    - feature can't be implemented for telepathy backend\n *\n * Ordering copied from sipe-backend.h\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <glib.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n\n/** BUDDIES ******************************************************************/\n\nvoid sipe_backend_buddy_list_processing_start(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public) {}\nvoid sipe_backend_buddy_request_add(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t    SIPE_UNUSED_PARAMETER const gchar *who,\n\t\t\t\t    SIPE_UNUSED_PARAMETER const gchar *alias) {}\nvoid sipe_backend_buddy_request_authorization(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t      SIPE_UNUSED_PARAMETER const gchar *who,\n\t\t\t\t\t      SIPE_UNUSED_PARAMETER const gchar *alias,\n\t\t\t\t\t      SIPE_UNUSED_PARAMETER gboolean on_list,\n\t\t\t\t\t      SIPE_UNUSED_PARAMETER sipe_backend_buddy_request_authorization_cb auth_cb,\n\t\t\t\t\t      SIPE_UNUSED_PARAMETER sipe_backend_buddy_request_authorization_cb deny_cb,\n\t\t\t\t\t      SIPE_UNUSED_PARAMETER gpointer data) {}\ngboolean sipe_backend_buddy_is_blocked(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t       SIPE_UNUSED_PARAMETER const gchar *who) { return(FALSE); }\nvoid sipe_backend_buddy_set_blocked_status(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t   SIPE_UNUSED_PARAMETER const gchar *who,\n\t\t\t\t\t   SIPE_UNUSED_PARAMETER gboolean blocked) {}\ngboolean sipe_backend_buddy_group_rename(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t SIPE_UNUSED_PARAMETER const gchar *old_name,\n\t\t\t\t\t SIPE_UNUSED_PARAMETER const gchar *new_name) { return(FALSE); }\nstruct sipe_backend_buddy_info *sipe_backend_buddy_info_start(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public) {  return(NULL); }\nvoid sipe_backend_buddy_info_add(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t SIPE_UNUSED_PARAMETER struct sipe_backend_buddy_info *info,\n\t\t\t\t SIPE_UNUSED_PARAMETER sipe_buddy_info_fields key,\n\t\t\t\t SIPE_UNUSED_PARAMETER const gchar *value) {}\nvoid sipe_backend_buddy_info_break(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t   SIPE_UNUSED_PARAMETER struct sipe_backend_buddy_info *info) {}\nvoid sipe_backend_buddy_info_finalize(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t      SIPE_UNUSED_PARAMETER struct sipe_backend_buddy_info *info,\n\t\t\t\t      SIPE_UNUSED_PARAMETER const gchar *uri) {}\nvoid sipe_backend_buddy_tooltip_add(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t    SIPE_UNUSED_PARAMETER struct sipe_backend_buddy_tooltip *tooltip,\n\t\t\t\t    SIPE_UNUSED_PARAMETER const gchar *description,\n\t\t\t\t    SIPE_UNUSED_PARAMETER const gchar *value) {}\nstruct sipe_backend_buddy_menu *sipe_backend_buddy_menu_start(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public) { return(NULL); }\nstruct sipe_backend_buddy_menu *sipe_backend_buddy_menu_add(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t    SIPE_UNUSED_PARAMETER struct sipe_backend_buddy_menu *menu,\n\t\t\t\t\t\t\t    SIPE_UNUSED_PARAMETER const gchar *label,\n\t\t\t\t\t\t\t    SIPE_UNUSED_PARAMETER enum sipe_buddy_menu_type type,\n\t\t\t\t\t\t\t    SIPE_UNUSED_PARAMETER gpointer parameter) { return(NULL); }\nstruct sipe_backend_buddy_menu *sipe_backend_buddy_menu_separator(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t\t  SIPE_UNUSED_PARAMETER struct sipe_backend_buddy_menu *menu,\n\t\t\t\t\t\t\t\t  SIPE_UNUSED_PARAMETER const gchar *label) { return(NULL); }\nstruct sipe_backend_buddy_menu *sipe_backend_buddy_sub_menu_add(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t\tSIPE_UNUSED_PARAMETER struct sipe_backend_buddy_menu *menu,\n\t\t\t\t\t\t\t\tSIPE_UNUSED_PARAMETER const gchar *label,\n\t\t\t\t\t\t\t\tSIPE_UNUSED_PARAMETER struct sipe_backend_buddy_menu *sub) { return(NULL); }\n\n/** CHAT *********************************************************************/\n\nvoid sipe_backend_chat_session_destroy(SIPE_UNUSED_PARAMETER struct sipe_backend_chat_session *session) {}\nvoid sipe_backend_chat_add(SIPE_UNUSED_PARAMETER struct sipe_backend_chat_session *backend_session,\n\t\t\t   SIPE_UNUSED_PARAMETER const gchar *uri,\n\t\t\t   SIPE_UNUSED_PARAMETER gboolean is_new) {}\nvoid sipe_backend_chat_close(SIPE_UNUSED_PARAMETER struct sipe_backend_chat_session *backend_session) {}\nstruct sipe_backend_chat_session *sipe_backend_chat_create(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t   SIPE_UNUSED_PARAMETER struct sipe_chat_session *session,\n\t\t\t\t\t\t\t   SIPE_UNUSED_PARAMETER const gchar *title,\n\t\t\t\t\t\t\t   SIPE_UNUSED_PARAMETER const gchar *nick) { return(NULL); }\ngboolean sipe_backend_chat_find(SIPE_UNUSED_PARAMETER struct sipe_backend_chat_session *backend_session,\n\t\t\t\tSIPE_UNUSED_PARAMETER const gchar *uri) { return(FALSE); }\ngboolean sipe_backend_chat_is_operator(SIPE_UNUSED_PARAMETER struct sipe_backend_chat_session *backend_session,\n\t\t\t\t       SIPE_UNUSED_PARAMETER const gchar *uri) { return(FALSE); }\nvoid sipe_backend_chat_message(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t       SIPE_UNUSED_PARAMETER struct sipe_backend_chat_session *backend_session,\n\t\t\t       SIPE_UNUSED_PARAMETER const gchar *from,\n\t\t\t       SIPE_UNUSED_PARAMETER time_t when,\n\t\t\t       SIPE_UNUSED_PARAMETER const gchar *html) {}\nvoid sipe_backend_chat_operator(SIPE_UNUSED_PARAMETER struct sipe_backend_chat_session *backend_session,\n\t\t\t\tSIPE_UNUSED_PARAMETER const gchar *uri) {}\nvoid sipe_backend_chat_rejoin(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t      SIPE_UNUSED_PARAMETER struct sipe_backend_chat_session *backend_session,\n\t\t\t      SIPE_UNUSED_PARAMETER const gchar *nick,\n\t\t\t      SIPE_UNUSED_PARAMETER const gchar *title) {}\nvoid sipe_backend_chat_rejoin_all(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public) {}\nvoid sipe_backend_chat_remove(SIPE_UNUSED_PARAMETER struct sipe_backend_chat_session *backend_session,\n\t\t\t      SIPE_UNUSED_PARAMETER const gchar *uri) {}\nvoid sipe_backend_chat_show(SIPE_UNUSED_PARAMETER struct sipe_backend_chat_session *backend_session) {}\nvoid sipe_backend_chat_topic(SIPE_UNUSED_PARAMETER struct sipe_backend_chat_session *backend_session,\n\t\t\t     SIPE_UNUSED_PARAMETER const gchar *topic) {}\n\n/** FILE TRANSFER ************************************************************/\n\nvoid sipe_backend_ft_error(SIPE_UNUSED_PARAMETER struct sipe_file_transfer *ft,\n\t\t\t   SIPE_UNUSED_PARAMETER const gchar *errmsg) {}\nconst gchar *sipe_backend_ft_get_error(SIPE_UNUSED_PARAMETER struct sipe_file_transfer *ft) { return(\"\"); }\nvoid sipe_backend_ft_deallocate(SIPE_UNUSED_PARAMETER struct sipe_file_transfer *ft) {}\ngssize sipe_backend_ft_read(SIPE_UNUSED_PARAMETER struct sipe_file_transfer *ft,\n\t\t\t    SIPE_UNUSED_PARAMETER guchar *data,\n\t\t\t    SIPE_UNUSED_PARAMETER gsize size) { return(-1); }\ngssize sipe_backend_ft_write(SIPE_UNUSED_PARAMETER struct sipe_file_transfer *ft,\n\t\t\t     SIPE_UNUSED_PARAMETER const guchar *data,\n\t\t\t     SIPE_UNUSED_PARAMETER gsize size) { return(-1); }\nvoid sipe_backend_ft_set_completed(SIPE_UNUSED_PARAMETER struct sipe_file_transfer *ft) {}\nvoid sipe_backend_ft_cancel_local(SIPE_UNUSED_PARAMETER struct sipe_file_transfer *ft) {}\nvoid sipe_backend_ft_cancel_remote(SIPE_UNUSED_PARAMETER struct sipe_file_transfer *ft) {}\nvoid sipe_backend_ft_incoming(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t      SIPE_UNUSED_PARAMETER struct sipe_file_transfer *ft,\n\t\t\t      SIPE_UNUSED_PARAMETER const gchar *who,\n\t\t\t      SIPE_UNUSED_PARAMETER const gchar *file_name,\n\t\t\t      SIPE_UNUSED_PARAMETER gsize file_size) {}\nvoid sipe_backend_ft_outgoing(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t      SIPE_UNUSED_PARAMETER struct sipe_file_transfer *ft,\n\t\t\t      SIPE_UNUSED_PARAMETER const gchar *who,\n\t\t\t      SIPE_UNUSED_PARAMETER const gchar *file_name) {}\nvoid sipe_backend_ft_start(SIPE_UNUSED_PARAMETER struct sipe_file_transfer *ft,\n\t\t\t   SIPE_UNUSED_PARAMETER struct sipe_backend_fd *fd,\n\t\t\t   SIPE_UNUSED_PARAMETER const char* ip,\n\t\t\t   SIPE_UNUSED_PARAMETER unsigned port) {}\ngboolean sipe_backend_ft_is_incoming(SIPE_UNUSED_PARAMETER struct sipe_file_transfer *ft) { return(FALSE); }\n\n/** GROUP CHAT ***************************************************************/\n\nvoid sipe_backend_groupchat_room_add(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t     SIPE_UNUSED_PARAMETER const gchar *uri,\n\t\t\t\t     SIPE_UNUSED_PARAMETER const gchar *name,\n\t\t\t\t     SIPE_UNUSED_PARAMETER const gchar *description,\n\t\t\t\t     SIPE_UNUSED_PARAMETER guint users,\n\t\t\t\t     SIPE_UNUSED_PARAMETER guint32 flags) {}\nvoid sipe_backend_groupchat_room_terminate(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public) {}\n\n/** IM ***********************************************************************/\n\nvoid sipe_backend_im_message(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t     SIPE_UNUSED_PARAMETER const gchar *from,\n\t\t\t     SIPE_UNUSED_PARAMETER const gchar *html) {}\nvoid sipe_backend_im_topic(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t   SIPE_UNUSED_PARAMETER const gchar *with,\n\t\t\t   SIPE_UNUSED_PARAMETER const gchar *topic) {}\n\n/** MARKUP *******************************************************************/\n\ngchar *sipe_backend_markup_css_property(SIPE_UNUSED_PARAMETER SIPE_UNUSED_PARAMETER const gchar *style,\n\t\t\t\t\tSIPE_UNUSED_PARAMETER const gchar *option) { return(g_strdup(\"\")); }\ngchar *sipe_backend_markup_strip_html(SIPE_UNUSED_PARAMETER SIPE_UNUSED_PARAMETER const gchar *html) { return(g_strdup(\"\")); }\n\n/** MEDIA ********************************************************************/\n#ifdef HAVE_VV\nstruct sipe_backend_media *sipe_backend_media_new(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t  SIPE_UNUSED_PARAMETER struct sipe_media_call *call,\n\t\t\t\t\t\t  SIPE_UNUSED_PARAMETER const gchar *participant,\n\t\t\t\t\t\t  SIPE_UNUSED_PARAMETER SipeMediaCallFlags flags) { return(NULL); }\nvoid sipe_backend_media_free(SIPE_UNUSED_PARAMETER struct sipe_backend_media *media) {}\nvoid sipe_backend_media_set_cname(SIPE_UNUSED_PARAMETER struct sipe_backend_media *media,\n\t\t\t\t  SIPE_UNUSED_PARAMETER gchar *cname) {}\nstruct sipe_backend_media_relays * sipe_backend_media_relays_convert(SIPE_UNUSED_PARAMETER GSList *media_relays,\n\t\t\t\t\t\t\t\t     SIPE_UNUSED_PARAMETER gchar *username,\n\t\t\t\t\t\t\t\t     SIPE_UNUSED_PARAMETER gchar *password) { return(NULL); }\nvoid sipe_backend_media_relays_free(SIPE_UNUSED_PARAMETER struct sipe_backend_media_relays *media_relays) {}\nstruct sipe_backend_media_stream *sipe_backend_media_add_stream(SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream,\n\t\t\t\t\t\t\t\tSIPE_UNUSED_PARAMETER SipeMediaType type,\n\t\t\t\t\t\t\t\tSIPE_UNUSED_PARAMETER SipeIceVersion ice_version,\n\t\t\t\t\t\t\t\tSIPE_UNUSED_PARAMETER gboolean initiator,\n\t\t\t\t\t\t\t\tSIPE_UNUSED_PARAMETER struct sipe_backend_media_relays *media_relays,\n\t\t\t\t\t\t\t\tSIPE_UNUSED_PARAMETER guint min_port,\n\t\t\t\t\t\t\t\tSIPE_UNUSED_PARAMETER guint max_port) { return(NULL); }\nvoid sipe_backend_media_add_remote_candidates(SIPE_UNUSED_PARAMETER struct sipe_media_call *media,\n\t\t\t\t\t      SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream,\n\t\t\t\t\t      SIPE_UNUSED_PARAMETER GList *candidates) {}\ngboolean sipe_backend_media_is_initiator(SIPE_UNUSED_PARAMETER struct sipe_media_call *media,\n\t\t\t\t\t SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream) { return(FALSE); }\ngboolean sipe_backend_media_accepted(SIPE_UNUSED_PARAMETER struct sipe_backend_media *media) { return(FALSE); }\ngboolean sipe_backend_stream_initialized(SIPE_UNUSED_PARAMETER struct sipe_media_call *media,\n\t\t\t\t\t SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream) { return(FALSE); }\nGList *sipe_backend_media_stream_get_active_local_candidates(SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream) { return(NULL); }\nGList *sipe_backend_media_stream_get_active_remote_candidates(SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream) { return(NULL); }\nvoid sipe_backend_media_set_encryption_keys(SIPE_UNUSED_PARAMETER struct sipe_media_call *media,\n\t\t\t\t\t    SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream,\n\t\t\t\t\t    SIPE_UNUSED_PARAMETER const guchar *encryption_key,\n\t\t\t\t\t    SIPE_UNUSED_PARAMETER const guchar *decryption_key) {}\nvoid sipe_backend_media_set_require_encryption(SIPE_UNUSED_PARAMETER struct sipe_media_call *media,\n\t\t\t\t\t       SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream,\n\t\t\t\t\t       SIPE_UNUSED_PARAMETER const gboolean require_encryption) {}\nvoid sipe_backend_stream_hold(SIPE_UNUSED_PARAMETER struct sipe_media_call *media,\n\t\t\t      SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream,\n\t\t\t      SIPE_UNUSED_PARAMETER gboolean local) {}\nvoid sipe_backend_stream_unhold(SIPE_UNUSED_PARAMETER struct sipe_media_call *media,\n\t\t\t\tSIPE_UNUSED_PARAMETER struct sipe_media_stream *stream,\n\t\t\t\tSIPE_UNUSED_PARAMETER gboolean local) {}\ngboolean sipe_backend_stream_is_held(SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream) { return(FALSE); }\nvoid sipe_backend_media_stream_end(SIPE_UNUSED_PARAMETER struct sipe_media_call *media,\n\t\t\t\t   SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream) {}\nvoid sipe_backend_media_stream_free(SIPE_UNUSED_PARAMETER struct sipe_backend_media_stream *stream) {}\nstruct sipe_backend_codec *sipe_backend_codec_new(SIPE_UNUSED_PARAMETER int id,\n\t\t\t\t\t\t  SIPE_UNUSED_PARAMETER const char *name,\n\t\t\t\t\t\t  SIPE_UNUSED_PARAMETER SipeMediaType type,\n\t\t\t\t\t\t  SIPE_UNUSED_PARAMETER guint clock_rate,\n\t\t\t\t\t\t  SIPE_UNUSED_PARAMETER guint channels) { return(NULL); }\nvoid sipe_backend_codec_free(SIPE_UNUSED_PARAMETER struct sipe_backend_codec *codec) {}\nint sipe_backend_codec_get_id(SIPE_UNUSED_PARAMETER struct sipe_backend_codec *codec) { return(0); }\ngchar *sipe_backend_codec_get_name(SIPE_UNUSED_PARAMETER struct sipe_backend_codec *codec) { return(g_strdup(\"\")); }\nguint sipe_backend_codec_get_clock_rate(SIPE_UNUSED_PARAMETER struct sipe_backend_codec *codec) { return(0); }\nvoid sipe_backend_codec_add_optional_parameter(SIPE_UNUSED_PARAMETER struct sipe_backend_codec *codec,\n\t\t\t\t\t       SIPE_UNUSED_PARAMETER const gchar *name,\n\t\t\t\t\t       SIPE_UNUSED_PARAMETER const gchar *value) {}\nGList *sipe_backend_codec_get_optional_parameters(SIPE_UNUSED_PARAMETER struct sipe_backend_codec *codec) { return(NULL); }\ngboolean sipe_backend_set_remote_codecs(SIPE_UNUSED_PARAMETER struct sipe_media_call *media,\n\t\t\t\t\tSIPE_UNUSED_PARAMETER struct sipe_media_stream *stream,\n\t\t\t\t\tSIPE_UNUSED_PARAMETER GList *codecs) { return(FALSE); }\nGList* sipe_backend_get_local_codecs(SIPE_UNUSED_PARAMETER struct sipe_media_call *media,\n\t\t\t\t     SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream) { return(NULL); }\nstruct sipe_backend_candidate * sipe_backend_candidate_new(SIPE_UNUSED_PARAMETER const gchar *foundation,\n\t\t\t\t\t\t\t   SIPE_UNUSED_PARAMETER SipeComponentType component,\n\t\t\t\t\t\t\t   SIPE_UNUSED_PARAMETER SipeCandidateType type,\n\t\t\t\t\t\t\t   SIPE_UNUSED_PARAMETER SipeNetworkProtocol proto,\n\t\t\t\t\t\t\t   SIPE_UNUSED_PARAMETER const gchar *ip,\n\t\t\t\t\t\t\t   SIPE_UNUSED_PARAMETER guint port,\n\t\t\t\t\t\t\t   SIPE_UNUSED_PARAMETER const gchar *username,\n\t\t\t\t\t\t\t   SIPE_UNUSED_PARAMETER const gchar *password) { return(NULL); }\nvoid sipe_backend_candidate_free(SIPE_UNUSED_PARAMETER struct sipe_backend_candidate *candidate) {}\ngchar *sipe_backend_candidate_get_username(SIPE_UNUSED_PARAMETER struct sipe_backend_candidate *candidate) { return(g_strdup(\"\")); }\ngchar *sipe_backend_candidate_get_password(SIPE_UNUSED_PARAMETER struct sipe_backend_candidate *candidate) { return(g_strdup(\"\")); }\ngchar *sipe_backend_candidate_get_foundation(SIPE_UNUSED_PARAMETER struct sipe_backend_candidate *candidate) { return(g_strdup(\"\")); }\ngchar *sipe_backend_candidate_get_ip(SIPE_UNUSED_PARAMETER struct sipe_backend_candidate *candidate) { return(g_strdup(\"127.0.0.1\")); }\nguint sipe_backend_candidate_get_port(SIPE_UNUSED_PARAMETER struct sipe_backend_candidate *candidate) { return(0); }\ngchar *sipe_backend_candidate_get_base_ip(SIPE_UNUSED_PARAMETER struct sipe_backend_candidate *candidate) { return(g_strdup(\"127.0.0.1\")); }\nguint sipe_backend_candidate_get_base_port(SIPE_UNUSED_PARAMETER struct sipe_backend_candidate *candidate) { return(0); }\nguint32 sipe_backend_candidate_get_priority(SIPE_UNUSED_PARAMETER struct sipe_backend_candidate *candidate) { return(0); }\nvoid sipe_backend_candidate_set_priority(SIPE_UNUSED_PARAMETER struct sipe_backend_candidate *candidate,\n\t\t\t\t\t SIPE_UNUSED_PARAMETER guint32 priority) {}\nSipeComponentType sipe_backend_candidate_get_component_type(SIPE_UNUSED_PARAMETER struct sipe_backend_candidate *candidate) { return(SIPE_COMPONENT_NONE); }\nSipeCandidateType sipe_backend_candidate_get_type(SIPE_UNUSED_PARAMETER struct sipe_backend_candidate *candidate) { return(SIPE_CANDIDATE_TYPE_ANY); }\nSipeNetworkProtocol sipe_backend_candidate_get_protocol(SIPE_UNUSED_PARAMETER struct sipe_backend_candidate *candidate) { return(SIPE_NETWORK_PROTOCOL_TCP_ACTIVE); }\nGList* sipe_backend_get_local_candidates(SIPE_UNUSED_PARAMETER struct sipe_media_call *media,\n\t\t\t\t\t SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream) { return(NULL); }\nvoid sipe_backend_media_accept(SIPE_UNUSED_PARAMETER struct sipe_backend_media *media,\n\t\t\t       SIPE_UNUSED_PARAMETER gboolean local) {}\nvoid sipe_backend_media_hangup(SIPE_UNUSED_PARAMETER struct sipe_backend_media *media,\n\t\t\t       SIPE_UNUSED_PARAMETER gboolean local) {}\nvoid sipe_backend_media_reject(SIPE_UNUSED_PARAMETER struct sipe_backend_media *media,\n\t\t\t       SIPE_UNUSED_PARAMETER gboolean local) {}\nSipeEncryptionPolicy sipe_backend_media_get_encryption_policy(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public) { return(SIPE_ENCRYPTION_POLICY_REJECTED); }\ngssize sipe_backend_media_stream_read(SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream,\n\t\t\t\t      SIPE_UNUSED_PARAMETER guint8 *buffer,\n\t\t\t\t      SIPE_UNUSED_PARAMETER gsize len) { return(-1); }\ngssize sipe_backend_media_stream_write(SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream,\n\t\t\t\t       SIPE_UNUSED_PARAMETER guint8 *buffer,\n\t\t\t\t       SIPE_UNUSED_PARAMETER gsize len) { return(-1); }\n#endif\n\n/** NETWORK ******************************************************************/\n\nstruct sipe_backend_listendata *sipe_backend_network_listen_range(SIPE_UNUSED_PARAMETER unsigned short port_min,\n\t\t\t\t\t\t\t\t  SIPE_UNUSED_PARAMETER unsigned short port_max,\n\t\t\t\t\t\t\t\t  SIPE_UNUSED_PARAMETER sipe_listen_start_cb listen_cb,\n\t\t\t\t\t\t\t\t  SIPE_UNUSED_PARAMETER sipe_client_connected_cb connect_cb,\n\t\t\t\t\t\t\t\t  SIPE_UNUSED_PARAMETER gpointer data) { return(NULL); }\nvoid sipe_backend_network_listen_cancel(SIPE_UNUSED_PARAMETER struct sipe_backend_listendata *ldata) {}\n\nstruct sipe_backend_fd *sipe_backend_fd_from_int(SIPE_UNUSED_PARAMETER int fd) { return (NULL); }\ngboolean sipe_backend_fd_is_valid(SIPE_UNUSED_PARAMETER struct sipe_backend_fd *fd) { return(FALSE); }\nvoid sipe_backend_fd_free(SIPE_UNUSED_PARAMETER struct sipe_backend_fd *fd) {}\n\n/** NOTIFICATIONS *************************************************************/\n\nvoid sipe_backend_notify_message_error(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t       SIPE_UNUSED_PARAMETER struct sipe_backend_chat_session *backend_session,\n\t\t\t\t       SIPE_UNUSED_PARAMETER const gchar *who,\n\t\t\t\t       SIPE_UNUSED_PARAMETER const gchar *message) {}\nvoid sipe_backend_notify_message_info(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t      SIPE_UNUSED_PARAMETER struct sipe_backend_chat_session *backend_session,\n\t\t\t\t      SIPE_UNUSED_PARAMETER const gchar *who,\n\t\t\t\t      SIPE_UNUSED_PARAMETER const gchar *message) {}\nvoid sipe_backend_notify_error(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t       SIPE_UNUSED_PARAMETER const gchar *title,\n\t\t\t       SIPE_UNUSED_PARAMETER const gchar *msg) {}\n\n/** USER *********************************************************************/\n\nvoid sipe_backend_user_feedback_typing(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t       SIPE_UNUSED_PARAMETER const gchar *from) {}\nvoid sipe_backend_user_feedback_typing_stop(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t\t    SIPE_UNUSED_PARAMETER const gchar *from) {}\nvoid sipe_backend_user_ask(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t   SIPE_UNUSED_PARAMETER const gchar *message,\n\t\t\t   SIPE_UNUSED_PARAMETER const gchar *accept_label,\n\t\t\t   SIPE_UNUSED_PARAMETER const gchar *decline_label,\n\t\t\t   SIPE_UNUSED_PARAMETER gpointer key) {}\nvoid sipe_backend_user_ask_choice(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,\n\t\t\t\t  SIPE_UNUSED_PARAMETER const gchar *message,\n\t\t\t\t  SIPE_UNUSED_PARAMETER GSList *choices,\n\t\t\t\t  SIPE_UNUSED_PARAMETER gpointer key) {}\nvoid sipe_backend_user_close_ask(SIPE_UNUSED_PARAMETER gpointer key) {}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/telepathy/telepathy-tls.c",
    "content": "/**\n * @file telepathy-tls.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2013-2018 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n * TLS certificate accept/reject user interaction\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <string.h>\n\n#include <glib-object.h>\n#include <telepathy-glib/dbus-properties-mixin.h>\n#include <telepathy-glib/svc-channel.h>\n#include <telepathy-glib/svc-tls.h>\n#include <telepathy-glib/telepathy-glib.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n\n#include \"telepathy-private.h\"\n\n/* TLS information required for user interaction */\nstruct _SipeTLSCertificate;\nstruct sipe_tls_info {\n\tgchar *hostname;\n\tgchar *cert_path;\n\tGPtrArray *cert_data;\n\tGStrv reference_identities;\n\tstruct _SipeTLSCertificate *certificate;\n};\n\n/* Certificate states */\n#define SIPE_TLS_CERTIFICATE_PENDING  0\n#define SIPE_TLS_CERTIFICATE_REJECTED 1\n#define SIPE_TLS_CERTIFICATE_ACCEPTED 2\n\nG_BEGIN_DECLS\n/*\n * TLS Manager class - data structures\n */\ntypedef struct _SipeTLSManagerClass {\n\tGObjectClass parent_class;\n} SipeTLSManagerClass;\n\ntypedef struct _SipeTLSManager {\n\tGObject parent;\n\n\tGObject *connection;\n\n\tGSList *channels;\n} SipeTLSManager;\n\n/*\n * TLS Manager class - type macros\n */\nstatic GType sipe_tls_manager_get_type(void);\n#define SIPE_TYPE_TLS_MANAGER \\\n\t(sipe_tls_manager_get_type())\n#define SIPE_TLS_MANAGER(obj) \\\n\t(G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_TLS_MANAGER, \\\n\t\t\t\t    SipeTLSManager))\n\n/*\n * TLS Channel class - data structures\n */\ntypedef struct _SipeTLSChannelClass {\n\tTpBaseChannelClass parent_class;\n} SipeTLSChannelClass;\n\ntypedef struct _SipeTLSChannel {\n        TpBaseChannel parent;\n\n\tconst struct sipe_tls_info *tls_info;\n\n\tGSimpleAsyncResult *result;\n} SipeTLSChannel;\n\n/*\n * TLS Channel class - type macros\n */\nstatic GType sipe_tls_channel_get_type(void) G_GNUC_CONST;\n#define SIPE_TYPE_TLS_CHANNEL \\\n\t(sipe_tls_channel_get_type())\n#define SIPE_TLS_CHANNEL(obj) \\\n\t(G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_TLS_CHANNEL, \\\n\t\t\t\t    SipeTLSChannel))\n\n/*\n * TLS Certificate class - data structures\n */\ntypedef struct _SipeTLSCertificateClass {\n\tGObjectClass parent_class;\n\n\tTpDBusPropertiesMixinClass dbus_props_class;\n} SipeTLSCertificateClass;\n\ntypedef struct _SipeTLSCertificate {\n\tGObject parent;\n\n\tconst struct sipe_tls_info *tls_info;\n\n\tguint state;\n} SipeTLSCertificate;\n\n/*\n * TLS Certificate class - type macros\n */\nstatic GType sipe_tls_certificate_get_type(void) G_GNUC_CONST;\n#define SIPE_TYPE_TLS_CERTIFICATE \\\n\t(sipe_tls_certificate_get_type())\n#define SIPE_TLS_CERTIFICATE(obj) \\\n\t(G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_TLS_CERTIFICATE, \\\n\t\t\t\t    SipeTLSCertificate))\nG_END_DECLS\n\n/*\n * TLS Manager class - type definition\n */\nstatic void channel_manager_iface_init(gpointer, gpointer);\nG_DEFINE_TYPE_WITH_CODE(SipeTLSManager,\n\t\t\tsipe_tls_manager,\n\t\t\tG_TYPE_OBJECT,\n\t\t\tG_IMPLEMENT_INTERFACE(TP_TYPE_CHANNEL_MANAGER,\n\t\t\t\t\t      channel_manager_iface_init);\n)\n\n/*\n * TLS Channel class - type definition\n */\nG_DEFINE_TYPE_WITH_CODE(SipeTLSChannel,\n\t\t\tsipe_tls_channel,\n\t\t\tTP_TYPE_BASE_CHANNEL,\n\t\t\tG_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CHANNEL_TYPE_SERVER_TLS_CONNECTION,\n\t\t\t\t\t      NULL);\n)\n\n/*\n * TLS Certificate class - type definition\n */\nstatic void tls_certificate_iface_init(gpointer, gpointer);\nG_DEFINE_TYPE_WITH_CODE (SipeTLSCertificate,\n\t\t\t sipe_tls_certificate,\n\t\t\t G_TYPE_OBJECT,\n\t\t\t G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_AUTHENTICATION_TLS_CERTIFICATE,\n\t\t\t\t\t       tls_certificate_iface_init);\n\t\t\t G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_DBUS_PROPERTIES,\n\t\t\t\t\t       tp_dbus_properties_mixin_iface_init);\n)\n\n/*\n * TLS Manager class - instance methods\n */\nstatic void sipe_tls_manager_constructed(GObject *object)\n{\n\tSipeTLSManager *self        = SIPE_TLS_MANAGER(object);\n\tvoid (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_manager_parent_class)->constructed;\n\n\tif (chain_up)\n\t\tchain_up(object);\n\n\tself->channels = NULL;\n}\n\nstatic void sipe_tls_manager_dispose(GObject *object)\n{\n\tSipeTLSManager *self        = SIPE_TLS_MANAGER(object);\n\tvoid (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_manager_parent_class)->constructed;\n\n\ttp_clear_object(&self->connection);\n\n\tif (chain_up)\n\t\tchain_up(object);\n}\n\nstatic void sipe_tls_manager_finalize(GObject *object)\n{\n\tSipeTLSManager *self        = SIPE_TLS_MANAGER(object);\n\tvoid (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_manager_parent_class)->constructed;\n\tGSList *entry               = self->channels;\n\n\t/* close channels */\n\twhile (entry) {\n\t\tGSList *next = entry->next;\n\t\t/* removes entry from list */\n\t\ttp_base_channel_close(entry->data);\n\t\tentry = next;\n\t}\n\n\ttp_clear_object(&self->connection);\n\n\tif (chain_up)\n\t\tchain_up(object);\n}\n\n\n/*\n * TLS Manager class - type implementation\n */\nstatic void sipe_tls_manager_class_init(SipeTLSManagerClass *klass)\n{\n\tGObjectClass *object_class = G_OBJECT_CLASS(klass);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeTLSManager::class_init\");\n\n\tobject_class->constructed  = sipe_tls_manager_constructed;\n\tobject_class->dispose      = sipe_tls_manager_dispose;\n\tobject_class->finalize     = sipe_tls_manager_finalize;\n}\n\nstatic void sipe_tls_manager_init(SIPE_UNUSED_PARAMETER SipeTLSManager *self)\n{\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeTLSManager::init\");\n}\n\n/*\n * TLS Manager class - interface implementation\n *\n * Channel Manager\n */\nstatic void foreach_channel(TpChannelManager *manager,\n\t\t\t    TpExportableChannelFunc func,\n\t\t\t    gpointer user_data)\n{\n\tSipeTLSManager *self = SIPE_TLS_MANAGER(manager);\n\tGSList *entry;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeTLSManager::foreach_channel\");\n\n\tfor (entry = self->channels; entry; entry = entry->next)\n\t\tfunc(entry->data, user_data);\n}\n\nstatic void channel_manager_iface_init(gpointer g_iface,\n\t\t\t\t       SIPE_UNUSED_PARAMETER gpointer iface_data)\n{\n\tTpChannelManagerIface *iface = g_iface;\n\n#define IMPLEMENT(x, y) iface->x = y\n\tIMPLEMENT(foreach_channel,            foreach_channel);\n\t/* These channels are not requestable. */\n\tIMPLEMENT(type_foreach_channel_class, NULL);\n\tIMPLEMENT(create_channel,             NULL);\n\tIMPLEMENT(request_channel,            NULL);\n\tIMPLEMENT(ensure_channel,             NULL);\n#undef IMPLEMENT\n}\n\n/* create new TLS manager object */\nSipeTLSManager *sipe_telepathy_tls_new(TpBaseConnection *connection)\n{\n\tSipeTLSManager *self = g_object_new(SIPE_TYPE_TLS_MANAGER, NULL);\n\tself->connection = g_object_ref(G_OBJECT(connection));\n\treturn(self);\n}\n\nstatic void channel_closed_cb(SipeTLSChannel *channel,\n\t\t\t      SipeTLSManager *self)\n{\n\tSIPE_DEBUG_INFO(\"channel_closed_cb: %p\", channel);\n\n\tself->channels = g_slist_remove(self->channels, channel);\n\ttp_channel_manager_emit_channel_closed_for_object(self,\n\t\t\t\t\t\t\t  TP_EXPORTABLE_CHANNEL(channel));\n\tg_object_unref(channel);\n}\n\nstatic void manager_new_channel(SipeTLSManager *self,\n\t\t\t\tSipeTLSChannel *channel)\n{\n\tself->channels = g_slist_prepend(self->channels,\n\t\t\t\t\t g_object_ref(channel));\n\n\tg_signal_connect(channel,\n\t\t\t \"closed\",\n\t\t\t G_CALLBACK(channel_closed_cb),\n\t\t\t self);\n\n\t/* emit NewChannel on the ChannelManager iface */\n\ttp_channel_manager_emit_new_channel(self,\n\t\t\t\t\t    TP_EXPORTABLE_CHANNEL(channel),\n\t\t\t\t\t    NULL);\n}\n\n/*\n * TLS Channel class - instance methods\n */\nenum {\n\tCHANNEL_PROP_SERVER_CERTIFICATE = 1,\n\tCHANNEL_PROP_HOSTNAME,\n\tCHANNEL_PROP_REFERENCE_IDENTITIES,\n\tCHANNEL_LAST_PROP\n};\n\nstatic void channel_get_property(GObject *object,\n\t\t\t\t guint property_id,\n\t\t\t\t GValue *value,\n\t\t\t\t GParamSpec *pspec)\n{\n\tSipeTLSChannel *self = SIPE_TLS_CHANNEL(object);\n\n\tswitch (property_id) {\n\tcase CHANNEL_PROP_SERVER_CERTIFICATE:\n\t\tg_value_set_boxed(value, self->tls_info->cert_path);\n\t\tbreak;\n\tcase CHANNEL_PROP_HOSTNAME:\n\t\tg_value_set_string(value, self->tls_info->hostname);\n\t\tbreak;\n\tcase CHANNEL_PROP_REFERENCE_IDENTITIES:\n\t\tg_value_set_boxed(value, self->tls_info->reference_identities);\n\t\tbreak;\n\tdefault:\n\t\tG_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);\n\t\tbreak;\n\t}\n}\n\nstatic void channel_fill_immutable_properties(TpBaseChannel *channel,\n\t\t\t\t\t      GHashTable *properties)\n{\n\tTP_BASE_CHANNEL_CLASS(sipe_tls_channel_parent_class)->fill_immutable_properties(channel,\n\t\t\t\t\t\t\t\t\t\t\t   properties);\n\ttp_dbus_properties_mixin_fill_properties_hash(G_OBJECT(channel),\n\t\t\t\t\t\t      properties,\n\t\t\t\t\t\t      TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, \"ServerCertificate\",\n\t\t\t\t\t\t      TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, \"Hostname\",\n\t\t\t\t\t\t      TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, \"ReferenceIdentities\",\n\t\t\t\t\t\t      NULL);\n}\n\nstatic gchar *channel_get_object_path_suffix(TpBaseChannel *base)\n{\n\treturn(g_strdup_printf(\"TLSChannel_%p\", base));\n}\n\nstatic void sipe_tls_channel_constructed(GObject *object)\n{\n\tvoid (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_channel_parent_class)->constructed;\n\n\tif (chain_up)\n\t\tchain_up(object);\n}\n\nstatic void sipe_tls_channel_finalize(GObject *object)\n{\n\tSipeTLSChannel *self = SIPE_TLS_CHANNEL(object);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeTLSChannel::finalize\");\n\n\tif (self->result) {\n\t\tg_simple_async_result_set_error(self->result,\n\t\t\t\t\t\tTP_ERROR,\n\t\t\t\t\t\tTP_ERROR_CANCELLED,\n\t\t\t\t\t\t\"The TLS channel is being destroyed\");\n\t\tg_simple_async_result_complete_in_idle(self->result);\n\t\tg_clear_object(&self->result);\n\t}\n\n\tG_OBJECT_CLASS(sipe_tls_channel_parent_class)->finalize(object);\n}\n\n/*\n * TLS Channel class - type implementation\n */\nstatic void sipe_tls_channel_class_init(SipeTLSChannelClass *klass)\n{\n\tstatic TpDBusPropertiesMixinPropImpl props[] = {\n\t\t{\n\t\t\t.name        = \"ServerCertificate\",\n\t\t\t.getter_data = \"server-certificate\",\n\t\t\t.setter_data = NULL\n\t\t},\n\t\t{\n\t\t\t.name        = \"Hostname\",\n\t\t\t.getter_data = \"hostname\",\n\t\t\t.setter_data = NULL\n\t\t},\n\t\t{\n\t\t\t.name        = \"ReferenceIdentities\",\n\t\t\t.getter_data = \"reference-identities\",\n\t\t\t.setter_data = NULL\n\t\t},\n\t\t{\n\t\t\t.name        = NULL\n\t\t}\n\t};\n\tGObjectClass *object_class     = G_OBJECT_CLASS(klass);\n\tTpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS(klass);\n\tGParamSpec *ps;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeTLSChannel::class_init\");\n\n\tobject_class->constructed      = sipe_tls_channel_constructed;\n\tobject_class->finalize         = sipe_tls_channel_finalize;\n\tobject_class->get_property     = channel_get_property;\n\n\tbase_class->channel_type       = TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION;\n\tbase_class->target_handle_type = TP_HANDLE_TYPE_NONE;\n\tbase_class->fill_immutable_properties = channel_fill_immutable_properties;\n\tbase_class->get_object_path_suffix    = channel_get_object_path_suffix;\n\tbase_class->interfaces         = NULL;\n\tbase_class->close              = tp_base_channel_destroyed;\n\n\tps = g_param_spec_boxed(\"server-certificate\",\n\t\t\t\t\"Server certificate path\",\n\t\t\t\t\"The object path of the server certificate.\",\n\t\t\t\tDBUS_TYPE_G_OBJECT_PATH,\n\t\t\t\tG_PARAM_READABLE | G_PARAM_STATIC_STRINGS);\n\tg_object_class_install_property(object_class,\n\t\t\t\t\tCHANNEL_PROP_SERVER_CERTIFICATE,\n\t\t\t\t\tps);\n\n\tps = g_param_spec_string(\"hostname\",\n\t\t\t\t \"The hostname to be verified\",\n\t\t\t\t \"The hostname which should be certified by the server certificate.\",\n\t\t\t\t NULL,\n\t\t\t\t G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);\n\tg_object_class_install_property(object_class,\n\t\t\t\t\tCHANNEL_PROP_HOSTNAME,\n\t\t\t\t\tps);\n\n\tps = g_param_spec_boxed(\"reference-identities\",\n\t\t\t\t\"The various identities to check the certificate against\",\n\t\t\t\t\"The server certificate identity should match one of these identities.\",\n\t\t\t\tG_TYPE_STRV,\n\t\t\t\tG_PARAM_READABLE | G_PARAM_STATIC_STRINGS);\n\tg_object_class_install_property(object_class,\n\t\t\t\t\tCHANNEL_PROP_REFERENCE_IDENTITIES,\n\t\t\t\t\tps);\n\n\ttp_dbus_properties_mixin_implement_interface(object_class,\n\t\t\t\t\t\t     TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_TLS_CONNECTION,\n\t\t\t\t\t\t     tp_dbus_properties_mixin_getter_gobject_properties,\n\t\t\t\t\t\t     NULL,\n\t\t\t\t\t\t     props);\n}\n\nstatic void sipe_tls_channel_init(SIPE_UNUSED_PARAMETER SipeTLSChannel *self)\n{\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeTLSChannel::init\");\n}\n\nstatic void certificate_accepted_cb(SIPE_UNUSED_PARAMETER SipeTLSCertificate *certificate,\n\t\t\t\t    SipeTLSChannel *self)\n{\n\tg_simple_async_result_complete(self->result);\n\tg_clear_object(&self->result);\n\ttp_base_channel_close(TP_BASE_CHANNEL(self));\n}\n\nstatic void certificate_rejected_cb(SIPE_UNUSED_PARAMETER SipeTLSCertificate *certificate,\n\t\t\t\t    SIPE_UNUSED_PARAMETER GPtrArray *rejections,\n\t\t\t\t    SipeTLSChannel *self)\n{\n\tstatic GQuark quark = 0;\n\n\tif (!quark)\n\t\tquark = g_quark_from_static_string(\"server-tls-error\");\n\n\tg_simple_async_result_set_error(self->result,\n\t\t\t\t\tquark,\n\t\t\t\t\t0,\n\t\t\t\t\t\"TLS certificate rejected\");\n\tg_simple_async_result_complete(self->result);\n\tg_clear_object(&self->result);\n\ttp_base_channel_close(TP_BASE_CHANNEL(self));\n}\n\nstatic void channel_new_certificate(GObject *connection,\n\t\t\t\t    struct sipe_tls_info *tls_info,\n\t\t\t\t    SipeTLSChannel *self,\n\t\t\t\t    GAsyncReadyCallback callback,\n\t\t\t\t    gpointer user_data)\n{\n\tstruct sipe_backend_private *telepathy_private = sipe_telepathy_connection_private(connection);\n\n\tself->tls_info = tls_info;\n\tself->result   = g_simple_async_result_new(G_OBJECT(self),\n\t\t\t\t\t\t   callback,\n\t\t\t\t\t\t   user_data,\n\t\t\t\t\t\t   channel_new_certificate);\n\n\tg_signal_connect(tls_info->certificate,\n\t\t\t \"accepted\",\n\t\t\t G_CALLBACK(certificate_accepted_cb),\n\t\t\t self);\n\n\tg_signal_connect(tls_info->certificate,\n\t\t\t \"rejected\",\n\t\t\t G_CALLBACK(certificate_rejected_cb),\n\t\t\t self);\n\n\tmanager_new_channel(telepathy_private->tls_manager, self);\n}\n\n\n\n/*\n * TLS Certificate class - instance methods\n */\nenum {\n\tCERTIFICATE_PROP_OBJECT_PATH = 1,\n\tCERTIFICATE_PROP_STATE,\n\tCERTIFICATE_PROP_TYPE,\n\tCERTIFICATE_PROP_CHAIN_DATA,\n\tCERTIFICATE_LAST_PROP\n};\n\nstatic void certificate_get_property(GObject *object,\n\t\t\t\t     guint property_id,\n\t\t\t\t     GValue *value,\n\t\t\t\t     GParamSpec *pspec)\n{\n\tSipeTLSCertificate *self = SIPE_TLS_CERTIFICATE(object);\n\n\tswitch (property_id) {\n\tcase CERTIFICATE_PROP_OBJECT_PATH:\n\t\tg_value_set_string(value, self->tls_info->cert_path);\n\t\tbreak;\n\tcase CERTIFICATE_PROP_STATE:\n\t\tg_value_set_uint(value, self->state);\n\t\tbreak;\n\tcase CERTIFICATE_PROP_TYPE:\n\t\tg_value_set_string(value, \"x509\");\n\t\tbreak;\n\tcase CERTIFICATE_PROP_CHAIN_DATA:\n\t\tg_value_set_boxed(value, self->tls_info->cert_data);\n\t\tbreak;\n\tdefault:\n\t\tG_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);\n\t\tbreak;\n\t}\n}\n\nstatic void sipe_tls_certificate_constructed(GObject *object)\n{\n\tSipeTLSCertificate *self    = SIPE_TLS_CERTIFICATE(object);\n\tvoid (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_tls_certificate_parent_class)->constructed;\n\n\tif (chain_up)\n\t\tchain_up(object);\n\n\tself->state = SIPE_TLS_CERTIFICATE_PENDING;\n}\n\nstatic void sipe_tls_certificate_finalize(GObject *object)\n{\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeTLSCertificate::finalize\");\n\n\tG_OBJECT_CLASS(sipe_tls_certificate_parent_class)->finalize(object);\n}\n\n/*\n * TLS Certificate class - type implementation\n */\nstatic void sipe_tls_certificate_class_init(SipeTLSCertificateClass *klass)\n{\n\tstatic TpDBusPropertiesMixinPropImpl props[] = {\n\t\t{\n\t\t\t.name        = \"State\",\n\t\t\t.getter_data = \"state\",\n\t\t\t.setter_data = NULL\n\t\t},\n\t\t{\n\t\t\t.name        = \"CertificateType\",\n\t\t\t.getter_data = \"certificate-type\",\n\t\t\t.setter_data = NULL\n\t\t},\n\t\t{\n\t\t\t.name        = \"CertificateChainData\",\n\t\t\t.getter_data = \"certificate-chain-data\",\n\t\t\t.setter_data = NULL\n\t\t},\n\t\t{\n\t\t\t.name        = NULL\n\t\t}\n\t};\n\tstatic TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {\n\t\t{\n\t\t\t.name   = TP_IFACE_AUTHENTICATION_TLS_CERTIFICATE,\n\t\t\t.getter = tp_dbus_properties_mixin_getter_gobject_properties,\n\t\t\t.setter = NULL,\n\t\t\t.props  = props\n\t\t},\n\t\t{\n\t\t\t.name   = NULL\n\t\t}\n\t};\n\tGObjectClass *object_class = G_OBJECT_CLASS(klass);\n\tGParamSpec *ps;\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeTLSCertificate::class_init\");\n\n\tklass->dbus_props_class.interfaces = prop_interfaces;\n\n\tobject_class->constructed      = sipe_tls_certificate_constructed;\n\tobject_class->finalize         = sipe_tls_certificate_finalize;\n\tobject_class->get_property     = certificate_get_property;\n\n\tps = g_param_spec_string(\"object-path\",\n\t\t\t\t \"D-Bus object path\",\n\t\t\t\t \"The D-Bus object path used for this object on the bus.\",\n\t\t\t\t NULL,\n\t\t\t\t G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);\n\tg_object_class_install_property(object_class,\n\t\t\t\t\tCERTIFICATE_PROP_OBJECT_PATH,\n\t\t\t\t\tps);\n\n\tps = g_param_spec_uint(\"state\",\n\t\t\t       \"State of this certificate\",\n\t\t\t       \"The state of this TLS certificate.\",\n\t\t\t       SIPE_TLS_CERTIFICATE_PENDING,\n\t\t\t       SIPE_TLS_CERTIFICATE_ACCEPTED,\n\t\t\t       SIPE_TLS_CERTIFICATE_PENDING,\n\t\t\t       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);\n\tg_object_class_install_property(object_class,\n\t\t\t\t\tCERTIFICATE_PROP_STATE,\n\t\t\t\t\tps);\n\n\tps = g_param_spec_string(\"certificate-type\",\n\t\t\t\t \"The certificate type\",\n\t\t\t\t \"The type of this certificate.\",\n\t\t\t\t NULL,\n\t\t\t\t G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);\n\tg_object_class_install_property(object_class,\n\t\t\t\t\tCERTIFICATE_PROP_TYPE,\n\t\t\t\t\tps);\n\n\tps = g_param_spec_boxed(\"certificate-chain-data\",\n\t\t\t\t\"The certificate chain data\",\n\t\t\t\t\"The raw DER-encoded trust chain of this certificate.\",\n\t\t\t\tTP_ARRAY_TYPE_UCHAR_ARRAY_LIST,\n\t\t\t\tG_PARAM_READABLE | G_PARAM_STATIC_STRINGS);\n\tg_object_class_install_property(object_class,\n\t\t\t\t\tCERTIFICATE_PROP_CHAIN_DATA, ps);\n\n\ttp_dbus_properties_mixin_class_init(object_class,\n\t\t\t\t\t    G_STRUCT_OFFSET(SipeTLSCertificateClass, dbus_props_class));\n}\n\nstatic void sipe_tls_certificate_init(SIPE_UNUSED_PARAMETER SipeTLSCertificate *self)\n{\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeTLSCertificate::init\");\n}\n\n/*\n * TLS Certificate class - interface implementation\n */\nstatic void tls_certificate_accept(TpSvcAuthenticationTLSCertificate *certificate,\n\t\t\t\t   DBusGMethodInvocation *context)\n{\n\tSipeTLSCertificate *self = SIPE_TLS_CERTIFICATE(certificate);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeTLSCertificate::accept\");\n\n\tif (self->state != SIPE_TLS_CERTIFICATE_PENDING) {\n\t\tGError error = {\n\t\t\tTP_ERROR,\n\t\t\tTP_ERROR_INVALID_ARGUMENT,\n\t\t\t\"Calling Accept() on a certificate with state != PENDING \"\n\t\t\t\"doesn't make sense.\"\n\t\t\t};\n\n\t\tdbus_g_method_return_error(context, &error);\n\t\treturn;\n\t}\n\n\tself->state = SIPE_TLS_CERTIFICATE_ACCEPTED;\n\ttp_svc_authentication_tls_certificate_emit_accepted(self);\n\n\ttp_svc_authentication_tls_certificate_return_from_accept(context);\n}\n\nstatic void tls_certificate_reject(TpSvcAuthenticationTLSCertificate *certificate,\n\t\t\t\t   const GPtrArray *rejections,\n\t\t\t\t   DBusGMethodInvocation *context)\n{\n\tSipeTLSCertificate *self = SIPE_TLS_CERTIFICATE(certificate);\n\n\tSIPE_DEBUG_INFO_NOFORMAT(\"SipeTLSCertificate::reject\");\n\n\tif (self->state != SIPE_TLS_CERTIFICATE_PENDING) {\n\t\tGError error = {\n\t\t\tTP_ERROR,\n\t\t\tTP_ERROR_INVALID_ARGUMENT,\n\t\t\t\"Calling Reject() on a certificate with state != PENDING \"\n\t\t\t\"doesn't make sense.\"\n\t\t};\n\n\t\tdbus_g_method_return_error(context, &error);\n\t\treturn;\n\t}\n\n\tself->state = SIPE_TLS_CERTIFICATE_REJECTED;\n\n\ttp_svc_authentication_tls_certificate_emit_rejected(self, rejections);\n\n\ttp_svc_authentication_tls_certificate_return_from_reject(context);\n}\n\nstatic void tls_certificate_iface_init(gpointer g_iface,\n\t\t\t\t       SIPE_UNUSED_PARAMETER gpointer iface_data)\n{\n\tTpSvcAuthenticationTLSCertificateClass *klass = g_iface;\n\n#define IMPLEMENT(x) \\\n\ttp_svc_authentication_tls_certificate_implement_##x(\t\\\n\t\tklass, tls_certificate_##x)\n\tIMPLEMENT(accept);\n\tIMPLEMENT(reject);\n#undef IMPLEMENT\n}\n\nstatic void append_certificate_der(GPtrArray *certificates,\n\t\t\t\t   GByteArray *der)\n{\n\tGArray *array = g_array_sized_new(FALSE,\n\t\t\t\t\t  FALSE,\n\t\t\t\t\t  sizeof(guchar),\n\t\t\t\t\t  der->len);\n\tarray = g_array_append_vals(array, der->data, der->len);\n\tg_byte_array_unref(der);\n\n\tg_ptr_array_add(certificates, array);\n}\n\nstruct sipe_tls_info *sipe_telepathy_tls_info_new(const gchar *hostname,\n\t\t\t\t\t\t  GTlsCertificate *certificate)\n{\n\tstruct sipe_tls_info *tls_info = NULL;\n\tGByteArray *der = NULL;\n\n\tg_object_get(certificate, \"certificate\", &der, NULL);\n\tif (der) {\n\t\tGPtrArray *identities = g_ptr_array_new();\n\n\t\ttls_info = g_new0(struct sipe_tls_info, 1);\n\t\ttls_info->hostname             = g_strdup(hostname);\n\n\t\t/* build GStrv of identies */\n\t\tg_ptr_array_add(identities, g_strdup(hostname));\n\t\tg_ptr_array_add(identities, NULL);\n\t\ttls_info->reference_identities = (GStrv) g_ptr_array_free(identities,\n\t\t\t\t\t\t\t\t\t  FALSE);\n\n\t\ttls_info->cert_data = g_ptr_array_new_full(1,\n\t\t\t\t\t\t\t   (GDestroyNotify) g_array_unref);\n\t\t/* unrefs \"der\" */\n\t\tappend_certificate_der(tls_info->cert_data, der);\n\n\t\t/* will be unref'd in loop */\n\t\tg_object_ref(certificate);\n\t\twhile (certificate) {\n\t\t\tGTlsCertificate *issuer = NULL;\n\n\t\t\tg_object_get(certificate, \"issuer\", &issuer, NULL);\n\t\t\tg_object_unref(certificate);\n\n\t\t\t/* add issuer certificate */\n\t\t\tif (issuer) {\n\t\t\t\tg_object_get(certificate, \"certificate\", &der, NULL);\n\t\t\t\t/* unrefs \"der\" */\n\t\t\t\tif (der)\n\t\t\t\t\tappend_certificate_der(tls_info->cert_data, der);\n\t\t\t}\n\n\t\t\t/* walk up the chain */\n\t\t\tcertificate = issuer;\n\t\t}\n\t}\n\n\treturn(tls_info);\n}\n\nvoid sipe_telepathy_tls_info_free(struct sipe_tls_info *tls_info)\n{\n\tg_object_unref(tls_info->certificate);\n\tg_free(tls_info->hostname);\n\tg_free(tls_info->cert_path);\n\tg_ptr_array_unref(tls_info->cert_data);\n\tg_strfreev(tls_info->reference_identities);\n\tg_free(tls_info);\n}\n\n/* create new tls certificate object */\nvoid sipe_telepathy_tls_verify_async(GObject *connection,\n\t\t\t\t     struct sipe_tls_info *tls_info,\n\t\t\t\t     GAsyncReadyCallback callback,\n\t\t\t\t     gpointer user_data)\n{\n\t/* property \"connection\" required by TpBaseChannel */\n\tSipeTLSChannel *channel = g_object_new(SIPE_TYPE_TLS_CHANNEL,\n\t\t\t\t\t       \"connection\", connection,\n\t\t\t\t\t       NULL);\n\tTpBaseChannel *base = TP_BASE_CHANNEL(channel);\n\tSipeTLSCertificate *certificate = g_object_new(SIPE_TYPE_TLS_CERTIFICATE,\n\t\t\t\t\t\t       NULL);\n\tTpDBusDaemon *daemon = tp_dbus_daemon_dup(NULL);\n\n\ttls_info->certificate = certificate;\n\tcertificate->tls_info = tls_info;\n\n\ttp_base_channel_register(base);\n\ttls_info->cert_path = g_strdup_printf(\"%s/TLSCertificateObject\",\n\t\t\t\t\t      tp_base_channel_get_object_path(base));\n\n\t/* register the certificate on the bus */\n\ttp_dbus_daemon_register_object(daemon,\n\t\t\t\t       tls_info->cert_path,\n\t\t\t\t       certificate);\n\tg_object_unref(daemon);\n\n\tchannel_new_certificate(connection,\n\t\t\t\ttls_info,\n\t\t\t\tchannel,\n\t\t\t\tcallback,\n\t\t\t\tuser_data);\n}\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  },
  {
    "path": "src/telepathy/telepathy-transport.c",
    "content": "/**\n * @file telepathy-transport.c\n *\n * pidgin-sipe\n *\n * Copyright (C) 2012-2017 SIPE Project <http://sipe.sourceforge.net/>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <string.h>\n\n#include <glib.h>\n#include <gio/gio.h>\n\n#include \"sipe-backend.h\"\n#include \"sipe-common.h\"\n#include \"sipe-core.h\"\n#include \"sipe-nls.h\"\n\n#include \"telepathy-private.h\"\n\nstruct sipe_transport_telepathy {\n\t/* public part shared with core */\n\tstruct sipe_transport_connection public;\n\n\t/* telepathy private part */\n\ttransport_connected_cb *connected;\n\ttransport_input_cb *input;\n\ttransport_error_cb *error;\n\tgchar *hostname;\n\tstruct sipe_tls_info *tls_info;\n\tstruct sipe_backend_private *private;\n\tGCancellable *cancel;\n\tGSocketConnection *socket;\n\tGInputStream *istream;\n\tGOutputStream *ostream;\n\tGSList *buffers; /* != NULL -> write operation in progress */\n\tguint port;\n\tgboolean do_flush;\n};\n\n#define TELEPATHY_TRANSPORT ((struct sipe_transport_telepathy *) conn)\n#define SIPE_TRANSPORT_CONNECTION ((struct sipe_transport_connection *) transport)\n\n#define BUFFER_SIZE_INCREMENT 4096\n\nstatic void read_completed(GObject *stream,\n\t\t\t   GAsyncResult *result,\n\t\t\t   gpointer data)\n{\n\tstruct sipe_transport_telepathy *transport = data;\n\tstruct sipe_transport_connection *conn = SIPE_TRANSPORT_CONNECTION;\n\n\tdo {\n\t\tif (conn->buffer_length < conn->buffer_used + BUFFER_SIZE_INCREMENT) {\n\t\t\tconn->buffer_length += BUFFER_SIZE_INCREMENT;\n\t\t\tconn->buffer = g_realloc(conn->buffer, conn->buffer_length);\n\t\t\tSIPE_DEBUG_INFO(\"read_completed: new buffer length %\" G_GSIZE_FORMAT,\n\t\t\t\t\tconn->buffer_length);\n\t\t}\n\n\t\t/* callback result is valid */\n\t\tif (result) {\n\t\t\tGError *error = NULL;\n\t\t\tgssize len    = g_input_stream_read_finish(G_INPUT_STREAM(stream),\n\t\t\t\t\t\t\t\t   result,\n\t\t\t\t\t\t\t\t   &error);\n\n\t\t\tif (len < 0) {\n\t\t\t\tconst gchar *msg = error ? error->message : \"UNKNOWN\";\n\t\t\t\tSIPE_DEBUG_ERROR(\"read_completed: error: %s\", msg);\n\t\t\t\tif (transport->error)\n\t\t\t\t\ttransport->error(conn, msg);\n\t\t\t\tif (error)\n\t\t\t\t\tg_error_free(error);\n\t\t\t\treturn;\n\t\t\t} else if (len == 0) {\n\t\t\t\tSIPE_DEBUG_ERROR_NOFORMAT(\"read_completed: server has disconnected\");\n\t\t\t\ttransport->error(conn, _(\"Server has disconnected\"));\n\t\t\t\treturn;\n\t\t\t} else if (transport->do_flush) {\n\t\t\t\t/* read completed while disconnected transport is flushing */\n\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"read_completed: ignored during flushing\");\n\t\t\t\treturn;\n\t\t\t} else if (g_cancellable_is_cancelled(transport->cancel)) {\n\t\t\t\t/* read completed when transport was disconnected */\n\t\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"read_completed: cancelled\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t/* Forward data to core */\n\t\t\tconn->buffer_used               += len;\n\t\t\tconn->buffer[conn->buffer_used]  = '\\0';\n\t\t\ttransport->input(conn);\n\n\t\t\t/* we processed the result */\n\t\t\tresult = NULL;\n\t\t}\n\n\t\t/* buffer too short? */\n\t} while (conn->buffer_length - conn->buffer_used - 1 == 0);\n\n\t/* setup next read */\n\tg_input_stream_read_async(G_INPUT_STREAM(stream),\n\t\t\t\t  conn->buffer + conn->buffer_used,\n\t\t\t\t  conn->buffer_length - conn->buffer_used - 1,\n\t\t\t\t  G_PRIORITY_DEFAULT,\n\t\t\t\t  transport->cancel,\n\t\t\t\t  read_completed,\n\t\t\t\t  transport);\n}\n\nstatic gboolean internal_connect(gpointer data);\nstatic void certificate_result(SIPE_UNUSED_PARAMETER GObject *unused,\n\t\t\t       GAsyncResult *result,\n\t\t\t       gpointer data)\n{\n\tstruct sipe_transport_telepathy *transport = data;\n\tGError *error = NULL;\n\n\tg_simple_async_result_propagate_error(G_SIMPLE_ASYNC_RESULT(result),\n\t\t\t\t\t      &error);\n\tif (error) {\n\t\tSIPE_DEBUG_INFO(\"certificate_result: %s\", error->message);\n\t\tif (transport->error)\n\t\t\ttransport->error(SIPE_TRANSPORT_CONNECTION,\n\t\t\t\t\t error->message);\n\t\tg_error_free(error);\n\t} else {\n\t\tSIPE_DEBUG_INFO(\"certificate_result: trigger reconnect %p\", transport);\n\t\tg_idle_add(internal_connect, transport);\n\t}\n}\n\nstatic void socket_connected(GObject *client,\n\t\t\t     GAsyncResult *result,\n\t\t\t     gpointer data)\n{\n\tstruct sipe_transport_telepathy *transport = data;\n\tGError *error = NULL;\n\n\ttransport->socket = g_socket_client_connect_finish(G_SOCKET_CLIENT(client),\n\t\t\t\t\t\t\t   result,\n\t\t\t\t\t\t\t   &error);\n\n\tif (transport->socket == NULL) {\n\t\tif (transport->tls_info) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"socket_connected: need to wait for user interaction\");\n\t\t\tsipe_telepathy_tls_verify_async(G_OBJECT(transport->private->connection),\n\t\t\t\t\t\t\ttransport->tls_info,\n\t\t\t\t\t\t\tcertificate_result,\n\t\t\t\t\t\t\ttransport);\n\t\t} else {\n\t\t\tconst gchar *msg = error ? error->message : \"UNKNOWN\";\n\t\t\tSIPE_DEBUG_ERROR(\"socket_connected: failed: %s\", msg);\n\t\t\tif (transport->error)\n\t\t\t\ttransport->error(SIPE_TRANSPORT_CONNECTION, msg);\n\t\t\tif (error)\n\t\t\t\tg_error_free(error);\n\t\t}\n\t} else if (g_cancellable_is_cancelled(transport->cancel)) {\n\t\t/* connect already succeeded when transport was disconnected */\n\t\tg_object_unref(transport->socket);\n\t\ttransport->socket = NULL;\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"socket_connected: succeeded, but cancelled\");\n\t} else {\n\t\tGSocketAddress *saddr = g_socket_connection_get_local_address(transport->socket,\n\t\t\t\t\t\t\t\t\t      &error);\n\n\t\tif (saddr) {\n\t\t\tSIPE_DEBUG_INFO_NOFORMAT(\"socket_connected: success\");\n\n\t\t\ttransport->public.client_port = g_inet_socket_address_get_port(G_INET_SOCKET_ADDRESS(saddr));\n\t\t\tg_object_unref(saddr);\n\n\t\t\ttransport->istream = g_io_stream_get_input_stream(G_IO_STREAM(transport->socket));\n\t\t\ttransport->ostream = g_io_stream_get_output_stream(G_IO_STREAM(transport->socket));\n\n\t\t\t/* the first connection is always to the server */\n\t\t\tif (transport->private->transport == NULL)\n\t\t\t\ttransport->private->transport = transport;\n\n\t\t\t/* this sets up the async read handler */\n\t\t\tread_completed(G_OBJECT(transport->istream), NULL, transport);\n\t\t\ttransport->connected(SIPE_TRANSPORT_CONNECTION);\n\n\t\t} else {\n\t\t\tg_object_unref(transport->socket);\n\t\t\ttransport->socket = NULL;\n\t\t\tSIPE_DEBUG_ERROR(\"socket_connected: failed: %s\", error->message);\n\t\t\ttransport->error(SIPE_TRANSPORT_CONNECTION, error->message);\n\t\t\tg_error_free(error);\n\t\t}\n\t}\n}\n\nstatic gboolean accept_certificate_signal(SIPE_UNUSED_PARAMETER GTlsConnection *tls,\n\t\t\t\t\t  GTlsCertificate *peer_cert,\n\t\t\t\t\t  SIPE_UNUSED_PARAMETER GTlsCertificateFlags errors,\n\t\t\t\t\t  gpointer user_data)\n{\n\tstruct sipe_transport_telepathy *transport = user_data;\n\n\tSIPE_DEBUG_INFO(\"accept_certificate_signal: %p\", transport);\n\n\t/* second connection attempt after feedback from user? */\n\tif (transport->tls_info) {\n\t\t/* user accepted certificate */\n\t\tsipe_telepathy_tls_info_free(transport->tls_info);\n\t\ttransport->tls_info = NULL;\n\t\treturn(TRUE);\n\t} else {\n\t\t/* retry after user accepted certificate */\n\t\ttransport->tls_info = sipe_telepathy_tls_info_new(transport->hostname,\n\t\t\t\t\t\t\t\t  peer_cert);\n\t\treturn(FALSE);\n\t}\n}\n\nstatic void tls_handshake_starts(SIPE_UNUSED_PARAMETER GSocketClient *client,\n\t\t\t\t GSocketClientEvent event,\n\t\t\t\t SIPE_UNUSED_PARAMETER GSocketConnectable *connectable,\n\t\t\t\t GIOStream *connection,\n\t\t\t\t gpointer user_data)\n{\n\tif (event == G_SOCKET_CLIENT_TLS_HANDSHAKING) {\n\t\tSIPE_DEBUG_INFO(\"tls_handshake_starts: %p\", connection);\n\t\tg_signal_connect(connection, /* is a GTlsConnection */\n\t\t\t\t \"accept-certificate\",\n\t\t\t\t G_CALLBACK(accept_certificate_signal),\n\t\t\t\t user_data);\n\t}\n}\n\nstatic gboolean internal_connect(gpointer data)\n{\n\tstruct sipe_transport_telepathy *transport = data;\n\tGSocketClient *client = g_socket_client_new();\n\n\tSIPE_DEBUG_INFO(\"internal_connect - hostname: %s port: %d\",\n\t\t\ttransport->hostname, transport->port);\n\n\t/* request TLS connection */\n\tif (transport->public.type == SIPE_TRANSPORT_TLS) {\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"using TLS\");\n\t\tg_socket_client_set_tls(client, TRUE);\n\t\tg_signal_connect(client,\n\t\t\t\t \"event\",\n\t\t\t\t G_CALLBACK(tls_handshake_starts),\n\t\t\t\t transport);\n\t} else\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"using TCP\");\n\n\tg_socket_client_connect_async(client,\n\t\t\t\t      g_network_address_new(transport->hostname,\n\t\t\t\t\t\t\t    transport->port),\n\t\t\t\t      transport->cancel,\n\t\t\t\t      socket_connected,\n\t\t\t\t      transport);\n\tg_object_unref(client);\n\n\treturn(FALSE);\n}\n\nstruct sipe_transport_connection *sipe_backend_transport_connect(struct sipe_core_public *sipe_public,\n\t\t\t\t\t\t\t\t const sipe_connect_setup *setup)\n{\n\tstruct sipe_transport_telepathy *transport = g_new0(struct sipe_transport_telepathy, 1);\n\n\ttransport->public.type      = setup->type;\n\ttransport->public.user_data = setup->user_data;\n\ttransport->connected        = setup->connected;\n\ttransport->input            = setup->input;\n\ttransport->error            = setup->error;\n\ttransport->hostname         = g_strdup(setup->server_name);\n\ttransport->tls_info         = NULL;\n\ttransport->private          = sipe_public->backend_private;\n\ttransport->cancel           = g_cancellable_new();\n\ttransport->buffers          = NULL;\n\ttransport->port             = setup->server_port;\n\ttransport->do_flush         = FALSE;\n\n\tif ((setup->type == SIPE_TRANSPORT_TLS) ||\n\t    (setup->type == SIPE_TRANSPORT_TCP)) {\n\n\t\tinternal_connect(transport);\n\t\treturn(SIPE_TRANSPORT_CONNECTION);\n\n\t} else {\n\t\tsetup->error(SIPE_TRANSPORT_CONNECTION,\n\t\t\t     \"This should not happen...\");\n\t\tsipe_backend_transport_disconnect(SIPE_TRANSPORT_CONNECTION);\n\t\treturn(NULL);\n\t}\n}\n\nstatic gboolean free_transport(gpointer data)\n{\n\tstruct sipe_transport_telepathy *transport = data;\n\tGSList *entry;\n\n\tSIPE_DEBUG_INFO(\"free_transport %p\", transport);\n\n\tif (transport->tls_info)\n\t\tsipe_telepathy_tls_info_free(transport->tls_info);\n\tg_free(transport->hostname);\n\n\t/* free unflushed buffers */\n\tfor (entry = transport->buffers; entry; entry = entry->next)\n\t\tg_free(entry->data);\n\tg_slist_free(transport->buffers);\n\n\tif (transport->cancel)\n\t\tg_object_unref(transport->cancel);\n\n\tg_free(transport);\n\n\treturn(FALSE);\n}\n\nstatic void close_completed(GObject *stream,\n\t\t\t    GAsyncResult *result,\n\t\t\t    gpointer data)\n{\n\tstruct sipe_transport_telepathy *transport = data;\n\tSIPE_DEBUG_INFO(\"close_completed: transport %p\", data);\n\tg_io_stream_close_finish(G_IO_STREAM(stream), result, NULL);\n\tg_idle_add(free_transport, transport);\n}\n\nstatic void do_close(struct sipe_transport_telepathy *transport)\n{\n\tSIPE_DEBUG_INFO(\"do_close: %p\", transport);\n\n\t/* cancel outstanding asynchronous operations */\n\ttransport->do_flush = FALSE;\n\tg_cancellable_cancel(transport->cancel);\n\tg_io_stream_close_async(G_IO_STREAM(transport->socket),\n\t\t\t\tG_PRIORITY_DEFAULT,\n\t\t\t\tNULL,\n\t\t\t\tclose_completed,\n\t\t\t\ttransport);\n}\n\nvoid sipe_backend_transport_disconnect(struct sipe_transport_connection *conn)\n{\n\tstruct sipe_transport_telepathy *transport = TELEPATHY_TRANSPORT;\n\n\tif (!transport) return;\n\n\tSIPE_DEBUG_INFO(\"sipe_backend_transport_disconnect: %p\", transport);\n\n\t/* error callback is invalid now, do no longer call! */\n\ttransport->error = NULL;\n\n\t/* dropping connection to the server? */\n\tif (transport->private->transport == transport)\n\t\ttransport->private->transport = NULL;\n\n\t/* already connected? */\n\tif (transport->socket) {\n\n\t\t/* flush required? */\n\t\tif (transport->do_flush && transport->buffers)\n\t\t\tSIPE_DEBUG_INFO(\"sipe_backend_transport_disconnect: %p needs flushing\",\n\t\t\t\t\ttransport);\n\t\telse\n\t\t\tdo_close(transport);\n\n\t} else {\n\t\t/* cancel outstanding connect operation */\n\t\tif (transport->cancel)\n\t\t\tg_cancellable_cancel(transport->cancel);\n\n\t\t/* queue transport to be deleted */\n\t\tg_idle_add(free_transport, transport);\n\t}\n}\n\ngchar *sipe_backend_transport_ip_address(struct sipe_transport_connection *conn)\n{\n\tstruct sipe_transport_telepathy *transport = TELEPATHY_TRANSPORT;\n\tgchar *ipstr = NULL;\n\n\tif (transport && transport->socket) {\n\t\tGSocketAddress *saddr = g_socket_connection_get_local_address(transport->socket,\n\t\t\t\t\t\t\t\t\t      NULL);\n\n\t\tif (saddr) {\n\t\t\tGInetAddress *iaddr = g_inet_socket_address_get_address(G_INET_SOCKET_ADDRESS(saddr));\n\n\t\t\tif (iaddr) {\n\t\t\t\tipstr = g_inet_address_to_string(iaddr);\n\t\t\t\tSIPE_DEBUG_INFO(\"sipe_backend_transport_ip_address: %s\", ipstr);\n\t\t\t}\n\t\t\tg_object_unref(saddr);\n\t\t}\n\t}\n\n\treturn(ipstr ? ipstr : g_strdup(\"0.0.0.0\"));\n}\n\nstatic void do_write(struct sipe_transport_telepathy *transport);\nstatic void write_completed(GObject *stream,\n\t\t\t    GAsyncResult *result,\n\t\t\t    gpointer data)\n{\n\tstruct sipe_transport_telepathy *transport = data;\n\tgchar                           *buffer;\n\tGError                          *error     = NULL;\n\tgssize written = g_output_stream_write_finish(G_OUTPUT_STREAM(stream),\n\t\t\t\t\t\t      result,\n\t\t\t\t\t\t      &error);\n\n\t/* free the buffer that has just been written. */\n\tbuffer = transport->buffers->data;\n\ttransport->buffers = g_slist_remove(transport->buffers, buffer);\n\tg_free(buffer);\n\n\tif ((written < 0) || error) {\n\t\tconst gchar *msg = error ? error->message : \"UNKNOWN\";\n\t\tSIPE_DEBUG_ERROR(\"write_completed: error: %s\", msg);\n\t\tif (transport->error)\n\t\t\ttransport->error(SIPE_TRANSPORT_CONNECTION, msg);\n\t\tif (error)\n\t\t\tg_error_free(error);\n\n\t\t/* error during flush: give up and close transport */\n\t\tif (transport->do_flush)\n\t\t\tdo_close(transport);\n\n\t} else if (g_cancellable_is_cancelled(transport->cancel)) {\n\t\t/* write completed when transport was disconnected */\n\t\tSIPE_DEBUG_INFO_NOFORMAT(\"write_completed: cancelled\");\n\t} else {\n\t\t/* more to write? */\n\t\tif (transport->buffers) {\n\t\t\tdo_write(transport);\n\t\t/* flush completed? */\n\t\t} else if (transport->do_flush) {\n\t\t\tdo_close(transport);\n\t\t}\n\t}\n}\n\nstatic void do_write(struct sipe_transport_telepathy *transport)\n{\n\tg_output_stream_write_async(transport->ostream,\n\t\t\t\t    transport->buffers->data,\n\t\t\t\t    strlen(transport->buffers->data),\n\t\t\t\t    G_PRIORITY_DEFAULT,\n\t\t\t\t    transport->cancel,\n\t\t\t\t    write_completed,\n\t\t\t\t    transport);\n}\n\nvoid sipe_backend_transport_message(struct sipe_transport_connection *conn,\n\t\t\t\t    const gchar *buffer)\n{\n\tstruct sipe_transport_telepathy *transport = TELEPATHY_TRANSPORT;\n\tgboolean can_write = (transport->buffers == NULL);\n\n\ttransport->buffers = g_slist_append(transport->buffers, g_strdup(buffer));\n\n\tif (can_write)\n\t\tdo_write(transport);\n}\n\nvoid sipe_backend_transport_flush(struct sipe_transport_connection *conn)\n{\n\tstruct sipe_transport_telepathy *transport = TELEPATHY_TRANSPORT;\n\ttransport->do_flush = TRUE;\n}\n\n\n/*\n  Local Variables:\n  mode: c\n  c-file-style: \"bsd\"\n  indent-tabs-mode: t\n  tab-width: 8\n  End:\n*/\n"
  }
]